Home | History | Annotate | Line # | Download | only in factor
factor.c revision 1.35
      1  1.35  christos /*	$NetBSD: factor.c,v 1.35 2020/10/07 19:48:29 christos Exp $	*/
      2   1.1       cgd /*
      3   1.5       cgd  * Copyright (c) 1989, 1993
      4   1.5       cgd  *	The Regents of the University of California.  All rights reserved.
      5   1.1       cgd  *
      6   1.1       cgd  * This code is derived from software contributed to Berkeley by
      7   1.1       cgd  * Landon Curt Noll.
      8   1.1       cgd  *
      9   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     10   1.1       cgd  * modification, are permitted provided that the following conditions
     11   1.1       cgd  * are met:
     12   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     14   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     16   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     17  1.14       agc  * 3. Neither the name of the University nor the names of its contributors
     18   1.1       cgd  *    may be used to endorse or promote products derived from this software
     19   1.1       cgd  *    without specific prior written permission.
     20   1.1       cgd  *
     21   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31   1.1       cgd  * SUCH DAMAGE.
     32   1.1       cgd  */
     33   1.1       cgd 
     34  1.30  christos #ifndef lint
     35   1.7     lukem #include <sys/cdefs.h>
     36  1.30  christos #ifdef __COPYRIGHT
     37  1.18     lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
     38  1.30  christos 	The Regents of the University of California.  All rights reserved.");
     39  1.30  christos #endif
     40  1.30  christos #ifdef __SCCSID
     41  1.30  christos __SCCSID("@(#)factor.c	8.4 (Berkeley) 5/4/95");
     42  1.30  christos #endif
     43  1.30  christos #ifdef __RCSID
     44  1.35  christos __RCSID("$NetBSD: factor.c,v 1.35 2020/10/07 19:48:29 christos Exp $");
     45  1.30  christos #endif
     46  1.30  christos #ifdef __FBSDID
     47  1.30  christos __FBSDID("$FreeBSD: head/usr.bin/factor/factor.c 356666 2020-01-12 20:25:11Z gad $");
     48   1.5       cgd #endif
     49   1.1       cgd #endif /* not lint */
     50   1.1       cgd 
     51   1.1       cgd /*
     52   1.1       cgd  * factor - factor a number into primes
     53   1.1       cgd  *
     54  1.30  christos  * By: Landon Curt Noll   chongo (at) toad.com,   ...!{sun,tolsoft}!hoptoad!chongo
     55  1.30  christos  *
     56  1.30  christos  *   chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
     57   1.1       cgd  *
     58   1.1       cgd  * usage:
     59  1.30  christos  *	factor [-hx] [number] ...
     60   1.1       cgd  *
     61  1.30  christos  * The form of the output is:
     62   1.1       cgd  *
     63   1.1       cgd  *	number: factor1 factor1 factor2 factor3 factor3 factor3 ...
     64   1.1       cgd  *
     65  1.16    rillig  * where factor1 <= factor2 <= factor3 <= ...
     66   1.1       cgd  *
     67  1.28       rin  * If the -h flag is specified, the output is in "human-readable" format.
     68  1.28       rin  * Duplicate factors are printed in the form of x^n.
     69  1.28       rin  *
     70  1.30  christos  * If the -x flag is specified numbers are printed in hex.
     71  1.30  christos  *
     72  1.28       rin  * If no number args are given, the list of numbers are read from stdin.
     73  1.30  christos  * If no args are given, the list of numbers are read from stdin.
     74   1.1       cgd  */
     75   1.1       cgd 
     76  1.10    simonb #include <ctype.h>
     77   1.5       cgd #include <err.h>
     78   1.5       cgd #include <errno.h>
     79  1.30  christos #include <inttypes.h>
     80   1.5       cgd #include <limits.h>
     81  1.30  christos #include <stdbool.h>
     82   1.1       cgd #include <stdio.h>
     83   1.5       cgd #include <stdlib.h>
     84   1.6       tls #include <unistd.h>
     85  1.30  christos 
     86  1.30  christos #include "primes.h"
     87   1.5       cgd 
     88  1.11    itojun #ifdef HAVE_OPENSSL
     89  1.30  christos 
     90  1.10    simonb #include <openssl/bn.h>
     91  1.30  christos 
     92  1.30  christos #define	PRIME_CHECKS	5
     93  1.30  christos 
     94  1.30  christos static void	pollard_pminus1(BIGNUM *, int); /* print factors for big numbers */
     95  1.30  christos 
     96  1.11    itojun #else
     97  1.30  christos 
     98  1.11    itojun typedef long	BIGNUM;
     99  1.11    itojun typedef u_long	BN_ULONG;
    100  1.30  christos 
    101  1.30  christos #define BN_CTX			int
    102  1.30  christos #define BN_CTX_new()		NULL
    103  1.34  christos #define BN_new()		calloc(sizeof(BIGNUM), 1)
    104  1.34  christos #define BN_free(a)		free(a)
    105  1.34  christos 
    106  1.34  christos #define BN_copy(a, b)		*(a) = *(b)
    107  1.34  christos #define BN_cmp(a, b)		(*(a) - *(b))
    108  1.13    simonb #define BN_is_zero(v)		(*(v) == 0)
    109  1.13    simonb #define BN_is_one(v)		(*(v) == 1)
    110  1.11    itojun #define BN_mod_word(a, b)	(*(a) % (b))
    111  1.10    simonb 
    112  1.34  christos static BIGNUM  *BN_dup(const BIGNUM *);
    113  1.30  christos static int	BN_dec2bn(BIGNUM **, const char *);
    114  1.30  christos static int	BN_hex2bn(BIGNUM **, const char *);
    115  1.30  christos static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
    116  1.30  christos static void	BN_print_fp(FILE *, const BIGNUM *);
    117   1.1       cgd 
    118  1.21  drochner #endif
    119   1.1       cgd 
    120  1.30  christos static void	BN_print_dec_fp(FILE *, const BIGNUM *);
    121  1.30  christos static void	convert_str2bn(BIGNUM **, char *);
    122  1.30  christos static bool	is_hex_str(char *);
    123  1.30  christos static void	pr_fact(BIGNUM *, int, int);	/* print factors of a value */
    124  1.30  christos static void	pr_print(BIGNUM *, int);	/* print a prime */
    125  1.32       tnn static void	usage(void) __dead;
    126  1.10    simonb 
    127  1.30  christos static BN_CTX	*ctx;			/* just use a global context */
    128   1.1       cgd 
    129   1.5       cgd int
    130  1.10    simonb main(int argc, char *argv[])
    131   1.1       cgd {
    132  1.10    simonb 	BIGNUM *val;
    133  1.30  christos 	int ch, hflag, xflag;
    134  1.10    simonb 	char *p, buf[LINE_MAX];		/* > max number of digits. */
    135  1.10    simonb 
    136  1.30  christos 	hflag = xflag = 0;
    137  1.12    simonb 	ctx = BN_CTX_new();
    138  1.10    simonb 	val = BN_new();
    139  1.10    simonb 	if (val == NULL)
    140  1.10    simonb 		errx(1, "can't initialise bignum");
    141   1.5       cgd 
    142  1.30  christos 	while ((ch = getopt(argc, argv, "hx")) != -1)
    143   1.5       cgd 		switch (ch) {
    144  1.28       rin 		case 'h':
    145  1.30  christos 			hflag++;
    146  1.30  christos 			break;
    147  1.30  christos 		case 'x':
    148  1.30  christos 			xflag++;
    149  1.28       rin 			break;
    150   1.5       cgd 		case '?':
    151   1.5       cgd 		default:
    152   1.5       cgd 			usage();
    153   1.5       cgd 		}
    154   1.5       cgd 	argc -= optind;
    155   1.5       cgd 	argv += optind;
    156   1.5       cgd 
    157   1.5       cgd 	/* No args supplied, read numbers from stdin. */
    158   1.5       cgd 	if (argc == 0)
    159   1.5       cgd 		for (;;) {
    160   1.5       cgd 			if (fgets(buf, sizeof(buf), stdin) == NULL) {
    161   1.5       cgd 				if (ferror(stdin))
    162   1.5       cgd 					err(1, "stdin");
    163   1.5       cgd 				exit (0);
    164   1.5       cgd 			}
    165  1.23   tnozaki 			for (p = buf; isblank((unsigned char)*p); ++p);
    166   1.5       cgd 			if (*p == '\n' || *p == '\0')
    167   1.5       cgd 				continue;
    168  1.30  christos 			convert_str2bn(&val, p);
    169  1.30  christos 			pr_fact(val, hflag, xflag);
    170   1.5       cgd 		}
    171   1.5       cgd 	/* Factor the arguments. */
    172   1.5       cgd 	else
    173  1.30  christos 		for (p = *argv; p != NULL; p = *++argv) {
    174  1.30  christos 			convert_str2bn(&val, p);
    175  1.30  christos 			pr_fact(val, hflag, xflag);
    176   1.1       cgd 		}
    177   1.1       cgd 	exit(0);
    178   1.1       cgd }
    179   1.1       cgd 
    180  1.35  christos static void
    181  1.35  christos pr_exp(int i, int xflag)
    182  1.35  christos {
    183  1.35  christos 	printf(xflag && i > 9 ? "^0x%x" : "^%d", i);
    184  1.35  christos }
    185  1.35  christos 
    186  1.35  christos static void
    187  1.35  christos pr_uint64(uint64_t i, int xflag)
    188  1.35  christos {
    189  1.35  christos 	printf(xflag ? " 0x%" PRIx64 : " %" PRIu64, i);
    190  1.35  christos }
    191  1.35  christos 
    192   1.1       cgd /*
    193   1.1       cgd  * pr_fact - print the factors of a number
    194   1.1       cgd  *
    195   1.1       cgd  * Print the factors of the number, from the lowest to the highest.
    196  1.30  christos  * A factor will be printed multiple times if it divides the value
    197  1.30  christos  * multiple times.
    198  1.28       rin  *
    199  1.28       rin  * If hflag is specified, duplicate factors are printed in "human-
    200  1.28       rin  * readable" form of x^n.
    201   1.1       cgd  *
    202  1.30  christos  * If the xflag is specified, numbers will be printed in hex.
    203  1.30  christos  *
    204   1.1       cgd  * Factors are printed with leading tabs.
    205   1.1       cgd  */
    206  1.19  dholland static void
    207  1.30  christos pr_fact(BIGNUM *val, int hflag, int xflag)
    208   1.1       cgd {
    209  1.28       rin 	int i;
    210  1.30  christos 	const uint64_t *fact;	/* The factor found. */
    211   1.1       cgd 
    212   1.5       cgd 	/* Firewall - catch 0 and 1. */
    213  1.30  christos 	if (BN_is_zero(val))	/* Historical practice; 0 just exits. */
    214  1.30  christos 		exit(0);
    215  1.30  christos 	if (BN_is_one(val)) {
    216  1.30  christos 		printf("1: 1\n");
    217  1.30  christos 		return;
    218  1.30  christos 	}
    219   1.1       cgd 
    220   1.5       cgd 	/* Factor value. */
    221  1.10    simonb 
    222  1.30  christos 	if (xflag) {
    223  1.30  christos 		fputs("0x", stdout);
    224  1.30  christos 		BN_print_fp(stdout, val);
    225  1.30  christos 	} else
    226  1.30  christos 		BN_print_dec_fp(stdout, val);
    227  1.10    simonb 	putchar(':');
    228  1.10    simonb 	for (fact = &prime[0]; !BN_is_one(val); ++fact) {
    229   1.5       cgd 		/* Look for the smallest factor. */
    230  1.30  christos 		do {
    231  1.10    simonb 			if (BN_mod_word(val, (BN_ULONG)*fact) == 0)
    232   1.1       cgd 				break;
    233  1.30  christos 		} while (++fact <= pr_limit);
    234   1.1       cgd 
    235   1.5       cgd 		/* Watch for primes larger than the table. */
    236   1.1       cgd 		if (fact > pr_limit) {
    237  1.11    itojun #ifdef HAVE_OPENSSL
    238  1.12    simonb 			BIGNUM *bnfact;
    239  1.12    simonb 
    240  1.12    simonb 			bnfact = BN_new();
    241  1.30  christos 			BN_set_word(bnfact, *(fact - 1));
    242  1.30  christos 			if (!BN_sqr(bnfact, bnfact, ctx))
    243  1.30  christos 				errx(1, "error in BN_sqr()");
    244  1.30  christos 			if (BN_cmp(bnfact, val) > 0 ||
    245  1.30  christos 			    BN_is_prime_ex(val, PRIME_CHECKS, NULL, NULL) == 1)
    246  1.30  christos 				pr_print(val, xflag);
    247  1.30  christos 			else
    248  1.30  christos 				pollard_pminus1(val, xflag);
    249  1.11    itojun #else
    250  1.30  christos 			pr_print(val, xflag);
    251  1.11    itojun #endif
    252  1.34  christos 			pr_print(NULL, xflag);
    253   1.5       cgd 			break;
    254   1.1       cgd 		}
    255   1.1       cgd 
    256   1.5       cgd 		/* Divide factor out until none are left. */
    257  1.28       rin 		i = 0;
    258   1.1       cgd 		do {
    259  1.28       rin 			i++;
    260  1.28       rin 			if (!hflag)
    261  1.35  christos 				pr_uint64(*fact, xflag);
    262  1.10    simonb 			BN_div_word(val, (BN_ULONG)*fact);
    263  1.10    simonb 		} while (BN_mod_word(val, (BN_ULONG)*fact) == 0);
    264   1.5       cgd 
    265  1.28       rin 		if (hflag) {
    266  1.35  christos 			pr_uint64(*fact, xflag);
    267  1.28       rin 			if (i > 1)
    268  1.35  christos 				pr_exp(i, xflag);
    269  1.28       rin 		}
    270  1.28       rin 
    271   1.5       cgd 		/* Let the user know we're doing something. */
    272  1.10    simonb 		fflush(stdout);
    273   1.1       cgd 	}
    274  1.10    simonb 	putchar('\n');
    275  1.10    simonb }
    276  1.10    simonb 
    277  1.19  dholland static void
    278  1.30  christos pr_print(BIGNUM *val, int xflag)
    279  1.10    simonb {
    280  1.34  christos 	static BIGNUM *sval;
    281  1.34  christos 	static int ex = 1;
    282  1.34  christos 	if (sval == NULL) {
    283  1.34  christos 		sval = BN_dup(val);
    284  1.34  christos 		return;
    285  1.34  christos 	}
    286  1.34  christos 
    287  1.34  christos 	if (val != NULL && BN_cmp(val, sval) == 0) {
    288  1.34  christos 		ex++;
    289  1.34  christos 		return;
    290  1.34  christos 	}
    291  1.34  christos 	if (val == NULL)
    292  1.34  christos 		val = sval;
    293  1.34  christos 
    294  1.30  christos 	if (xflag) {
    295  1.30  christos 		fputs(" 0x", stdout);
    296  1.30  christos 		BN_print_fp(stdout, val);
    297  1.30  christos 	} else {
    298  1.30  christos 		putchar(' ');
    299  1.30  christos 		BN_print_dec_fp(stdout, val);
    300  1.30  christos 	}
    301  1.34  christos 	if (ex > 1)
    302  1.35  christos 		pr_exp(ex, xflag);
    303  1.34  christos 
    304  1.34  christos 	if (val != NULL) {
    305  1.34  christos 		BN_copy(sval, val);
    306  1.34  christos 	} else {
    307  1.34  christos 		BN_free(sval);
    308  1.34  christos 		sval = NULL;
    309  1.34  christos 	}
    310  1.34  christos 	ex = 1;
    311   1.5       cgd }
    312   1.5       cgd 
    313  1.30  christos static void
    314  1.10    simonb usage(void)
    315   1.5       cgd {
    316  1.35  christos 	fprintf(stderr, "Usage: %s [-hx] [value ...]\n", getprogname());
    317  1.30  christos 	exit(1);
    318  1.10    simonb }
    319  1.10    simonb 
    320  1.30  christos #ifdef HAVE_OPENSSL
    321  1.10    simonb 
    322  1.30  christos /* pollard p-1, algorithm from Jim Gillogly, May 2000 */
    323  1.19  dholland static void
    324  1.30  christos pollard_pminus1(BIGNUM *val, int xflag)
    325  1.10    simonb {
    326  1.30  christos 	BIGNUM *base, *rbase, *num, *i, *x;
    327  1.10    simonb 
    328  1.30  christos 	base = BN_new();
    329  1.30  christos 	rbase = BN_new();
    330  1.30  christos 	num = BN_new();
    331  1.30  christos 	i = BN_new();
    332  1.21  drochner 	x = BN_new();
    333  1.30  christos 
    334  1.30  christos 	BN_set_word(rbase, 1);
    335  1.30  christos newbase:
    336  1.30  christos 	if (!BN_add_word(rbase, 1))
    337  1.30  christos 		errx(1, "error in BN_add_word()");
    338  1.30  christos 	BN_set_word(i, 2);
    339  1.30  christos 	BN_copy(base, rbase);
    340  1.10    simonb 
    341  1.10    simonb 	for (;;) {
    342  1.30  christos 		BN_mod_exp(base, base, i, val, ctx);
    343  1.30  christos 		if (BN_is_one(base))
    344  1.30  christos 			goto newbase;
    345  1.30  christos 
    346  1.30  christos 		BN_copy(x, base);
    347  1.30  christos 		BN_sub_word(x, 1);
    348  1.30  christos 		if (!BN_gcd(x, x, val, ctx))
    349  1.30  christos 			errx(1, "error in BN_gcd()");
    350  1.30  christos 
    351  1.30  christos 		if (!BN_is_one(x)) {
    352  1.30  christos 			if (BN_is_prime_ex(x, PRIME_CHECKS, NULL, NULL) == 1)
    353  1.30  christos 				pr_print(x, xflag);
    354  1.30  christos 			else
    355  1.30  christos 				pollard_pminus1(x, xflag);
    356  1.10    simonb 			fflush(stdout);
    357  1.10    simonb 
    358  1.30  christos 			BN_div(num, NULL, val, x, ctx);
    359  1.10    simonb 			if (BN_is_one(num))
    360  1.10    simonb 				return;
    361  1.30  christos 			if (BN_is_prime_ex(num, PRIME_CHECKS, NULL,
    362  1.30  christos 			    NULL) == 1) {
    363  1.30  christos 				pr_print(num, xflag);
    364  1.10    simonb 				fflush(stdout);
    365  1.10    simonb 				return;
    366  1.10    simonb 			}
    367  1.10    simonb 			BN_copy(val, num);
    368  1.10    simonb 		}
    369  1.30  christos 		if (!BN_add_word(i, 1))
    370  1.30  christos 			errx(1, "error in BN_add_word()");
    371  1.10    simonb 	}
    372   1.1       cgd }
    373  1.30  christos 
    374  1.30  christos /*
    375  1.30  christos  * Sigh..  No _decimal_ output to file functions in BN.
    376  1.30  christos  */
    377  1.30  christos static void
    378  1.30  christos BN_print_dec_fp(FILE *fp, const BIGNUM *num)
    379  1.30  christos {
    380  1.30  christos 	char *buf;
    381  1.30  christos 
    382  1.30  christos 	buf = BN_bn2dec(num);
    383  1.30  christos 	if (buf == NULL)
    384  1.30  christos 		return;	/* XXX do anything here? */
    385  1.30  christos 	fprintf(fp, "%s", buf);
    386  1.30  christos 	free(buf);
    387  1.30  christos }
    388  1.30  christos 
    389  1.11    itojun #else
    390  1.30  christos 
    391  1.30  christos static void
    392  1.30  christos BN_print_fp(FILE *fp, const BIGNUM *num)
    393  1.30  christos {
    394  1.30  christos 	fprintf(fp, "%lx", (unsigned long)*num);
    395  1.30  christos }
    396  1.30  christos 
    397  1.30  christos static void
    398  1.30  christos BN_print_dec_fp(FILE *fp, const BIGNUM *num)
    399  1.11    itojun {
    400  1.30  christos 	fprintf(fp, "%lu", (unsigned long)*num);
    401  1.30  christos }
    402  1.30  christos 
    403  1.30  christos static int
    404  1.30  christos BN_dec2bn(BIGNUM **a, const char *str)
    405  1.30  christos {
    406  1.30  christos 	char *p;
    407  1.30  christos 
    408  1.30  christos 	errno = 0;
    409  1.30  christos 	**a = strtoul(str, &p, 10);
    410  1.30  christos 	return (errno == 0 ? 1 : 0);	/* OpenSSL returns 0 on error! */
    411  1.30  christos }
    412  1.30  christos 
    413  1.30  christos static int
    414  1.30  christos BN_hex2bn(BIGNUM **a, const char *str)
    415  1.30  christos {
    416  1.30  christos 	char *p;
    417  1.11    itojun 
    418  1.30  christos 	errno = 0;
    419  1.30  christos 	**a = strtoul(str, &p, 16);
    420  1.30  christos 	return (errno == 0 ? 1 : 0);	/* OpenSSL returns 0 on error! */
    421  1.11    itojun }
    422  1.11    itojun 
    423  1.19  dholland static BN_ULONG
    424  1.11    itojun BN_div_word(BIGNUM *a, BN_ULONG b)
    425  1.11    itojun {
    426  1.11    itojun 	BN_ULONG mod;
    427  1.11    itojun 
    428  1.11    itojun 	mod = *a % b;
    429  1.11    itojun 	*a /= b;
    430  1.11    itojun 	return mod;
    431  1.11    itojun }
    432  1.30  christos 
    433  1.34  christos static BIGNUM *
    434  1.34  christos BN_dup(const BIGNUM *a)
    435  1.34  christos {
    436  1.34  christos 	BIGNUM *b = BN_new();
    437  1.34  christos 	BN_copy(b, a);
    438  1.34  christos 	return b;
    439  1.34  christos }
    440  1.34  christos 
    441  1.11    itojun #endif
    442  1.30  christos 
    443  1.30  christos /*
    444  1.30  christos  * Scan the string from left-to-right to see if the longest substring
    445  1.30  christos  * is a valid hexadecimal number.
    446  1.30  christos  */
    447  1.30  christos static bool
    448  1.30  christos is_hex_str(char *str)
    449  1.30  christos {
    450  1.30  christos 	char c, *p;
    451  1.30  christos 	bool saw_hex = false;
    452  1.30  christos 
    453  1.30  christos 	for (p = str; *p; p++) {
    454  1.30  christos 		if (isdigit((unsigned char)*p))
    455  1.30  christos 			continue;
    456  1.30  christos 		c = tolower((unsigned char)*p);
    457  1.30  christos 		if (c >= 'a' && c <= 'f') {
    458  1.30  christos 			saw_hex = true;
    459  1.30  christos 			continue;
    460  1.30  christos 		}
    461  1.30  christos 		break;	/* Not a hexadecimal digit. */
    462  1.30  christos 	}
    463  1.30  christos 	return saw_hex;
    464  1.30  christos }
    465  1.30  christos 
    466  1.30  christos /* Convert string pointed to by *str to a bignum.  */
    467  1.30  christos static void
    468  1.30  christos convert_str2bn(BIGNUM **val, char *p)
    469  1.30  christos {
    470  1.30  christos 	int n = 0;
    471  1.30  christos 
    472  1.30  christos 	if (*p == '+') p++;
    473  1.30  christos 	if (*p == '-')
    474  1.30  christos 		errx(1, "negative numbers aren't permitted.");
    475  1.33  christos 	if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
    476  1.33  christos 		n = BN_hex2bn(val, p + 2);
    477  1.30  christos 	} else {
    478  1.30  christos 		n = is_hex_str(p) ? BN_hex2bn(val, p) : BN_dec2bn(val, p);
    479  1.30  christos 	}
    480  1.30  christos 	if (n == 0)
    481  1.30  christos 		errx(1, "%s: illegal numeric format.", p);
    482  1.30  christos }
    483