int main() { BIGNUM two, three, four, five; BIGNUM answer; BN_CTX *context; size_t length; char *string; context = BN_CTX_new(); if (context == NULL) fail("BN_CTX_new"); /* answer = 5 ** 4 ** 3 ** 2 */ BN_init(&two); BN_init(&three); BN_init(&four); BN_init(&five); if (BN_set_word(&two, 2) == 0 || BN_set_word(&three, 3) == 0 || BN_set_word(&four, 4) == 0 || BN_set_word(&five, 5) == 0) fail("BN_set_word"); BN_init(&answer); if (BN_exp(&answer, &three, &two, context) == 0 || BN_exp(&answer, &four, &answer, context) == 0 || BN_exp(&answer, &five, &answer, context) == 0) fail("BN_exp"); /* string = decimal answer */ string = BN_bn2dec(&answer); if (string == NULL) fail("BN_bn2dec"); length = strlen(string); printf(" First 20 digits: %.20s\n", string); if (length >= 20) printf(" Last 20 digits: %.20s\n", string + length - 20); printf("Number of digits: %zd\n", length); OPENSSL_free(string); BN_free(&answer); BN_free(&five); BN_free(&four); BN_free(&three); BN_free(&two); BN_CTX_free(context); return 0; }
// http://stackoverflow.com/questions/356090/how-to-compute-the-nth-root-of-a-very-big-integer static BIGNUM *nearest_cuberoot(BIGNUM *in) { BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); BIGNUM *three = BN_CTX_get(ctx); BIGNUM *high = BN_CTX_get(ctx); BIGNUM *mid = BN_CTX_get(ctx); BIGNUM *low = BN_CTX_get(ctx); BIGNUM *tmp = BN_CTX_get(ctx); BN_set_word(three, 3); // Create the constant 3 BN_set_word(high, 1); // high = 1 do { BN_lshift1(high, high); // high = high << 1 (high * 2) BN_exp(tmp, high, three, ctx); // tmp = high^3 } while (BN_ucmp(tmp, in) <= -1); // while (tmp < in) BN_rshift1(low, high); // low = high >> 1 (high / 2) while (BN_ucmp(low, high) <= -1) // while (low < high) { BN_add(tmp, low, high); // tmp = low + high BN_rshift1(mid, tmp); // mid = tmp >> 1 (tmp / 2) BN_exp(tmp, mid, three, ctx); // tmp = mid^3 if (BN_ucmp(low, mid) <= -1 && BN_ucmp(tmp, in) <= -1) // if (low < mid && tmp < in) BN_copy(low, mid); // low = mid else if (BN_ucmp(high, mid) >= 1 && BN_ucmp(tmp, in) >= 1) // else if (high > mid && tmp > in) BN_copy(high, mid); // high = mid else { // subtract 1 from mid because 1 will be added after the loop BN_sub_word(mid, 1); // mid -= 1 break; } } BN_add_word(mid, 1); // mid += 1 BIGNUM *result = BN_dup(mid); BN_CTX_end(ctx); BN_CTX_free(ctx); return result; }
void split_number(const struct number *n, BIGNUM *i, BIGNUM *f) { u_long rem; bn_checkp(BN_copy(i, n->number)); if (n->scale == 0 && f != NULL) bn_check(BN_zero(f)); else if (n->scale < sizeof(factors)/sizeof(factors[0])) { rem = BN_div_word(i, factors[n->scale]); if (f != NULL) bn_check(BN_set_word(f, rem)); } else { BIGNUM *a, *p; BN_CTX *ctx; a = BN_new(); bn_checkp(a); p = BN_new(); bn_checkp(p); ctx = BN_CTX_new(); bn_checkp(ctx); bn_check(BN_set_word(a, 10)); bn_check(BN_set_word(p, n->scale)); bn_check(BN_exp(a, a, p, ctx)); bn_check(BN_div(i, f, n->number, a, ctx)); BN_CTX_free(ctx); BN_free(a); BN_free(p); } }
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; }
/** https://core.telegram.org/api/end-to-end says: "Both clients in a secret chat creation are to check that g, g_a and g_b are greater than one and smaller than p-1. Recommented checking that g_a and g_b are between 2^{2048-64} and p - 2^{2048-64} as well." */ qint32 CryptoUtils::checkCalculatedParams(const BIGNUM *gAOrB, const BIGNUM *g, const BIGNUM *p) { ASSERT(gAOrB); ASSERT(g); ASSERT(p); // 1) gAOrB and g greater than one and smaller than p-1 BIGNUM one; BN_init(&one); Utils::ensure(BN_one(&one)); BIGNUM *pMinusOne = BN_dup(p); Utils::ensure(BN_sub_word(pMinusOne, 1)); // check params greater than one if (BN_cmp(gAOrB, &one) <= 0) return -1; if (BN_cmp(g, &one) <= 0) return -1; // check params <= p-1 if (BN_cmp(gAOrB, pMinusOne) >= 0) return -1; if (BN_cmp(g, pMinusOne) >= 0) return -1; // 2) gAOrB between 2^{2048-64} and p - 2^{2048-64} quint64 expWord = 2048 - 64; BIGNUM exp; BN_init(&exp); Utils::ensure(BN_set_word(&exp, expWord)); BIGNUM base; BN_init(&base); Utils::ensure(BN_set_word(&base, 2)); // lowLimit = base ^ exp BIGNUM lowLimit; BN_init(&lowLimit); Utils::ensure(BN_exp(&lowLimit, &base, &exp, BN_ctx)); // highLimit = p - lowLimit BIGNUM highLimit; BN_init(&highLimit); BN_sub(&highLimit, p, &lowLimit); if (BN_cmp(gAOrB, &lowLimit) < 0) return -1; if (BN_cmp(gAOrB, &highLimit) > 0) return -1; BN_free(&one); BN_free(pMinusOne); BN_free(&exp); BN_free(&lowLimit); BN_free(&highLimit); delete g; delete gAOrB; delete p; return 0; }
BigNumber BigNumber::exp(const BigNumber &bn) { BigNumber ret; BN_CTX *bnctx; bnctx = BN_CTX_new(); BN_exp(ret.m_bn, m_bn, bn.m_bn, bnctx); BN_CTX_free(bnctx); 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; }
void openssl_bioBN_math() { BIO *outs; BN_CTX *ctx; char num1[8], num2[8]; BIGNUM *bg1, *bg2, *tmp, *stp; bg1 = BN_new(); bg2 = BN_new(); tmp = BN_new(); ctx = BN_CTX_new(); strcpy(num1, "84"); strcpy(num2, "3"); BN_hex2bn(&bg1, num1); BN_hex2bn(&bg2, num2); outs = BIO_new(BIO_s_file()); BIO_set_fp(outs, stdout, BIO_NOCLOSE); printf("\nBIO_MATH as follow:\n"); BN_add(tmp, bg1, bg2); BIO_puts(outs, "\tbn(0x84 + 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_sub(tmp, bg1, bg2); BIO_puts(outs, "\tbn(0x84 - 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_mul(tmp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 * 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_sqr(tmp, bg1, ctx); BIO_puts(outs, "\tbn(sqr(0x84)) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_div(tmp, stp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 / 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_exp(tmp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 e 0x03)= 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_free(bg1); BN_free(bg2); BN_free(tmp); BIO_free(outs); }
int test_mod_exp(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*c,*d,*e; int i; a=BN_new(); b=BN_new(); c=BN_new(); d=BN_new(); e=BN_new(); BN_bntest_rand(c,30,0,1); /* must be odd for montgomery */ for (i=0; i<num2; i++) { BN_bntest_rand(a,20+i*5,0,0); /**/ BN_bntest_rand(b,2+i,0,0); /**/ if (!BN_mod_exp(d,a,b,c,ctx)) return(00); if (bp != NULL) { if (!results) { BN_print(bp,a); BIO_puts(bp," ^ "); BN_print(bp,b); BIO_puts(bp," % "); BN_print(bp,c); BIO_puts(bp," - "); } BN_print(bp,d); BIO_puts(bp,"\n"); } BN_exp(e,a,b,ctx); BN_sub(e,e,d); BN_div(a,b,e,c,ctx); if(!BN_is_zero(b)) { fprintf(stderr,"Modulo exponentiation test failed!\n"); return 0; } } BN_free(a); BN_free(b); BN_free(c); BN_free(d); BN_free(e); return(1); }
int test_exp(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*d,*e,*one; int i; a=BN_new(); b=BN_new(); d=BN_new(); e=BN_new(); one=BN_new(); BN_one(one); for (i=0; i<num2; i++) { BN_bntest_rand(a,20+i*5,0,0); /**/ BN_bntest_rand(b,2+i,0,0); /**/ if (!BN_exp(d,a,b,ctx)) return(00); if (bp != NULL) { if (!results) { BN_print(bp,a); BIO_puts(bp," ^ "); BN_print(bp,b); BIO_puts(bp," - "); } BN_print(bp,d); BIO_puts(bp,"\n"); } BN_one(e); for( ; !BN_is_zero(b) ; BN_sub(b,b,one)) BN_mul(e,e,a,ctx); BN_sub(e,e,d); if(!BN_is_zero(e)) { fprintf(stderr,"Exponentiation test failed!\n"); return 0; } } BN_free(a); BN_free(b); BN_free(d); BN_free(e); BN_free(one); return(1); }
/* Multiply n by 10^s */ void scale_number(BIGNUM *n, int s) { unsigned int abs_scale; if (s == 0) return; abs_scale = s > 0 ? s : -s; if (abs_scale < sizeof(factors)/sizeof(factors[0])) { if (s > 0) bn_check(BN_mul_word(n, factors[abs_scale])); else BN_div_word(n, factors[abs_scale]); } else { BIGNUM *a, *p; BN_CTX *ctx; a = BN_new(); bn_checkp(a); p = BN_new(); bn_checkp(p); ctx = BN_CTX_new(); bn_checkp(ctx); bn_check(BN_set_word(a, 10)); bn_check(BN_set_word(p, abs_scale)); bn_check(BN_exp(a, a, p, ctx)); if (s > 0) bn_check(BN_mul(n, n, a, ctx)); else bn_check(BN_div(n, NULL, n, a, ctx)); BN_CTX_free(ctx); BN_free(a); BN_free(p); } }
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; }
/* * rsa_get_params(): - Get the important parameters of an RSA public key */ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, BIGNUM **modulusp, BIGNUM **r_squaredp) { BIGNUM *big1, *big2, *big32, *big2_32; BIGNUM *n, *r, *r_squared, *tmp; BN_CTX *bn_ctx = BN_CTX_new(); int ret = 0; /* Initialize BIGNUMs */ big1 = BN_new(); big2 = BN_new(); big32 = BN_new(); r = BN_new(); r_squared = BN_new(); tmp = BN_new(); big2_32 = BN_new(); n = BN_new(); if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 || !n) { fprintf(stderr, "Out of memory (bignum)\n"); return -ENOMEM; } if (0 != rsa_get_exponent(key, exponent)) ret = -1; if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) || !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L)) ret = -1; /* big2_32 = 2^32 */ if (!BN_exp(big2_32, big2, big32, bn_ctx)) ret = -1; /* Calculate n0_inv = -1 / n[0] mod 2^32 */ if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) || !BN_sub(tmp, big2_32, tmp)) ret = -1; *n0_invp = BN_get_word(tmp); /* Calculate R = 2^(# of key bits) */ if (!BN_set_word(tmp, BN_num_bits(n)) || !BN_exp(r, big2, tmp, bn_ctx)) ret = -1; /* Calculate r_squared = R^2 mod n */ if (!BN_copy(r_squared, r) || !BN_mul(tmp, r_squared, r, bn_ctx) || !BN_mod(r_squared, tmp, n, bn_ctx)) ret = -1; *modulusp = n; *r_squaredp = r_squared; BN_free(big1); BN_free(big2); BN_free(big32); BN_free(r); BN_free(tmp); BN_free(big2_32); if (ret) { fprintf(stderr, "Bignum operations failed\n"); return -ENOMEM; } return ret; }
static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) { if (!threeValidHandles(env, r, a, p)) return JNI_FALSE; Unique_BN_CTX ctx(BN_CTX_new()); return BN_exp(r, a, p, ctx.get()); }
/** * public static native int BN_exp(int, int, int, int) */ static jboolean NativeBN_BN_exp(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* p, BN_CTX* ctx) { if (!threeValidHandles(env, r, a, p)) return FALSE; return BN_exp(r, a, p, ctx); }
int vb_keyb_from_rsa(struct rsa_st *rsa_private_key, uint8_t **keyb_data, uint32_t *keyb_size) { uint32_t i, nwords; BIGNUM *N = NULL; BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL; BIGNUM *B = NULL; BIGNUM *N0inv = NULL, *R = NULL, *RR = NULL; BIGNUM *RRTemp = NULL, *NnumBits = NULL; BIGNUM *n = NULL, *rr = NULL; BN_CTX *bn_ctx = BN_CTX_new(); uint32_t n0invout; uint32_t bufsize; uint32_t *outbuf; int retval = 1; /* Size of RSA key in 32-bit words */ nwords = BN_num_bits(rsa_private_key->n) / 32; bufsize = (2 + nwords + nwords) * sizeof(uint32_t); outbuf = malloc(bufsize); if (!outbuf) goto done; *keyb_data = (uint8_t *)outbuf; *keyb_size = bufsize; *outbuf++ = nwords; /* Initialize BIGNUMs */ #define NEW_BIGNUM(x) do { x = BN_new(); if (!x) goto done; } while (0) NEW_BIGNUM(N); NEW_BIGNUM(Big1); NEW_BIGNUM(Big2); NEW_BIGNUM(Big32); NEW_BIGNUM(BigMinus1); NEW_BIGNUM(N0inv); NEW_BIGNUM(R); NEW_BIGNUM(RR); NEW_BIGNUM(RRTemp); NEW_BIGNUM(NnumBits); NEW_BIGNUM(n); NEW_BIGNUM(rr); NEW_BIGNUM(B); #undef NEW_BIGNUM BN_copy(N, rsa_private_key->n); BN_set_word(Big1, 1L); BN_set_word(Big2, 2L); BN_set_word(Big32, 32L); BN_sub(BigMinus1, Big1, Big2); BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */ /* Calculate and output N0inv = -1 / N[0] mod 2^32 */ BN_mod_inverse(N0inv, N, B, bn_ctx); BN_sub(N0inv, B, N0inv); n0invout = BN_get_word(N0inv); *outbuf++ = n0invout; /* Calculate R = 2^(# of key bits) */ BN_set_word(NnumBits, BN_num_bits(N)); BN_exp(R, Big2, NnumBits, bn_ctx); /* Calculate RR = R^2 mod N */ BN_copy(RR, R); BN_mul(RRTemp, RR, R, bn_ctx); BN_mod(RR, RRTemp, N, bn_ctx); /* Write out modulus as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t nout; BN_mod(n, N, B, bn_ctx); /* n = N mod B */ nout = BN_get_word(n); *outbuf++ = nout; BN_rshift(N, N, 32); /* N = N/B */ } /* Write R^2 as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t rrout; BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */ rrout = BN_get_word(rr); *outbuf++ = rrout; BN_rshift(RR, RR, 32); /* RR = RR/B */ } outbuf = NULL; retval = 0; done: free(outbuf); /* Free BIGNUMs. */ BN_free(Big1); BN_free(Big2); BN_free(Big32); BN_free(BigMinus1); BN_free(N0inv); BN_free(R); BN_free(RRTemp); BN_free(NnumBits); BN_free(n); BN_free(rr); return retval; }
/* Pre-processes and outputs RSA public key to standard out. */ void output(RSA* key) { int i, nwords; BIGNUM *N = key->n; BIGNUM *Big1, *Big2, *Big32, *BigMinus1; BIGNUM *B; BIGNUM *N0inv, *R, *RR, *RRTemp, *NnumBits; BIGNUM *n, *rr; BN_CTX *bn_ctx = BN_CTX_new(); uint32_t n0invout; N = key->n; /* Output size of RSA key in 32-bit words */ nwords = BN_num_bits(N) / 32; write(1, &nwords, sizeof(nwords)); /* Initialize BIGNUMs */ Big1 = BN_new(); Big2 = BN_new(); Big32 = BN_new(); BigMinus1 = BN_new(); N0inv= BN_new(); R = BN_new(); RR = BN_new(); RRTemp = BN_new(); NnumBits = BN_new(); n = BN_new(); rr = BN_new(); BN_set_word(Big1, 1L); BN_set_word(Big2, 2L); BN_set_word(Big32, 32L); BN_sub(BigMinus1, Big1, Big2); B = BN_new(); BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */ /* Calculate and output N0inv = -1 / N[0] mod 2^32 */ BN_mod_inverse(N0inv, N, B, bn_ctx); BN_sub(N0inv, B, N0inv); n0invout = BN_get_word(N0inv); write(1, &n0invout, sizeof(n0invout)); /* Calculate R = 2^(# of key bits) */ BN_set_word(NnumBits, BN_num_bits(N)); BN_exp(R, Big2, NnumBits, bn_ctx); /* Calculate RR = R^2 mod N */ BN_copy(RR, R); BN_mul(RRTemp, RR, R, bn_ctx); BN_mod(RR, RRTemp, N, bn_ctx); /* Write out modulus as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t nout; BN_mod(n, N, B, bn_ctx); /* n = N mod B */ nout = BN_get_word(n); write(1, &nout, sizeof(nout)); BN_rshift(N, N, 32); /* N = N/B */ } /* Write R^2 as little endian array of integers. */ for (i = 0; i < nwords; ++i) { uint32_t rrout; BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */ rrout = BN_get_word(rr); write(1, &rrout, sizeof(rrout)); BN_rshift(RR, RR, 32); /* RR = RR/B */ } /* Free BIGNUMs. */ BN_free(Big1); BN_free(Big2); BN_free(Big32); BN_free(BigMinus1); BN_free(N0inv); BN_free(R); BN_free(RRTemp); BN_free(NnumBits); BN_free(n); BN_free(rr); }
/* * 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; }
extern "C" void Java_java_math_NativeBN_BN_1exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) { if (!threeValidHandles(env, r, a, p)) return; Unique_BN_CTX ctx(BN_CTX_new()); BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get()); throwExceptionIfNecessary(env); }