CHECK_RETVAL_BOOL \ static BOOLEAN selfTestGeneralOps1( void ) { BIGNUM a; /* Simple tests that don't need the support of higher-level routines like importBignum() */ BN_init( &a ); if( !BN_zero( &a ) ) return( FALSE ); if( !BN_is_zero( &a ) || BN_is_one( &a ) ) return( FALSE ); if( !BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) ) return( FALSE ); if( BN_is_odd( &a ) ) return( FALSE ); if( BN_get_word( &a ) != 0 ) return( FALSE ); if( !BN_one( &a ) ) return( FALSE ); if( BN_is_zero( &a ) || !BN_is_one( &a ) ) return( FALSE ); if( BN_is_word( &a, 0 ) || !BN_is_word( &a, 1 ) ) return( FALSE ); if( !BN_is_odd( &a ) ) return( FALSE ); if( BN_num_bytes( &a ) != 1 ) return( FALSE ); if( BN_get_word( &a ) != 1 ) return( FALSE ); BN_clear( &a ); return( TRUE ); }
bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size) { RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer; bool ret = false; BN_CTX* ctx = BN_CTX_new(); BIGNUM* r32 = BN_new(); BIGNUM* n0inv = BN_new(); BIGNUM* rr = BN_new(); if (sizeof(RSAPublicKey) > size || RSA_size(key) != ANDROID_PUBKEY_MODULUS_SIZE) { goto cleanup; } // Store the modulus size. key_struct->modulus_size_words = ANDROID_PUBKEY_MODULUS_SIZE_WORDS; // Compute and store n0inv = -1 / N[0] mod 2^32. if (!ctx || !r32 || !n0inv || !BN_set_bit(r32, 32) || !BN_mod(n0inv, key->n, r32, ctx) || !BN_mod_inverse(n0inv, n0inv, r32, ctx) || !BN_sub(n0inv, r32, n0inv)) { goto cleanup; } key_struct->n0inv = (uint32_t)BN_get_word(n0inv); // Store the modulus. if (!android_pubkey_encode_bignum(key->n, key_struct->modulus)) { goto cleanup; } // Compute and store rr = (2^(rsa_size)) ^ 2 mod N. if (!ctx || !rr || !BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8) || !BN_mod_sqr(rr, rr, key->n, ctx) || !android_pubkey_encode_bignum(rr, key_struct->rr)) { goto cleanup; } // Store the exponent. key_struct->exponent = (uint32_t)BN_get_word(key->e); ret = true; cleanup: BN_free(rr); BN_free(n0inv); BN_free(r32); BN_CTX_free(ctx); return ret; }
static u_long get_ulong(struct number *n) { normalize(n, 0); return (BN_get_word(n->number)); }
bool MakePrime(RsaParams params, const BIGNUM* value, BIGNUM** delta_ret, BN_CTX* ctx) { BIGNUM* tmp = BN_dup(value); CHECK_CALL(tmp); // Find a delta such that // p = value + delta // is prime const int delta_max = RsaParams_GetDeltaMax(params); bool is_even = !BN_is_odd(tmp); if(is_even) { CHECK_CALL(BN_add_word(tmp, 1)); } if(!RsaPrime(*delta_ret, tmp, ctx)) return false; if(is_even) { CHECK_CALL(BN_add_word(*delta_ret, 1)); } // printf("%llu %d\n", BN_get_word(*delta_ret), delta_max); if(BN_get_word(*delta_ret) > delta_max) return false; BN_clear_free(tmp); return true; }
static int test_BN_import_export(void) { BIGNUM *bn; int ret = 0; int i; bn = BN_new(); for (i = 0; i < sizeof(ietests)/sizeof(ietests[0]); i++) { size_t len; unsigned char *p; if (!BN_bin2bn((unsigned char*)ietests[i].data, ietests[i].len, bn)) return 1; if (BN_get_word(bn) != ietests[i].num) return 1; len = BN_num_bytes(bn); if (len != ietests[i].len) return 1; p = malloc(len + 1); p[len] = 0xf4; BN_bn2bin(bn, p); if (p[len] != 0xf4) return 1; if (memcmp(p, ietests[i].data, ietests[i].len) != 0) return 1; free(p); } BN_free(bn); return ret; }
static void to_ascii(void) { struct number *n; struct value *value; char str[2]; value = pop(); if (value != NULL) { str[1] = '\0'; switch (value->type) { case BCODE_NONE: return; case BCODE_NUMBER: n = value->u.num; normalize(n, 0); if (BN_num_bits(n->number) > 8) bn_check(BN_mask_bits(n->number, 8)); str[0] = (char)BN_get_word(n->number); break; case BCODE_STRING: str[0] = value->u.string[0]; break; } stack_free_value(value); push_string(bstrdup(str)); } }
void b58encode_check(void *buf, size_t len, char *result) { unsigned char hash1[32]; unsigned char hash2[32]; int d, p; BN_CTX *bnctx; BIGNUM *bn, *bndiv, *bntmp; BIGNUM bna, bnb, bnbase, bnrem; unsigned char *binres; int brlen, zpfx; bnctx = BN_CTX_new(); BN_init(&bna); BN_init(&bnb); BN_init(&bnbase); BN_init(&bnrem); BN_set_word(&bnbase, 58); bn = &bna; bndiv = &bnb; brlen = (2 * len) + 4; binres = (unsigned char*) malloc(brlen); memcpy(binres, buf, len); SHA256(binres, len, hash1); SHA256(hash1, sizeof(hash1), hash2); memcpy(&binres[len], hash2, 4); BN_bin2bn(binres, len + 4, bn); for (zpfx = 0; zpfx < (len + 4) && binres[zpfx] == 0; zpfx++); p = brlen; while (!BN_is_zero(bn)) { BN_div(bndiv, &bnrem, bn, &bnbase, bnctx); bntmp = bn; bn = bndiv; bndiv = bntmp; d = BN_get_word(&bnrem); binres[--p] = b58alphabet[d]; } while (zpfx--) { binres[--p] = b58alphabet[0]; } memcpy(result, &binres[p], brlen - p); result[brlen - p] = '\0'; free(binres); BN_clear_free(&bna); BN_clear_free(&bnb); BN_clear_free(&bnbase); BN_clear_free(&bnrem); BN_CTX_free(bnctx); }
int rsa_plaintext_to_word(const rsa_plaintext_t *m, unsigned long *a) { OPENSSL_assert(m); OPENSSL_assert(a); *a = BN_get_word(m); return 0; }
static int fdt_add_bignum(void *blob, int noffset, const char *prop_name, BIGNUM *num, int num_bits) { int nwords = num_bits / 32; int size; uint32_t *buf, *ptr; BIGNUM *tmp, *big2, *big32, *big2_32; BN_CTX *ctx; int ret; tmp = BN_new(); big2 = BN_new(); big32 = BN_new(); big2_32 = BN_new(); if (!tmp || !big2 || !big32 || !big2_32) { fprintf(stderr, "Out of memory (bignum)\n"); return -ENOMEM; } ctx = BN_CTX_new(); if (!tmp) { fprintf(stderr, "Out of memory (bignum context)\n"); return -ENOMEM; } BN_set_word(big2, 2L); BN_set_word(big32, 32L); BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ size = nwords * sizeof(uint32_t); buf = malloc(size); if (!buf) { fprintf(stderr, "Out of memory (%d bytes)\n", size); return -ENOMEM; } /* Write out modulus as big endian array of integers */ for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ *ptr = cpu_to_fdt32(BN_get_word(tmp)); BN_rshift(num, num, 32); /* N = N/B */ } /* * We try signing with successively increasing size values, so this * might fail several times */ ret = fdt_setprop(blob, noffset, prop_name, buf, size); if (ret) return -FDT_ERR_NOSPACE; free(buf); BN_free(tmp); BN_free(big2); BN_free(big32); BN_free(big2_32); return ret; }
/* * rsa_get_exponent(): - Get the public exponent from an RSA key */ static int rsa_get_exponent(RSA *key, uint64_t *e) { int ret; BIGNUM *bn_te; uint64_t te; ret = -EINVAL; bn_te = NULL; if (!e) goto cleanup; if (BN_num_bits(key->e) > 64) goto cleanup; *e = BN_get_word(key->e); if (BN_num_bits(key->e) < 33) { ret = 0; goto cleanup; } bn_te = BN_dup(key->e); if (!bn_te) goto cleanup; if (!BN_rshift(bn_te, bn_te, 32)) goto cleanup; if (!BN_mask_bits(bn_te, 32)) goto cleanup; te = BN_get_word(bn_te); te <<= 32; *e |= te; ret = 0; cleanup: if (bn_te) BN_free(bn_te); return ret; }
static int fdt_add_bignum(void *blob, int noffset, const char *prop_name, BIGNUM *num, int num_bits) { int nwords = num_bits / 32; int size; uint32_t *buf, *ptr; BIGNUM *tmp, *big2, *big32, *big2_32; BN_CTX *ctx; int ret; tmp = BN_new(); big2 = BN_new(); big32 = BN_new(); big2_32 = BN_new(); if (!tmp || !big2 || !big32 || !big2_32) { fprintf(stderr, "Out of memory (bignum)\n"); return -ENOMEM; } ctx = BN_CTX_new(); if (!tmp) { fprintf(stderr, "Out of memory (bignum context)\n"); return -ENOMEM; } BN_set_word(big2, 2L); BN_set_word(big32, 32L); BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ size = nwords * sizeof(uint32_t); buf = malloc(size); if (!buf) { fprintf(stderr, "Out of memory (%d bytes)\n", size); return -ENOMEM; } /* Write out modulus as big endian array of integers */ for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ *ptr = cpu_to_fdt32(BN_get_word(tmp)); BN_rshift(num, num, 32); /* N = N/B */ } ret = fdt_setprop(blob, noffset, prop_name, buf, size); if (ret) { fprintf(stderr, "Failed to write public key to FIT\n"); return -ENOSPC; } free(buf); BN_free(tmp); BN_free(big2); BN_free(big32); BN_free(big2_32); return ret; }
static void not(void) { struct number *a; a = pop_number(); if (a == NULL) return; a->scale = 0; bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1)); push_number(a); }
static int stackint(GPtrArray *stack, int index) { struct buffer *buf = stacktop(stack, index); BIGNUM bn; BN_init(&bn); int ret = -1; if (!CastToBigNum(&bn, buf)) goto out; if (!BN_is_negative(&bn)) ret = BN_get_word(&bn); else { BN_set_negative(&bn, 0); ret = BN_get_word(&bn); ret = -ret; } out: BN_clear_free(&bn); return ret; }
int bn_probable_prime_dh_coprime(BIGNUM *rnd, int bits, BN_CTX *ctx) { int i; BIGNUM *offset_index; BIGNUM *offset_count; int ret = 0; OPENSSL_assert(bits > prime_multiplier_bits); BN_CTX_start(ctx); if ((offset_index = BN_CTX_get(ctx)) == NULL) goto err; if ((offset_count = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_add_word(offset_count, prime_offset_count)) goto err; loop: if (!BN_rand(rnd, bits - prime_multiplier_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) goto err; if (BN_is_bit_set(rnd, bits)) goto loop; if (!BN_rand_range(offset_index, offset_count)) goto err; if (!BN_mul_word(rnd, prime_multiplier) || !BN_add_word(rnd, prime_offsets[BN_get_word(offset_index)])) goto err; /* we now have a random number 'rand' to test. */ /* skip coprimes */ for (i = first_prime_index; i < NUMPRIMES; i++) { /* check that rnd is a prime */ BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); if (mod == (BN_ULONG)-1) goto err; if (mod <= 1) goto loop; } ret = 1; err: BN_CTX_end(ctx); bn_check_top(rnd); return ret; }
static int set_get(unsigned long num) { BIGNUM *bn; bn = BN_new(); if (!BN_set_word(bn, num)) return 1; if (BN_get_word(bn) != num) return 1; BN_free(bn); return 0; }
/*place base58 encoding of data into result*/ void base58_encode(unsigned char *data, unsigned int len, char *result) { const char code_string[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; BIGNUM *x, *rem, *base, *tmp, *tmp2; x = BN_new(); rem = BN_new(); base = BN_new(); tmp = BN_new(); char * output_string = malloc(64); x = BN_bin2bn(data, len, x); BN_set_word(rem, 1); BN_set_word(base, 58); BN_CTX *bnctx; bnctx = BN_CTX_new(); int i = 0; while (!BN_is_zero(x)) { BN_div(tmp, rem, x, base, bnctx); output_string[i++] = code_string[BN_get_word(rem)]; tmp2 = x; x = tmp; tmp = tmp2; } //public key int i2 = 0; while (data[i2] == 0) { output_string[i++] = code_string[0]; i2++; } int base58len = i; while (i>=0) { result[base58len-i] = output_string[i-1]; i--; } result[base58len] = 0; BN_free(x); BN_free(base); BN_free(rem); BN_free(tmp); BN_CTX_free(bnctx); free(output_string); }
int check(RSA* key) { int public_exponent = BN_get_word(key->e); int modulus = BN_num_bits(key->n); if (public_exponent != 65537) { fprintf(stderr, "WARNING: Public exponent should be 65537 (but is %d).\n", public_exponent); } if (modulus != 1024 && modulus != 2048 && modulus != 4096 && modulus != 8192) { fprintf(stderr, "ERROR: Unknown modulus length = %d.\n", modulus); return 0; } return 1; }
qint32 CryptoUtils::checkDHParams (BIGNUM *p, qint32 g) { if (g < 2 || g > 7) { return -1; } BIGNUM t; BN_init (&t); BIGNUM dh_g; BN_init (&dh_g); Utils::ensure (BN_set_word (&dh_g, 4 * g)); Utils::ensure (BN_mod (&t, p, &dh_g, BN_ctx)); qint32 x = BN_get_word (&t); Q_ASSERT(x >= 0 && x < 4 * g); BN_free (&dh_g); switch (g) { case 2: if (x != 7) { return -1; } break; case 3: if (x % 3 != 2 ) { return -1; } break; case 4: break; case 5: if (x % 5 != 1 && x % 5 != 4) { return -1; } break; case 6: if (x != 19 && x != 23) { return -1; } break; case 7: if (x % 7 != 3 && x % 7 != 5 && x % 7 != 6) { return -1; } break; } if (!checkPrime (p)) { return -1; } BIGNUM b; BN_init (&b); Utils::ensure (BN_set_word (&b, 2)); Utils::ensure (BN_div (&t, 0, p, &b, BN_ctx)); if (!checkPrime (&t)) { return -1; } BN_free (&b); BN_free (&t); return 0; }
int check(RSA* key) { const BIGNUM *n, *e; int public_exponent, modulus; RSA_get0_key(key, &n, &e, NULL); public_exponent = BN_get_word(e); modulus = BN_num_bits(n); if (public_exponent != 3 && public_exponent != 65537) { fprintf(stderr, "WARNING: Public exponent should be 3 or 65537 (but is %d).\n", public_exponent); } if (modulus != 1024 && modulus != 2048 && modulus != 3072 && modulus != 4096 && modulus != 8192) { fprintf(stderr, "ERROR: Unknown modulus length = %d.\n", modulus); return 0; } return 1; }
int paillier_decryptll(long long *plain, const BIGNUM *c, const privKey *key, BN_CTX *ctx) { int ret = 1; BN_CTX_start(ctx); BIGNUM *plain_BN = BN_CTX_get(ctx); if (paillier_decrypt(plain_BN, c, key, ctx) != 0) goto end; *plain = BN_get_word(plain_BN); if (*plain == 0xffffffffL) goto end; ret = 0; end: if (ret) { ERR_load_crypto_strings(); fprintf(stderr, "Can't decrypt: %s", ERR_error_string(ERR_get_error(), NULL)); } BN_CTX_end(ctx); return ret; }
static int get_key_bignum(BIGNUM *num, int num_bits, uint32_t *key_mod) { BIGNUM *tmp, *big2, *big32, *big2_32; BN_CTX *ctx; int ret; tmp = BN_new(); big2 = BN_new(); big32 = BN_new(); big2_32 = BN_new(); if (!tmp || !big2 || !big32 || !big2_32) { fprintf(stderr, "Out of memory (bignum)\n"); return -1; } ctx = BN_CTX_new(); if (!tmp) { fprintf(stderr, "Out of memory (bignum context)\n"); return -1; } BN_set_word(big2, 2L); BN_set_word(big32, 32L); BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ for (ret = 0; ret <= 63; ret++) { BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ key_mod[ret] = htonl(BN_get_word(tmp)); BN_rshift(num, num, 32); /* N = N/B */ } BN_free(tmp); BN_free(big2); BN_free(big32); BN_free(big2_32); return 0; }
static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods) { int i; BN_ULONG delta; BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; char is_single_word = bits <= BN_BITS2; again: if (!BN_priv_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) return 0; /* we now have a random number 'rnd' to test. */ for (i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); if (mod == (BN_ULONG)-1) return 0; mods[i] = (prime_t) mod; } /* * If bits is so small that it fits into a single word then we * additionally don't want to exceed that many bits. */ if (is_single_word) { BN_ULONG size_limit; if (bits == BN_BITS2) { /* * Shifting by this much has undefined behaviour so we do it a * different way */ size_limit = ~((BN_ULONG)0) - BN_get_word(rnd); } else { size_limit = (((BN_ULONG)1) << bits) - BN_get_word(rnd) - 1; } if (size_limit < maxdelta) maxdelta = size_limit; } delta = 0; loop: if (is_single_word) { BN_ULONG rnd_word = BN_get_word(rnd); /*- * In the case that the candidate prime is a single word then * we check that: * 1) It's greater than primes[i] because we shouldn't reject * 3 as being a prime number because it's a multiple of * three. * 2) That it's not a multiple of a known prime. We don't * check that rnd-1 is also coprime to all the known * primes because there aren't many small primes where * that's true. */ for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) { if ((mods[i] + delta) % primes[i] == 0) { delta += 2; if (delta > maxdelta) goto again; goto loop; } } } else { for (i = 1; i < NUMPRIMES; i++) { /* * check that rnd is not a prime and also that gcd(rnd-1,primes) * == 1 (except for 2) */ if (((mods[i] + delta) % primes[i]) <= 1) { delta += 2; if (delta > maxdelta) goto again; goto loop; } } } if (!BN_add_word(rnd, delta)) return 0; if (BN_num_bits(rnd) != bits) goto again; bn_check_top(rnd); return 1; }
static int test_BN_uadd(void) { BIGNUM *a, *b, *c; char *p; a = BN_new(); b = BN_new(); c = BN_new(); BN_set_word(a, 1); BN_set_word(b, 2); BN_uadd(c, a, b); if (BN_get_word(c) != 3) return 1; BN_uadd(c, b, a); if (BN_get_word(c) != 3) return 1; BN_set_word(b, 0xff); BN_uadd(c, a, b); if (BN_get_word(c) != 0x100) return 1; BN_uadd(c, b, a); if (BN_get_word(c) != 0x100) return 1; BN_set_word(a, 0xff); BN_uadd(c, a, b); if (BN_get_word(c) != 0x1fe) return 1; BN_uadd(c, b, a); if (BN_get_word(c) != 0x1fe) return 1; BN_free(a); BN_free(b); BN_hex2bn(&a, "50212A3B611D46642C825A16A354CE0FD4D85DD2"); BN_hex2bn(&b, "84B6C7E8D28ACA1614954DA"); BN_uadd(c, b, a); p = BN_bn2hex(c); if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) { free(p); return 1; } free(p); BN_uadd(c, a, b); p = BN_bn2hex(c); if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) { free(p); return 1; } free(p); BN_free(a); BN_free(b); BN_free(c); return 0; }
static int probable_prime(BIGNUM *rnd, int bits) { int i; prime_t mods[NUMPRIMES]; BN_ULONG delta; BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES-1]; char is_single_word = bits <= BN_BITS2; again: if (!BN_rand(rnd,bits,1,1)) return(0); /* we now have a random number 'rnd' to test. */ for (i=1; i<NUMPRIMES; i++) mods[i]=(prime_t)BN_mod_word(rnd,(BN_ULONG)primes[i]); /* If bits is so small that it fits into a single word then we * additionally don't want to exceed that many bits. */ if (is_single_word) { BN_ULONG size_limit = (((BN_ULONG) 1) << bits) - BN_get_word(rnd) - 1; if (size_limit < maxdelta) maxdelta = size_limit; } delta=0; loop: if (is_single_word) { BN_ULONG rnd_word = BN_get_word(rnd); /* In the case that the candidate prime is a single word then * we check that: * 1) It's greater than primes[i] because we shouldn't reject * 3 as being a prime number because it's a multiple of * three. * 2) That it's not a multiple of a known prime. We don't * check that rnd-1 is also coprime to all the known * primes because there aren't many small primes where * that's true. */ for (i=1; i<NUMPRIMES && primes[i]<rnd_word; i++) { if ((mods[i]+delta)%primes[i] == 0) { delta+=2; if (delta > maxdelta) goto again; goto loop; } } } else { for (i=1; i<NUMPRIMES; i++) { /* check that rnd is not a prime and also * that gcd(rnd-1,primes) == 1 (except for 2) */ if (((mods[i]+delta)%primes[i]) <= 1) { delta+=2; if (delta > maxdelta) goto again; goto loop; } } } if (!BN_add_word(rnd,delta)) return(0); if (BN_num_bits(rnd) != bits) goto again; bn_check_top(rnd); return(1); }
void * vg_thread_loop(void *arg) { unsigned char hash_buf[128]; unsigned char *eckey_buf; unsigned char hash1[32]; int i, c, len, output_interval; int hash_len; const BN_ULONG rekey_max = 10000000; BN_ULONG npoints, rekey_at, nbatch; vg_context_t *vcp = (vg_context_t *) arg; EC_KEY *pkey = NULL; const EC_GROUP *pgroup; const EC_POINT *pgen; const int ptarraysize = 256; EC_POINT *ppnt[ptarraysize]; EC_POINT *pbatchinc; vg_test_func_t test_func = vcp->vc_test; vg_exec_context_t ctx; vg_exec_context_t *vxcp; struct timeval tvstart; memset(&ctx, 0, sizeof(ctx)); vxcp = &ctx; vg_exec_context_init(vcp, &ctx); pkey = vxcp->vxc_key; pgroup = EC_KEY_get0_group(pkey); pgen = EC_GROUP_get0_generator(pgroup); for (i = 0; i < ptarraysize; i++) { ppnt[i] = EC_POINT_new(pgroup); if (!ppnt[i]) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } } pbatchinc = EC_POINT_new(pgroup); if (!pbatchinc) { fprintf(stderr, "ERROR: out of memory?\n"); exit(1); } BN_set_word(&vxcp->vxc_bntmp, ptarraysize); EC_POINT_mul(pgroup, pbatchinc, &vxcp->vxc_bntmp, NULL, NULL, vxcp->vxc_bnctx); EC_POINT_make_affine(pgroup, pbatchinc, vxcp->vxc_bnctx); npoints = 0; rekey_at = 0; nbatch = 0; vxcp->vxc_key = pkey; vxcp->vxc_binres[0] = vcp->vc_addrtype; c = 0; output_interval = 1000; gettimeofday(&tvstart, NULL); if (vcp->vc_format == VCF_SCRIPT) { hash_buf[ 0] = 0x51; // OP_1 hash_buf[ 1] = 0x41; // pubkey length // gap for pubkey hash_buf[67] = 0x51; // OP_1 hash_buf[68] = 0xae; // OP_CHECKMULTISIG eckey_buf = hash_buf + 2; hash_len = 69; } else { eckey_buf = hash_buf; hash_len = 65; } while (!vcp->vc_halt) { if (++npoints >= rekey_at) { vg_exec_context_upgrade_lock(vxcp); /* Generate a new random private key */ EC_KEY_generate_key(pkey); npoints = 0; /* Determine rekey interval */ EC_GROUP_get_order(pgroup, &vxcp->vxc_bntmp, vxcp->vxc_bnctx); BN_sub(&vxcp->vxc_bntmp2, &vxcp->vxc_bntmp, EC_KEY_get0_private_key(pkey)); rekey_at = BN_get_word(&vxcp->vxc_bntmp2); if ((rekey_at == BN_MASK2) || (rekey_at > rekey_max)) rekey_at = rekey_max; assert(rekey_at > 0); EC_POINT_copy(ppnt[0], EC_KEY_get0_public_key(pkey)); vg_exec_context_downgrade_lock(vxcp); npoints++; vxcp->vxc_delta = 0; if (vcp->vc_pubkey_base) EC_POINT_add(pgroup, ppnt[0], ppnt[0], vcp->vc_pubkey_base, vxcp->vxc_bnctx); for (nbatch = 1; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch-1], pgen, vxcp->vxc_bnctx); } } else { /* * Common case * * EC_POINT_add() can skip a few multiplies if * one or both inputs are affine (Z_is_one). * This is the case for every point in ppnt, as * well as pbatchinc. */ assert(nbatch == ptarraysize); for (nbatch = 0; (nbatch < ptarraysize) && (npoints < rekey_at); nbatch++, npoints++) { EC_POINT_add(pgroup, ppnt[nbatch], ppnt[nbatch], pbatchinc, vxcp->vxc_bnctx); } } /* * The single most expensive operation performed in this * loop is modular inversion of ppnt->Z. There is an * algorithm implemented in OpenSSL to do batched inversion * that only does one actual BN_mod_inverse(), and saves * a _lot_ of time. * * To take advantage of this, we batch up a few points, * and feed them to EC_POINTs_make_affine() below. */ EC_POINTs_make_affine(pgroup, nbatch, ppnt, vxcp->vxc_bnctx); for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) { /* Hash the public key */ len = EC_POINT_point2oct(pgroup, ppnt[i], POINT_CONVERSION_UNCOMPRESSED, eckey_buf, 65, vxcp->vxc_bnctx); assert(len == 65); SHA256(hash_buf, hash_len, hash1); RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]); switch (test_func(vxcp)) { case 1: npoints = 0; rekey_at = 0; i = nbatch; break; case 2: goto out; default: break; } } c += i; if (c >= output_interval) { output_interval = vg_output_timing(vcp, c, &tvstart); if (output_interval > 250000) output_interval = 250000; c = 0; } vg_exec_context_yield(vxcp); } out: vg_exec_context_del(&ctx); vg_context_thread_exit(vcp); for (i = 0; i < ptarraysize; i++) if (ppnt[i]) EC_POINT_free(ppnt[i]); if (pbatchinc) EC_POINT_free(pbatchinc); return NULL; }
/* * Find the bignum ranges that produce a given prefix. */ static int get_prefix_ranges(int addrtype, const char *pfx, BIGNUM **result, BN_CTX *bnctx) { int i, p, c; int zero_prefix = 0; int check_upper = 0; int b58pow, b58ceil, b58top = 0; int ret = -1; BIGNUM bntarg, bnceil, bnfloor; BIGNUM bnbase; BIGNUM *bnap, *bnbp, *bntp; BIGNUM *bnhigh = NULL, *bnlow = NULL, *bnhigh2 = NULL, *bnlow2 = NULL; BIGNUM bntmp, bntmp2; BN_init(&bntarg); BN_init(&bnceil); BN_init(&bnfloor); BN_init(&bnbase); BN_init(&bntmp); BN_init(&bntmp2); BN_set_word(&bnbase, 58); p = strlen(pfx); for (i = 0; i < p; i++) { c = vg_b58_reverse_map[(int)pfx[i]]; if (c == -1) { fprintf(stderr, "Invalid character '%c' in prefix '%s'\n", pfx[i], pfx); goto out; } if (i == zero_prefix) { if (c == 0) { /* Add another zero prefix */ zero_prefix++; if (zero_prefix > 19) { fprintf(stderr, "Prefix '%s' is too long\n", pfx); goto out; } continue; } /* First non-zero character */ b58top = c; BN_set_word(&bntarg, c); } else { BN_set_word(&bntmp2, c); BN_mul(&bntmp, &bntarg, &bnbase, bnctx); BN_add(&bntarg, &bntmp, &bntmp2); } } /* Power-of-two ceiling and floor values based on leading 1s */ BN_clear(&bntmp); BN_set_bit(&bntmp, 200 - (zero_prefix * 8)); BN_sub(&bnceil, &bntmp, BN_value_one()); BN_set_bit(&bnfloor, 192 - (zero_prefix * 8)); bnlow = BN_new(); bnhigh = BN_new(); if (b58top) { /* * If a non-zero was given in the prefix, find the * numeric boundaries of the prefix. */ BN_copy(&bntmp, &bnceil); bnap = &bntmp; bnbp = &bntmp2; b58pow = 0; while (BN_cmp(bnap, &bnbase) > 0) { b58pow++; BN_div(bnbp, NULL, bnap, &bnbase, bnctx); bntp = bnap; bnap = bnbp; bnbp = bntp; } b58ceil = BN_get_word(bnap); if ((b58pow - (p - zero_prefix)) < 6) { /* * Do not allow the prefix to constrain the * check value, this is ridiculous. */ fprintf(stderr, "Prefix '%s' is too long\n", pfx); goto out; } BN_set_word(&bntmp2, b58pow - (p - zero_prefix)); BN_exp(&bntmp, &bnbase, &bntmp2, bnctx); BN_mul(bnlow, &bntmp, &bntarg, bnctx); BN_sub(&bntmp2, &bntmp, BN_value_one()); BN_add(bnhigh, bnlow, &bntmp2); if (b58top <= b58ceil) { /* Fill out the upper range too */ check_upper = 1; bnlow2 = BN_new(); bnhigh2 = BN_new(); BN_mul(bnlow2, bnlow, &bnbase, bnctx); BN_mul(&bntmp2, bnhigh, &bnbase, bnctx); BN_set_word(&bntmp, 57); BN_add(bnhigh2, &bntmp2, &bntmp); /* * Addresses above the ceiling will have one * fewer "1" prefix in front than we require. */ if (BN_cmp(&bnceil, bnlow2) < 0) { /* High prefix is above the ceiling */ check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bnceil, bnhigh2) < 0) /* High prefix is partly above the ceiling */ BN_copy(bnhigh2, &bnceil); /* * Addresses below the floor will have another * "1" prefix in front instead of our target. */ if (BN_cmp(&bnfloor, bnhigh) >= 0) { /* Low prefix is completely below the floor */ assert(check_upper); check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bnfloor, bnlow) > 0) { /* Low prefix is partly below the floor */ BN_copy(bnlow, &bnfloor); } } } else { BN_copy(bnhigh, &bnceil); BN_clear(bnlow); } /* Limit the prefix to the address type */ BN_clear(&bntmp); BN_set_word(&bntmp, addrtype); BN_lshift(&bntmp2, &bntmp, 192); if (check_upper) { if (BN_cmp(&bntmp2, bnhigh2) > 0) { check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnlow2) > 0) BN_copy(bnlow2, &bntmp2); } if (BN_cmp(&bntmp2, bnhigh) > 0) { if (!check_upper) goto not_possible; check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnlow) > 0) { BN_copy(bnlow, &bntmp2); } BN_set_word(&bntmp, addrtype + 1); BN_lshift(&bntmp2, &bntmp, 192); if (check_upper) { if (BN_cmp(&bntmp2, bnlow2) < 0) { check_upper = 0; BN_free(bnhigh2); bnhigh2 = NULL; BN_free(bnlow2); bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnhigh2) < 0) BN_copy(bnlow2, &bntmp2); } if (BN_cmp(&bntmp2, bnlow) < 0) { if (!check_upper) goto not_possible; check_upper = 0; BN_free(bnhigh); bnhigh = bnhigh2; bnhigh2 = NULL; BN_free(bnlow); bnlow = bnlow2; bnlow2 = NULL; } else if (BN_cmp(&bntmp2, bnhigh) < 0) { BN_copy(bnhigh, &bntmp2); } /* Address ranges are complete */ assert(check_upper || ((bnlow2 == NULL) && (bnhigh2 == NULL))); result[0] = bnlow; result[1] = bnhigh; result[2] = bnlow2; result[3] = bnhigh2; bnlow = NULL; bnhigh = NULL; bnlow2 = NULL; bnhigh2 = NULL; ret = 0; if (0) { not_possible: ret = -2; } out: BN_clear_free(&bntarg); BN_clear_free(&bnceil); BN_clear_free(&bnfloor); BN_clear_free(&bnbase); BN_clear_free(&bntmp); BN_clear_free(&bntmp2); if (bnhigh) BN_free(bnhigh); if (bnlow) BN_free(bnlow); if (bnhigh2) BN_free(bnhigh2); if (bnlow2) BN_free(bnlow2); return ret; }
void * d2i_bio_max(const ASN1_ITEM *it, BIO *in, void *x, unsigned int max) { AUTO(uint8_t, buf); AUTO(BIGNUM, size); AUTO(BIGNUM, cmp); size_t blocks = 0; ssize_t need = 0; size_t have = 0; int rd; size = BN_new(); if (size == NULL) return NULL; while (true) { need = get_size(buf, have, size); if (need < 0) return NULL; else if (need == 0) break; if (have + need > max) return NULL; if (have + (size_t) need >= blocks * BLOCKSIZE) { uint8_t *tmp; blocks = (have + need + BLOCKSIZE - 1) / BLOCKSIZE; tmp = realloc(buf, blocks * BLOCKSIZE); if (tmp == NULL) return NULL; buf = tmp; } rd = BIO_read(in, buf + have, need); have += need; if (rd <= 0 || rd != need) return NULL; } cmp = BN_new(); if (cmp == NULL) return NULL; if (BN_set_word(cmp, max) <= 0) return NULL; if (BN_cmp(size, cmp) > 0) return NULL; if (BN_set_word(cmp, BLOCKSIZE) <= 0) return NULL; while (true) { need = BLOCKSIZE; if (BN_cmp(size, cmp) < 0) need = BN_get_word(size); if (need == 0) break; if (BN_sub_word(size, need) <= 0) return NULL; if (have + (size_t) need >= blocks * BLOCKSIZE) { uint8_t *tmp; blocks = (have + need + BLOCKSIZE - 1) / BLOCKSIZE; tmp = realloc(buf, blocks * BLOCKSIZE); if (tmp == NULL) return NULL; buf = tmp; } while (need > 0) { rd = BIO_read(in, buf + have, need); if (rd <= 0) return NULL; have += rd; need -= rd; } } return ASN1_item_d2i(x, &(const uint8_t *) { buf }, have, it); }
static int test_BN_bit(void) { BIGNUM *bn; int ret = 0; bn = BN_new(); /* test setting and getting of "word" */ if (!BN_set_word(bn, 1)) return 1; if (!BN_is_bit_set(bn, 0)) ret += 1; if (!BN_is_bit_set(bn, 0)) ret += 1; if (!BN_set_word(bn, 2)) return 1; if (!BN_is_bit_set(bn, 1)) ret += 1; if (!BN_set_word(bn, 3)) return 1; if (!BN_is_bit_set(bn, 0)) ret += 1; if (!BN_is_bit_set(bn, 1)) ret += 1; if (!BN_set_word(bn, 0x100)) return 1; if (!BN_is_bit_set(bn, 8)) ret += 1; if (!BN_set_word(bn, 0x1000)) return 1; if (!BN_is_bit_set(bn, 12)) ret += 1; /* test bitsetting */ if (!BN_set_word(bn, 1)) return 1; if (!BN_set_bit(bn, 1)) return 1; if (BN_get_word(bn) != 3) return 1; if (!BN_clear_bit(bn, 0)) return 1; if (BN_get_word(bn) != 2) return 1; /* test bitsetting past end of current end */ BN_clear(bn); if (!BN_set_bit(bn, 12)) return 1; if (BN_get_word(bn) != 0x1000) return 1; /* test bit and byte counting functions */ if (BN_num_bits(bn) != 13) return 1; if (BN_num_bytes(bn) != 2) return 1; BN_free(bn); return ret; }
void printnumber(FILE *f, const struct number *b, u_int base) { struct number *int_part, *fract_part; int digits; char buf[11]; size_t sz; int i; struct stack stack; char *p; charcount = 0; lastchar = -1; if (BN_is_zero(b->number)) putcharwrap(f, '0'); int_part = new_number(); fract_part = new_number(); fract_part->scale = b->scale; if (base <= 16) digits = 1; else { digits = snprintf(buf, sizeof(buf), "%u", base-1); } split_number(b, int_part->number, fract_part->number); i = 0; stack_init(&stack); while (!BN_is_zero(int_part->number)) { BN_ULONG rem = BN_div_word(int_part->number, base); stack_pushstring(&stack, get_digit(rem, digits, base)); i++; } sz = i; if (BN_cmp(b->number, &zero) < 0) putcharwrap(f, '-'); for (i = 0; i < sz; i++) { p = stack_popstring(&stack); if (base > 16) putcharwrap(f, ' '); printwrap(f, p); free(p); } stack_clear(&stack); if (b->scale > 0) { struct number *num_base; BIGNUM mult, stop; putcharwrap(f, '.'); num_base = new_number(); BN_set_word(num_base->number, base); BN_init(&mult); BN_one(&mult); BN_init(&stop); BN_one(&stop); scale_number(&stop, b->scale); i = 0; while (BN_cmp(&mult, &stop) < 0) { u_long rem; if (i && base > 16) putcharwrap(f, ' '); i = 1; bmul_number(fract_part, fract_part, num_base); split_number(fract_part, int_part->number, NULL); rem = BN_get_word(int_part->number); p = get_digit(rem, digits, base); int_part->scale = 0; normalize(int_part, fract_part->scale); BN_sub(fract_part->number, fract_part->number, int_part->number); printwrap(f, p); free(p); BN_mul_word(&mult, base); } free_number(num_base); BN_free(&mult); BN_free(&stop); } flushwrap(f); free_number(int_part); free_number(fract_part); }
static int vg_regex_test(vg_exec_context_t *vxcp) { vg_regex_context_t *vcrp = (vg_regex_context_t *) vxcp->vxc_vc; unsigned char hash1[32], hash2[32]; int i, zpfx, p, d, nres, re_vec[9]; char b58[40]; BIGNUM bnrem; BIGNUM *bn, *bndiv, *bnptmp; int res = 0; pcre *re; BN_init(&bnrem); /* Hash the hash and write the four byte check code */ SHA256(vxcp->vxc_binres, 21, hash1); SHA256(hash1, sizeof(hash1), hash2); memcpy(&vxcp->vxc_binres[21], hash2, 4); bn = &vxcp->vxc_bntmp; bndiv = &vxcp->vxc_bntmp2; BN_bin2bn(vxcp->vxc_binres, 25, bn); /* Compute the complete encoded address */ for (zpfx = 0; zpfx < 25 && vxcp->vxc_binres[zpfx] == 0; zpfx++); p = sizeof(b58) - 1; b58[p] = '\0'; while (!BN_is_zero(bn)) { BN_div(bndiv, &bnrem, bn, &vxcp->vxc_bnbase, vxcp->vxc_bnctx); bnptmp = bn; bn = bndiv; bndiv = bnptmp; d = BN_get_word(&bnrem); b58[--p] = vg_b58_alphabet[d]; } while (zpfx--) { b58[--p] = vg_b58_alphabet[0]; } /* * Run the regular expressions on it * SLOW, runs in linear time with the number of REs */ restart_loop: nres = vcrp->base.vc_npatterns; if (!nres) { res = 2; goto out; } for (i = 0; i < nres; i++) { d = pcre_exec(vcrp->vcr_regex[i], vcrp->vcr_regex_extra[i], &b58[p], (sizeof(b58) - 1) - p, 0, 0, re_vec, sizeof(re_vec)/sizeof(re_vec[0])); if (d <= 0) { if (d != PCRE_ERROR_NOMATCH) { fprintf(stderr, "PCRE error: %d\n", d); res = 2; goto out; } continue; } re = vcrp->vcr_regex[i]; if (vg_exec_context_upgrade_lock(vxcp) && ((i >= vcrp->base.vc_npatterns) || (vcrp->vcr_regex[i] != re))) goto restart_loop; vg_exec_context_consolidate_key(vxcp); vcrp->base.vc_output_match(&vcrp->base, vxcp->vxc_key, vcrp->vcr_regex_pat[i]); vcrp->base.vc_found++; if (vcrp->base.vc_only_one) { res = 2; goto out; } if (vcrp->base.vc_remove_on_match) { pcre_free(vcrp->vcr_regex[i]); if (vcrp->vcr_regex_extra[i]) pcre_free(vcrp->vcr_regex_extra[i]); nres -= 1; vcrp->base.vc_npatterns = nres; if (!nres) { res = 2; goto out; } vcrp->vcr_regex[i] = vcrp->vcr_regex[nres]; vcrp->vcr_regex_extra[i] = vcrp->vcr_regex_extra[nres]; vcrp->vcr_regex_pat[i] = vcrp->vcr_regex_pat[nres]; vcrp->base.vc_npatterns = nres; vcrp->base.vc_pattern_generation++; } res = 1; } out: BN_clear_free(&bnrem); return res; }