static int dh_bn_mod_exp(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { if (a->top == 1) { BN_ULONG A = a->d[0]; return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx); } else return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx); }
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { /* * If a is only one word long and constant time is false, use the faster * exponenentiation function. */ if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) { BN_ULONG A = a->d[0]; return BN_mod_exp_mont_word(r, A, p, m, ctx, m_ctx); } else return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); }
# ifdef MONT_EXP_WORD if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_CONSTTIME) == 0)) { BN_ULONG A = a->d[0]; ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL); } else # endif ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL);
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero() { BIGNUM *a = NULL, *p = NULL, *m = NULL; BIGNUM *r = NULL; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; m = BN_new(); if (!m) goto err; BN_one(m); a = BN_new(); if (!a) goto err; BN_one(a); p = BN_new(); if (!p) goto err; BN_zero(p); r = BN_new(); if (!r) goto err; if (!BN_rand(a, 1024, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) goto err; if (!BN_mod_exp(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp", r, a)) failed = 1; if (!BN_mod_exp_recp(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_recp", r, a)) failed = 1; if (!BN_mod_exp_simple(r, a, p, m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_simple", r, a)) failed = 1; if (!BN_mod_exp_mont(r, a, p, m, ctx, NULL)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_mont", r, a)) failed = 1; if (!BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL)) { goto err; } if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a)) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL)) goto err; if (!BN_is_zero(r)) { fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); fprintf(stderr, "r = "); BN_print_fp(stderr, r); fprintf(stderr, "\n"); return 0; } ret = failed; err: BN_free(r); BN_free(a); BN_free(p); BN_free(m); BN_CTX_free(ctx); return ret; }
/* * test_mod_exp_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_mod_exp_zero(void) { BIGNUM *a = NULL, *p = NULL, *m = NULL; BIGNUM *r = NULL; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; if (!TEST_ptr(m = BN_new()) || !TEST_ptr(a = BN_new()) || !TEST_ptr(p = BN_new()) || !TEST_ptr(r = BN_new())) goto err; BN_one(m); BN_one(a); BN_zero(p); if (!TEST_true(BN_rand(a, 1024, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))) goto err; if (!TEST_true(BN_mod_exp(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_recp(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_recp", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_simple(r, a, p, m, ctx))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_simple", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_mont(r, a, p, m, ctx, NULL))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont", r, a))) failed = 1; if (!TEST_true(BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL))) goto err; if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a))) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!TEST_true(BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL))) goto err; if (!TEST_BN_eq_zero(r)) { TEST_error("BN_mod_exp_mont_word failed: " "1 ** 0 mod 1 = r (should be 0)"); BN_print_var(r); goto err; } ret = !failed; err: BN_free(r); BN_free(a); BN_free(p); BN_free(m); BN_CTX_free(ctx); return ret; }
uint32 reg_proto_generate_prebuild_dhkeypair(DH **DHKeyPair, BufferObj *pubKey, uint8 *prebuild_privkey) { BIGNUM *pub_key = NULL, *priv_key = NULL; BN_CTX *ctx = NULL; BN_MONT_CTX *mont; uint8 temp[SIZE_PUB_KEY]; uint32 g = 0; uint32 ret = RPROT_ERR_CRYPTO; *DHKeyPair = DH_new(); if (*DHKeyPair == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_new failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->p = BN_new(); if ((*DHKeyPair)->p == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new p failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->g = BN_new(); if ((*DHKeyPair)->g == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new g failed\n")); return RPROT_ERR_CRYPTO; } /* 2. load the value of P */ if (BN_bin2bn(DH_P_VALUE, BUF_SIZE_1536_BITS, (*DHKeyPair)->p) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value p failed\n")); return RPROT_ERR_CRYPTO; } /* 3. load the value of G */ g = WpsHtonl(DH_G_VALUE); if (BN_bin2bn((uint8 *)&g, 4, (*DHKeyPair)->g) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value g failed\n")); return RPROT_ERR_CRYPTO; } /* 4. generate the DH key */ ctx = BN_CTX_new(); if (ctx == NULL) goto err; priv_key = BN_new(); if (priv_key == NULL) goto err; pub_key = BN_new(); if (pub_key == NULL) goto err; if (!BN_bin2bn(prebuild_privkey, SIZE_PUB_KEY, priv_key)) goto err; if ((*DHKeyPair)->flags & DH_FLAG_CACHE_MONT_P) { if (((*DHKeyPair)->method_mont_p = BN_MONT_CTX_new()) != NULL) if (!BN_MONT_CTX_set((BN_MONT_CTX *)(*DHKeyPair)->method_mont_p, (*DHKeyPair)->p, ctx)) goto err; } mont = (BN_MONT_CTX *)(*DHKeyPair)->method_mont_p; if ((*DHKeyPair)->g->top == 1) { BN_ULONG A = (*DHKeyPair)->g->d[0]; if (!BN_mod_exp_mont_word(pub_key, A, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; } else if (!BN_mod_exp_mont(pub_key, (*DHKeyPair)->g, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; (*DHKeyPair)->pub_key = pub_key; (*DHKeyPair)->priv_key = priv_key; if (BN_num_bytes((*DHKeyPair)->pub_key) == 0) goto err; /* 5. extract the DH public key */ if (reg_proto_BN_bn2bin((*DHKeyPair)->pub_key, temp) != SIZE_PUB_KEY) { TUTRACE((TUTRACE_ERR, "RPROTO: invalid public key length\n")); goto err; } buffobj_Append(pubKey, SIZE_PUB_KEY, temp); ret = WPS_SUCCESS; err: if ((pub_key != NULL) && ((*DHKeyPair)->pub_key == NULL)) BN_free(pub_key); if ((priv_key != NULL) && ((*DHKeyPair)->priv_key == NULL)) BN_free(priv_key); if (ctx) BN_CTX_free(ctx); return ret; }
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero(void) { BIGNUM a, p, m; BIGNUM r; BN_ULONG one_word = 1; BN_CTX *ctx = BN_CTX_new(); int ret = 1, failed = 0; BN_init(&m); BN_one(&m); BN_init(&a); BN_one(&a); BN_init(&p); BN_zero(&p); BN_init(&r); if (!BN_rand(&a, 1024, 0, 0)) goto err; if (!BN_mod_exp(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp", &r, &a)) failed = 1; if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a)) failed = 1; if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a)) failed = 1; if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL)) goto err; if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a)) failed = 1; if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) { goto err; } if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a)) failed = 1; /* * A different codepath exists for single word multiplication * in non-constant-time only. */ if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL)) goto err; if (!BN_is_zero(&r)) { fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); fprintf(stderr, "r = "); BN_print_fp(stderr, &r); fprintf(stderr, "\n"); return 0; } ret = failed; err: BN_free(&r); BN_free(&a); BN_free(&p); BN_free(&m); BN_CTX_free(ctx); return ret; }