1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35: #include <sys/cdefs.h>
36: #ifndef lint
37: __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
38: The Regents of the University of California. All rights reserved.\n");
39: #endif
40:
41: #ifndef lint
42: #if 0
43: static char sccsid[] = "@(#)factor.c 8.4 (Berkeley) 5/4/95";
44: #else
45: __RCSID("$NetBSD: factor.c,v 1.15 2004/02/08 11:47:36 jsm Exp $");
46: #endif
47: #endif
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68: #include <ctype.h>
69: #include <err.h>
70: #include <errno.h>
71: #include <limits.h>
72: #include <stdio.h>
73: #include <stdlib.h>
74: #include <unistd.h>
75:
76: #ifdef HAVE_OPENSSL
77: #include <openssl/bn.h>
78: #else
79: typedef long BIGNUM;
80: typedef u_long BN_ULONG;
81: int BN_dec2bn(BIGNUM **a, const char *str);
82: #define BN_new() ((BIGNUM *)calloc(sizeof(BIGNUM), 1))
83: #define BN_is_zero(v) (*(v) == 0)
84: #define BN_is_one(v) (*(v) == 1)
85: #define BN_new() ((BIGNUM *)calloc(sizeof(BIGNUM), 1))
86: #define BN_is_zero(v) (*(v) == 0)
87: #define BN_is_one(v) (*(v) == 1)
88: #define BN_mod_word(a, b) (*(a) % (b))
89: #endif
90:
91: #include "primes.h"
92:
93:
94:
95:
96:
97:
98:
99: extern const ubig prime[];
100: extern const ubig *pr_limit;
101:
102: #define PRIME_CHECKS 5
103:
104: #ifdef HAVE_OPENSSL
105: BN_CTX *ctx;
106: #endif
107:
108: int main(int, char *[]);
109: void pr_fact(BIGNUM *);
110: void BN_print_dec_fp(FILE *, const BIGNUM *);
111: void usage(void) __attribute__((__noreturn__));
112: #ifdef HAVE_OPENSSL
113: void pollard_pminus1(BIGNUM *);
114: #else
115: char *BN_bn2dec(const BIGNUM *);
116: BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
117: #endif
118:
119:
120: #ifndef HAVE_OPENSSL
121: int
122: BN_dec2bn(BIGNUM **a, const char *str)
123: {
124: char *p;
125:
126: errno = 0;
127: **a = strtoul(str, &p, 10);
128: if (errno)
129: err(1, "%s", str);
130: return (*p == '\n' || *p == '\0');
131: }
132: #endif
133:
134: int
135: main(int argc, char *argv[])
136: {
137: BIGNUM *val;
138: int ch;
139: char *p, buf[LINE_MAX];
140:
141: #ifdef HAVE_OPENSSL
142: ctx = BN_CTX_new();
143: #endif
144: val = BN_new();
145: if (val == NULL)
146: errx(1, "can't initialise bignum");
147:
148:
149: setregid(getgid(), getgid());
150:
151: while ((ch = getopt(argc, argv, "")) != -1)
152: switch (ch) {
153: case '?':
154: default:
155: usage();
156: }
157: argc -= optind;
158: argv += optind;
159:
160:
161: if (argc == 0)
162: for (;;) {
163: if (fgets(buf, sizeof(buf), stdin) == NULL) {
164: if (ferror(stdin))
165: err(1, "stdin");
166: exit (0);
167: }
168: for (p = buf; isblank(*p); ++p);
169: if (*p == '\n' || *p == '\0')
170: continue;
171: if (*p == '-')
172: errx(1, "negative numbers aren't permitted.");
173: if (BN_dec2bn(&val, buf) == 0)
174: errx(1, "%s: illegal numeric format.", argv[0]);
175: pr_fact(val);
176: }
177:
178: else
179: for (; *argv != NULL; ++argv) {
180: if (argv[0][0] == '-')
181: errx(1, "negative numbers aren't permitted.");
182: if (BN_dec2bn(&val, argv[0]) == 0)
183: errx(1, "%s: illegal numeric format.", argv[0]);
184: pr_fact(val);
185: }
186: exit(0);
187: }
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202: void
203: pr_fact(BIGNUM *val)
204: {
205: const ubig *fact;
206:
207:
208: if (BN_is_zero(val))
209: exit(0);
210: if (BN_is_one(val)) {
211: printf("1: 1\n");
212: return;
213: }
214:
215:
216:
217: BN_print_dec_fp(stdout, val);
218: putchar(':');
219: for (fact = &prime[0]; !BN_is_one(val); ++fact) {
220:
221: do {
222: if (BN_mod_word(val, (BN_ULONG)*fact) == 0)
223: break;
224: } while (++fact <= pr_limit);
225:
226:
227: if (fact > pr_limit) {
228: #ifdef HAVE_OPENSSL
229: BIGNUM *bnfact;
230:
231: bnfact = BN_new();
232: BN_set_word(bnfact, *(fact - 1));
233: BN_sqr(bnfact, bnfact, ctx);
234: if (BN_cmp(bnfact, val) > 0
235: || BN_is_prime(val, PRIME_CHECKS, NULL, NULL,
236: NULL) == 1) {
237: putchar(' ');
238: BN_print_dec_fp(stdout, val);
239: } else
240: pollard_pminus1(val);
241: #else
242: printf(" %s", BN_bn2dec(val));
243: #endif
244: break;
245: }
246:
247:
248: do {
249: printf(" %lu", *fact);
250: BN_div_word(val, (BN_ULONG)*fact);
251: } while (BN_mod_word(val, (BN_ULONG)*fact) == 0);
252:
253:
254: fflush(stdout);
255: }
256: putchar('\n');
257: }
258:
259:
260:
261:
262: void
263: BN_print_dec_fp(FILE *fp, const BIGNUM *num)
264: {
265: char *buf;
266:
267: buf = BN_bn2dec(num);
268: if (buf == NULL)
269: return;
270: fprintf(fp, buf);
271: free(buf);
272: }
273:
274: void
275: usage(void)
276: {
277: fprintf(stderr, "usage: factor [value ...]\n");
278: exit (0);
279: }
280:
281:
282:
283:
284: #ifdef HAVE_OPENSSL
285:
286:
287: void
288: pollard_pminus1(BIGNUM *val)
289: {
290: BIGNUM *base, *rbase, *num, *i, *x;
291:
292: base = BN_new();
293: rbase = BN_new();
294: num = BN_new();
295: i = BN_new();
296: x = BN_new();
297:
298: BN_set_word(rbase, 1);
299: newbase:
300: BN_add_word(rbase, 1);
301: BN_set_word(i, 2);
302: BN_copy(base, rbase);
303:
304: for (;;) {
305: BN_mod_exp(base, base, i, val, ctx);
306: if (BN_is_one(base))
307: goto newbase;
308:
309: BN_copy(x, base);
310: BN_sub_word(x, 1);
311: BN_gcd(x, x, val, ctx);
312:
313: if (!BN_is_one(x)) {
314: if (BN_is_prime(x, PRIME_CHECKS, NULL, NULL,
315: NULL) == 1) {
316: putchar(' ');
317: BN_print_dec_fp(stdout, x);
318: } else
319: pollard_pminus1(x);
320: fflush(stdout);
321:
322: BN_div(num, NULL, val, x, ctx);
323: if (BN_is_one(num))
324: return;
325: if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL,
326: NULL) == 1) {
327: putchar(' ');
328: BN_print_dec_fp(stdout, num);
329: fflush(stdout);
330: return;
331: }
332: BN_copy(val, num);
333: }
334: BN_add_word(i, 1);
335: }
336: }
337: #else
338: char *
339: BN_bn2dec(const BIGNUM *val)
340: {
341: char *buf;
342:
343: buf = malloc(100);
344: if (!buf)
345: return buf;
346: snprintf(buf, 100, "%ld", (long)*val);
347: return buf;
348: }
349:
350: BN_ULONG
351: BN_div_word(BIGNUM *a, BN_ULONG b)
352: {
353: BN_ULONG mod;
354:
355: mod = *a % b;
356: *a /= b;
357: return mod;
358: }
359: #endif