1*5d858a7aSchristos /* $NetBSD: factor.c,v 1.38 2020/10/12 13:54:51 christos Exp $ */
261f28255Scgd /*
342fb1b9dScgd * Copyright (c) 1989, 1993
442fb1b9dScgd * The Regents of the University of California. All rights reserved.
561f28255Scgd *
661f28255Scgd * This code is derived from software contributed to Berkeley by
761f28255Scgd * Landon Curt Noll.
861f28255Scgd *
961f28255Scgd * Redistribution and use in source and binary forms, with or without
1061f28255Scgd * modification, are permitted provided that the following conditions
1161f28255Scgd * are met:
1261f28255Scgd * 1. Redistributions of source code must retain the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer.
1461f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1561f28255Scgd * notice, this list of conditions and the following disclaimer in the
1661f28255Scgd * documentation and/or other materials provided with the distribution.
17e5aeb4eaSagc * 3. Neither the name of the University nor the names of its contributors
1861f28255Scgd * may be used to endorse or promote products derived from this software
1961f28255Scgd * without specific prior written permission.
2061f28255Scgd *
2161f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2261f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2361f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2461f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2561f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2661f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2761f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2861f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2961f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3061f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3161f28255Scgd * SUCH DAMAGE.
3261f28255Scgd */
3361f28255Scgd
3461f28255Scgd #ifndef lint
355e85fe34Schristos #include <sys/cdefs.h>
365e85fe34Schristos #ifdef __COPYRIGHT
372fe2731dSlukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
382fe2731dSlukem The Regents of the University of California. All rights reserved.");
395e85fe34Schristos #endif
405e85fe34Schristos #ifdef __SCCSID
415e85fe34Schristos __SCCSID("@(#)factor.c 8.4 (Berkeley) 5/4/95");
425e85fe34Schristos #endif
435e85fe34Schristos #ifdef __RCSID
44*5d858a7aSchristos __RCSID("$NetBSD: factor.c,v 1.38 2020/10/12 13:54:51 christos Exp $");
455e85fe34Schristos #endif
465e85fe34Schristos #ifdef __FBSDID
475e85fe34Schristos __FBSDID("$FreeBSD: head/usr.bin/factor/factor.c 356666 2020-01-12 20:25:11Z gad $");
4842fb1b9dScgd #endif
4961f28255Scgd #endif /* not lint */
5061f28255Scgd
5161f28255Scgd /*
5261f28255Scgd * factor - factor a number into primes
5361f28255Scgd *
545e85fe34Schristos * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
555e85fe34Schristos *
565e85fe34Schristos * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
5761f28255Scgd *
5861f28255Scgd * usage:
595e85fe34Schristos * factor [-hx] [number] ...
6061f28255Scgd *
615e85fe34Schristos * The form of the output is:
6261f28255Scgd *
6361f28255Scgd * number: factor1 factor1 factor2 factor3 factor3 factor3 ...
6461f28255Scgd *
651a815e1fSrillig * where factor1 <= factor2 <= factor3 <= ...
6661f28255Scgd *
67f345b5cbSrin * If the -h flag is specified, the output is in "human-readable" format.
68f345b5cbSrin * Duplicate factors are printed in the form of x^n.
69f345b5cbSrin *
705e85fe34Schristos * If the -x flag is specified numbers are printed in hex.
715e85fe34Schristos *
72f345b5cbSrin * If no number args are given, the list of numbers are read from stdin.
7361f28255Scgd */
7461f28255Scgd
7561f28255Scgd #include <ctype.h>
76a311a773Ssimonb #include <err.h>
7742fb1b9dScgd #include <errno.h>
785e85fe34Schristos #include <inttypes.h>
7942fb1b9dScgd #include <limits.h>
805e85fe34Schristos #include <stdbool.h>
8142fb1b9dScgd #include <stdio.h>
8242fb1b9dScgd #include <stdlib.h>
8334cd8f5bStls #include <unistd.h>
845e85fe34Schristos
855e85fe34Schristos #include "primes.h"
8642fb1b9dScgd
8769757aeeSitojun #ifdef HAVE_OPENSSL
885e85fe34Schristos
89a311a773Ssimonb #include <openssl/bn.h>
905e85fe34Schristos
915e85fe34Schristos #define PRIME_CHECKS 5
925e85fe34Schristos
93f1aebb0cSchristos /* print factors for big numbers */
94f1aebb0cSchristos static void pollard_pminus1(BIGNUM *, int, int);
955e85fe34Schristos
9669757aeeSitojun #else
975e85fe34Schristos
9869757aeeSitojun typedef long BIGNUM;
9969757aeeSitojun typedef u_long BN_ULONG;
1005e85fe34Schristos
1015e85fe34Schristos #define BN_CTX int
1025e85fe34Schristos #define BN_CTX_new() NULL
103c5aeb8a7Schristos #define BN_new() calloc(sizeof(BIGNUM), 1)
104c5aeb8a7Schristos #define BN_free(a) free(a)
105c5aeb8a7Schristos
106c5aeb8a7Schristos #define BN_copy(a, b) *(a) = *(b)
107c5aeb8a7Schristos #define BN_cmp(a, b) (*(a) - *(b))
108aab04f50Ssimonb #define BN_is_zero(v) (*(v) == 0)
109aab04f50Ssimonb #define BN_is_one(v) (*(v) == 1)
11069757aeeSitojun #define BN_mod_word(a, b) (*(a) % (b))
111a311a773Ssimonb
112c5aeb8a7Schristos static BIGNUM *BN_dup(const BIGNUM *);
1135e85fe34Schristos static int BN_dec2bn(BIGNUM **, const char *);
1145e85fe34Schristos static int BN_hex2bn(BIGNUM **, const char *);
115e0ba63feSdholland static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
1165e85fe34Schristos static void BN_print_fp(FILE *, const BIGNUM *);
1175e85fe34Schristos
11869757aeeSitojun #endif
11961f28255Scgd
1205e85fe34Schristos static void BN_print_dec_fp(FILE *, const BIGNUM *);
1215e85fe34Schristos static void convert_str2bn(BIGNUM **, char *);
1225e85fe34Schristos static void pr_fact(BIGNUM *, int, int); /* print factors of a value */
123f1aebb0cSchristos static void pr_print(BIGNUM *, int, int); /* print a prime */
1247f481043Stnn static void usage(void) __dead;
125aab04f50Ssimonb
1265e85fe34Schristos static BN_CTX *ctx; /* just use a global context */
127aab04f50Ssimonb
12842fb1b9dScgd int
main(int argc,char * argv[])129a311a773Ssimonb main(int argc, char *argv[])
13061f28255Scgd {
131a311a773Ssimonb BIGNUM *val;
1325e85fe34Schristos int ch, hflag, xflag;
133a311a773Ssimonb char *p, buf[LINE_MAX]; /* > max number of digits. */
134a311a773Ssimonb
1355e85fe34Schristos hflag = xflag = 0;
136da942834Ssimonb ctx = BN_CTX_new();
137a311a773Ssimonb val = BN_new();
138a311a773Ssimonb if (val == NULL)
139a311a773Ssimonb errx(1, "can't initialise bignum");
14061f28255Scgd
1415e85fe34Schristos while ((ch = getopt(argc, argv, "hx")) != -1)
14242fb1b9dScgd switch (ch) {
143f345b5cbSrin case 'h':
1445e85fe34Schristos hflag++;
1455e85fe34Schristos break;
1465e85fe34Schristos case 'x':
1475e85fe34Schristos xflag++;
148f345b5cbSrin break;
14942fb1b9dScgd case '?':
15042fb1b9dScgd default:
15142fb1b9dScgd usage();
15261f28255Scgd }
15342fb1b9dScgd argc -= optind;
15442fb1b9dScgd argv += optind;
15561f28255Scgd
15642fb1b9dScgd /* No args supplied, read numbers from stdin. */
15742fb1b9dScgd if (argc == 0)
15842fb1b9dScgd for (;;) {
15942fb1b9dScgd if (fgets(buf, sizeof(buf), stdin) == NULL) {
16042fb1b9dScgd if (ferror(stdin))
16142fb1b9dScgd err(1, "stdin");
16242fb1b9dScgd exit (0);
16361f28255Scgd }
16450eb6aadStnozaki for (p = buf; isblank((unsigned char)*p); ++p);
16542fb1b9dScgd if (*p == '\n' || *p == '\0')
16642fb1b9dScgd continue;
1675e85fe34Schristos convert_str2bn(&val, p);
1685e85fe34Schristos pr_fact(val, hflag, xflag);
16961f28255Scgd }
17042fb1b9dScgd /* Factor the arguments. */
17142fb1b9dScgd else
1725e85fe34Schristos for (p = *argv; p != NULL; p = *++argv) {
1735e85fe34Schristos convert_str2bn(&val, p);
1745e85fe34Schristos pr_fact(val, hflag, xflag);
17561f28255Scgd }
17661f28255Scgd exit(0);
17761f28255Scgd }
17861f28255Scgd
1790540874bSchristos static void
pr_exp(int i,int xflag)1800540874bSchristos pr_exp(int i, int xflag)
1810540874bSchristos {
1820540874bSchristos printf(xflag && i > 9 ? "^0x%x" : "^%d", i);
1830540874bSchristos }
1840540874bSchristos
1850540874bSchristos static void
pr_uint64(uint64_t i,int xflag)1860540874bSchristos pr_uint64(uint64_t i, int xflag)
1870540874bSchristos {
1880540874bSchristos printf(xflag ? " 0x%" PRIx64 : " %" PRIu64, i);
1890540874bSchristos }
1900540874bSchristos
19161f28255Scgd /*
19261f28255Scgd * pr_fact - print the factors of a number
19361f28255Scgd *
19461f28255Scgd * Print the factors of the number, from the lowest to the highest.
1955e85fe34Schristos * A factor will be printed multiple times if it divides the value
1965e85fe34Schristos * multiple times.
197f345b5cbSrin *
198f345b5cbSrin * If hflag is specified, duplicate factors are printed in "human-
199f345b5cbSrin * readable" form of x^n.
20061f28255Scgd *
2015e85fe34Schristos * If the xflag is specified, numbers will be printed in hex.
2025e85fe34Schristos *
20361f28255Scgd * Factors are printed with leading tabs.
20461f28255Scgd */
205e0ba63feSdholland static void
pr_fact(BIGNUM * val,int hflag,int xflag)2065e85fe34Schristos pr_fact(BIGNUM *val, int hflag, int xflag)
20761f28255Scgd {
208f345b5cbSrin int i;
2095e85fe34Schristos const uint64_t *fact; /* The factor found. */
21061f28255Scgd
21142fb1b9dScgd /* Firewall - catch 0 and 1. */
2125e85fe34Schristos if (BN_is_zero(val)) /* Historical practice; 0 just exits. */
2135e85fe34Schristos exit(0);
2145e85fe34Schristos if (BN_is_one(val)) {
2155e85fe34Schristos printf("1: 1\n");
2165e85fe34Schristos return;
2175e85fe34Schristos }
21861f28255Scgd
21942fb1b9dScgd /* Factor value. */
220a311a773Ssimonb
2215e85fe34Schristos if (xflag) {
2225e85fe34Schristos fputs("0x", stdout);
2235e85fe34Schristos BN_print_fp(stdout, val);
2245e85fe34Schristos } else
225a311a773Ssimonb BN_print_dec_fp(stdout, val);
226a311a773Ssimonb putchar(':');
227*5d858a7aSchristos fflush(stdout);
228a311a773Ssimonb for (fact = &prime[0]; !BN_is_one(val); ++fact) {
22942fb1b9dScgd /* Look for the smallest factor. */
2305e85fe34Schristos do {
231a311a773Ssimonb if (BN_mod_word(val, (BN_ULONG)*fact) == 0)
23261f28255Scgd break;
2335e85fe34Schristos } while (++fact <= pr_limit);
23461f28255Scgd
23542fb1b9dScgd /* Watch for primes larger than the table. */
23661f28255Scgd if (fact > pr_limit) {
23769757aeeSitojun #ifdef HAVE_OPENSSL
238da942834Ssimonb BIGNUM *bnfact;
239da942834Ssimonb
240da942834Ssimonb bnfact = BN_new();
2415e85fe34Schristos BN_set_word(bnfact, *(fact - 1));
2425e85fe34Schristos if (!BN_sqr(bnfact, bnfact, ctx))
2435e85fe34Schristos errx(1, "error in BN_sqr()");
2445e85fe34Schristos if (BN_cmp(bnfact, val) > 0 ||
2455e85fe34Schristos BN_is_prime_ex(val, PRIME_CHECKS, NULL, NULL) == 1)
246f1aebb0cSchristos pr_print(val, hflag, xflag);
2475e85fe34Schristos else
248f1aebb0cSchristos pollard_pminus1(val, hflag, xflag);
24969757aeeSitojun #else
250f1aebb0cSchristos pr_print(val, hflag, xflag);
25169757aeeSitojun #endif
252f1aebb0cSchristos pr_print(NULL, hflag, xflag);
25342fb1b9dScgd break;
25461f28255Scgd }
25561f28255Scgd
25642fb1b9dScgd /* Divide factor out until none are left. */
257f345b5cbSrin i = 0;
25861f28255Scgd do {
259f345b5cbSrin i++;
260f345b5cbSrin if (!hflag)
2610540874bSchristos pr_uint64(*fact, xflag);
262a311a773Ssimonb BN_div_word(val, (BN_ULONG)*fact);
263a311a773Ssimonb } while (BN_mod_word(val, (BN_ULONG)*fact) == 0);
26442fb1b9dScgd
265f345b5cbSrin if (hflag) {
2660540874bSchristos pr_uint64(*fact, xflag);
267f345b5cbSrin if (i > 1)
2680540874bSchristos pr_exp(i, xflag);
269f345b5cbSrin }
270f345b5cbSrin
27142fb1b9dScgd /* Let the user know we're doing something. */
272a311a773Ssimonb fflush(stdout);
27361f28255Scgd }
274a311a773Ssimonb putchar('\n');
275a311a773Ssimonb }
276a311a773Ssimonb
2775e85fe34Schristos static void
pr_print(BIGNUM * val,int hflag,int xflag)278f1aebb0cSchristos pr_print(BIGNUM *val, int hflag, int xflag)
2795e85fe34Schristos {
280c5aeb8a7Schristos static BIGNUM *sval;
281c5aeb8a7Schristos static int ex = 1;
282f1aebb0cSchristos BIGNUM *pval;
283f1aebb0cSchristos
284f1aebb0cSchristos if (hflag) {
285c5aeb8a7Schristos if (sval == NULL) {
286c5aeb8a7Schristos sval = BN_dup(val);
287c5aeb8a7Schristos return;
288c5aeb8a7Schristos }
289c5aeb8a7Schristos
290c5aeb8a7Schristos if (val != NULL && BN_cmp(val, sval) == 0) {
291c5aeb8a7Schristos ex++;
292c5aeb8a7Schristos return;
293c5aeb8a7Schristos }
294f1aebb0cSchristos pval = sval;
295f1aebb0cSchristos } else if (val == NULL) {
296f1aebb0cSchristos return;
297f1aebb0cSchristos } else {
298f1aebb0cSchristos pval = val;
299f1aebb0cSchristos }
300c5aeb8a7Schristos
3015e85fe34Schristos if (xflag) {
3025e85fe34Schristos fputs(" 0x", stdout);
303f1aebb0cSchristos BN_print_fp(stdout, pval);
3045e85fe34Schristos } else {
3055e85fe34Schristos putchar(' ');
306f1aebb0cSchristos BN_print_dec_fp(stdout, pval);
3075e85fe34Schristos }
308f1aebb0cSchristos
309f1aebb0cSchristos if (hflag) {
310c5aeb8a7Schristos if (ex > 1)
3110540874bSchristos pr_exp(ex, xflag);
312c5aeb8a7Schristos
313c5aeb8a7Schristos if (val != NULL) {
314c5aeb8a7Schristos BN_copy(sval, val);
315c5aeb8a7Schristos } else {
316c5aeb8a7Schristos BN_free(sval);
317c5aeb8a7Schristos sval = NULL;
318c5aeb8a7Schristos }
319c5aeb8a7Schristos ex = 1;
3205e85fe34Schristos }
321f1aebb0cSchristos }
3225e85fe34Schristos
3235e85fe34Schristos static void
usage(void)3245e85fe34Schristos usage(void)
3255e85fe34Schristos {
3260540874bSchristos fprintf(stderr, "Usage: %s [-hx] [value ...]\n", getprogname());
3275e85fe34Schristos exit(1);
3285e85fe34Schristos }
3295e85fe34Schristos
3305e85fe34Schristos #ifdef HAVE_OPENSSL
3315e85fe34Schristos
3325e85fe34Schristos /* pollard p-1, algorithm from Jim Gillogly, May 2000 */
3335e85fe34Schristos static void
pollard_pminus1(BIGNUM * val,int hflag,int xflag)334f1aebb0cSchristos pollard_pminus1(BIGNUM *val, int hflag, int xflag)
3355e85fe34Schristos {
3365e85fe34Schristos BIGNUM *base, *rbase, *num, *i, *x;
3375e85fe34Schristos
3385e85fe34Schristos base = BN_new();
3395e85fe34Schristos rbase = BN_new();
3405e85fe34Schristos num = BN_new();
3415e85fe34Schristos i = BN_new();
3425e85fe34Schristos x = BN_new();
3435e85fe34Schristos
3445e85fe34Schristos BN_set_word(rbase, 1);
3455e85fe34Schristos newbase:
3465e85fe34Schristos if (!BN_add_word(rbase, 1))
3475e85fe34Schristos errx(1, "error in BN_add_word()");
3485e85fe34Schristos BN_set_word(i, 2);
3495e85fe34Schristos BN_copy(base, rbase);
3505e85fe34Schristos
3515e85fe34Schristos for (;;) {
3525e85fe34Schristos BN_mod_exp(base, base, i, val, ctx);
3535e85fe34Schristos if (BN_is_one(base))
3545e85fe34Schristos goto newbase;
3555e85fe34Schristos
3565e85fe34Schristos BN_copy(x, base);
3575e85fe34Schristos BN_sub_word(x, 1);
3585e85fe34Schristos if (!BN_gcd(x, x, val, ctx))
3595e85fe34Schristos errx(1, "error in BN_gcd()");
3605e85fe34Schristos
3615e85fe34Schristos if (!BN_is_one(x)) {
3625e85fe34Schristos if (BN_is_prime_ex(x, PRIME_CHECKS, NULL, NULL) == 1)
363f1aebb0cSchristos pr_print(x, hflag, xflag);
3645e85fe34Schristos else
365f1aebb0cSchristos pollard_pminus1(x, hflag, xflag);
3665e85fe34Schristos fflush(stdout);
3675e85fe34Schristos
3685e85fe34Schristos BN_div(num, NULL, val, x, ctx);
3695e85fe34Schristos if (BN_is_one(num))
3705e85fe34Schristos return;
3715e85fe34Schristos if (BN_is_prime_ex(num, PRIME_CHECKS, NULL,
3725e85fe34Schristos NULL) == 1) {
373f1aebb0cSchristos pr_print(num, hflag, xflag);
3745e85fe34Schristos fflush(stdout);
3755e85fe34Schristos return;
3765e85fe34Schristos }
3775e85fe34Schristos BN_copy(val, num);
3785e85fe34Schristos }
3795e85fe34Schristos if (!BN_add_word(i, 1))
3805e85fe34Schristos errx(1, "error in BN_add_word()");
3815e85fe34Schristos }
3825e85fe34Schristos }
3835e85fe34Schristos
384a311a773Ssimonb /*
385a311a773Ssimonb * Sigh.. No _decimal_ output to file functions in BN.
386a311a773Ssimonb */
387e0ba63feSdholland static void
BN_print_dec_fp(FILE * fp,const BIGNUM * num)388a311a773Ssimonb BN_print_dec_fp(FILE *fp, const BIGNUM *num)
389a311a773Ssimonb {
390a311a773Ssimonb char *buf;
391a311a773Ssimonb
392a311a773Ssimonb buf = BN_bn2dec(num);
393a311a773Ssimonb if (buf == NULL)
394a311a773Ssimonb return; /* XXX do anything here? */
395cbd2e3d5Sjoerg fprintf(fp, "%s", buf);
396a311a773Ssimonb free(buf);
39742fb1b9dScgd }
39842fb1b9dScgd
39969757aeeSitojun #else
40069757aeeSitojun
4015e85fe34Schristos static void
BN_print_fp(FILE * fp,const BIGNUM * num)4025e85fe34Schristos BN_print_fp(FILE *fp, const BIGNUM *num)
4035e85fe34Schristos {
4045e85fe34Schristos fprintf(fp, "%lx", (unsigned long)*num);
4055e85fe34Schristos }
4065e85fe34Schristos
4075e85fe34Schristos static void
BN_print_dec_fp(FILE * fp,const BIGNUM * num)4085e85fe34Schristos BN_print_dec_fp(FILE *fp, const BIGNUM *num)
4095e85fe34Schristos {
4105e85fe34Schristos fprintf(fp, "%lu", (unsigned long)*num);
4115e85fe34Schristos }
4125e85fe34Schristos
4135e85fe34Schristos static int
BN_dec2bn(BIGNUM ** a,const char * str)4145e85fe34Schristos BN_dec2bn(BIGNUM **a, const char *str)
4155e85fe34Schristos {
4165e85fe34Schristos char *p;
4175e85fe34Schristos
4185e85fe34Schristos errno = 0;
4195e85fe34Schristos **a = strtoul(str, &p, 10);
4205e85fe34Schristos return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
4215e85fe34Schristos }
4225e85fe34Schristos
4235e85fe34Schristos static int
BN_hex2bn(BIGNUM ** a,const char * str)4245e85fe34Schristos BN_hex2bn(BIGNUM **a, const char *str)
4255e85fe34Schristos {
4265e85fe34Schristos char *p;
4275e85fe34Schristos
4285e85fe34Schristos errno = 0;
4295e85fe34Schristos **a = strtoul(str, &p, 16);
4305e85fe34Schristos return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
43169757aeeSitojun }
43269757aeeSitojun
433e0ba63feSdholland static BN_ULONG
BN_div_word(BIGNUM * a,BN_ULONG b)43469757aeeSitojun BN_div_word(BIGNUM *a, BN_ULONG b)
43569757aeeSitojun {
43669757aeeSitojun BN_ULONG mod;
43769757aeeSitojun
43869757aeeSitojun mod = *a % b;
43969757aeeSitojun *a /= b;
44069757aeeSitojun return mod;
44169757aeeSitojun }
4425e85fe34Schristos
443c5aeb8a7Schristos static BIGNUM *
BN_dup(const BIGNUM * a)444c5aeb8a7Schristos BN_dup(const BIGNUM *a)
445c5aeb8a7Schristos {
446c5aeb8a7Schristos BIGNUM *b = BN_new();
447c5aeb8a7Schristos BN_copy(b, a);
448c5aeb8a7Schristos return b;
449c5aeb8a7Schristos }
450c5aeb8a7Schristos
45169757aeeSitojun #endif
4525e85fe34Schristos
4535e85fe34Schristos /* Convert string pointed to by *str to a bignum. */
4545e85fe34Schristos static void
convert_str2bn(BIGNUM ** val,char * p)4555e85fe34Schristos convert_str2bn(BIGNUM **val, char *p)
4565e85fe34Schristos {
4575e85fe34Schristos int n = 0;
4585e85fe34Schristos
4595e85fe34Schristos if (*p == '+') p++;
4605e85fe34Schristos if (*p == '-')
4615e85fe34Schristos errx(1, "negative numbers aren't permitted.");
462a17b1cd2Schristos if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
4632c61d0e8Schristos n = BN_hex2bn(val, p + 2);
4645e85fe34Schristos } else {
465662c0e24Schristos n = BN_dec2bn(val, p);
4665e85fe34Schristos }
4675e85fe34Schristos if (n == 0)
4685e85fe34Schristos errx(1, "%s: illegal numeric format.", p);
4695e85fe34Schristos }
470