static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *X = NULL; const BIGNUM *order; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; int order_bits; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!EC_KEY_can_sign(eckey)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ X = BN_new(); if (k == NULL || r == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } order = EC_GROUP_get0_order(group); if (order == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } /* Preallocate space */ order_bits = BN_num_bits(order); if (!BN_set_bit(k, order_bits) || !BN_set_bit(r, order_bits) || !BN_set_bit(X, order_bits)) goto err; do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_priv_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* Check if optimized inverse is implemented */ if (EC_GROUP_do_inverse_ord(group, k, k, ctx) == 0) { /* compute the inverse of k */ if (group->mont_data != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, group->mont_data)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx != ctx_in) BN_CTX_free(ctx); EC_POINT_free(tmp_point); BN_clear_free(X); return ret; }
/* some tests from the X9.62 draft */ int x9_62_test_internal(BIO *out, int nid, const char *r_in, const char *s_in) { int ret = 0; const char message[] = "abc"; unsigned char digest[20]; unsigned int dgst_len = 0; EVP_MD_CTX md_ctx; EC_KEY *key = NULL; ECDSA_SIG *signature = NULL; BIGNUM *r = NULL, *s = NULL; BIGNUM *kinv = NULL, *rp = NULL; EVP_MD_CTX_init(&md_ctx); /* get the message digest */ if (!EVP_DigestInit(&md_ctx, EVP_ecdsa()) || !EVP_DigestUpdate(&md_ctx, (const void *)message, 3) || !EVP_DigestFinal(&md_ctx, digest, &dgst_len)) goto x962_int_err; BIO_printf(out, "testing %s: ", OBJ_nid2sn(nid)); /* create the key */ if ((key = EC_KEY_new_by_curve_name(nid)) == NULL) goto x962_int_err; use_fake = 1; if (!EC_KEY_generate_key(key)) goto x962_int_err; BIO_printf(out, "."); (void)BIO_flush(out); /* create the signature */ use_fake = 1; /* Use ECDSA_sign_setup to avoid use of ECDSA nonces */ if (!ECDSA_sign_setup(key, NULL, &kinv, &rp)) goto x962_int_err; signature = ECDSA_do_sign_ex(digest, 20, kinv, rp, key); if (signature == NULL) goto x962_int_err; BIO_printf(out, "."); (void)BIO_flush(out); /* compare the created signature with the expected signature */ if ((r = BN_new()) == NULL || (s = BN_new()) == NULL) goto x962_int_err; if (!BN_dec2bn(&r, r_in) || !BN_dec2bn(&s, s_in)) goto x962_int_err; if (BN_cmp(signature->r, r) || BN_cmp(signature->s, s)) goto x962_int_err; BIO_printf(out, "."); (void)BIO_flush(out); /* verify the signature */ if (ECDSA_do_verify(digest, 20, signature, key) != 1) goto x962_int_err; BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); ret = 1; x962_int_err: if (!ret) BIO_printf(out, " failed\n"); EC_KEY_free(key); ECDSA_SIG_free(signature); BN_free(r); BN_free(s); EVP_MD_CTX_cleanup(&md_ctx); BN_clear_free(kinv); BN_clear_free(rp); return ret; }
static int run_srp(const char *username, const char *client_pass, const char *server_pass) { int ret = -1; BIGNUM *s = NULL; BIGNUM *v = NULL; BIGNUM *a = NULL; BIGNUM *b = NULL; BIGNUM *u = NULL; BIGNUM *x = NULL; BIGNUM *Apub = NULL; BIGNUM *Bpub = NULL; BIGNUM *Kclient = NULL; BIGNUM *Kserver = NULL; unsigned char rand_tmp[RANDOM_SIZE]; /* use builtin 1024-bit params */ const SRP_gN *GN = SRP_get_default_gN("1024"); if (GN == NULL) { fprintf(stderr, "Failed to get SRP parameters\n"); return -1; } /* Set up server's password entry */ if (!SRP_create_verifier_BN(username, server_pass, &s, &v, GN->N, GN->g)) { fprintf(stderr, "Failed to create SRP verifier\n"); return -1; } showbn("N", GN->N); showbn("g", GN->g); showbn("Salt", s); showbn("Verifier", v); /* Server random */ RAND_bytes(rand_tmp, sizeof(rand_tmp)); b = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); /* TODO - check b != 0 */ showbn("b", b); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); showbn("B", Bpub); if (!SRP_Verify_B_mod_N(Bpub, GN->N)) { fprintf(stderr, "Invalid B\n"); return -1; } /* Client random */ RAND_bytes(rand_tmp, sizeof(rand_tmp)); a = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); /* TODO - check a != 0 */ showbn("a", a); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); showbn("A", Apub); if (!SRP_Verify_A_mod_N(Apub, GN->N)) { fprintf(stderr, "Invalid A\n"); return -1; } /* Both sides calculate u */ u = SRP_Calc_u(Apub, Bpub, GN->N); /* Client's key */ x = SRP_Calc_x(s, username, client_pass); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); showbn("Client's key", Kclient); /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); showbn("Server's key", Kserver); if (BN_cmp(Kclient, Kserver) == 0) { ret = 0; } else { fprintf(stderr, "Keys mismatch\n"); ret = 1; } BN_clear_free(Kclient); BN_clear_free(Kserver); BN_clear_free(x); BN_free(u); BN_free(Apub); BN_clear_free(a); BN_free(Bpub); BN_clear_free(b); BN_free(s); BN_clear_free(v); return ret; }
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; }
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen, DSA *dsa) { BIGNUM *kinv=NULL,*r=NULL,*s=NULL; BIGNUM m; BIGNUM xr; BN_CTX *ctx=NULL; int i,reason=ERR_R_BN_LIB; DSA_SIG *ret=NULL; if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_DSA_DO_SIGN,FIPS_R_FIPS_SELFTEST_FAILED); return NULL; } if (FIPS_mode() && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_KEY_SIZE_TOO_SMALL); return NULL; } BN_init(&m); BN_init(&xr); if (!dsa->p || !dsa->q || !dsa->g) { reason=DSA_R_MISSING_PARAMETERS; goto err; } s=BN_new(); if (s == NULL) goto err; i=BN_num_bytes(dsa->q); /* should be 20 */ if ((dlen > i) || (dlen > 50)) { reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE; goto err; } ctx=BN_CTX_new(); if (ctx == NULL) goto err; if (!dsa->meth->dsa_sign_setup(dsa,ctx,&kinv,&r)) goto err; if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err; /* Compute s = inv(k) (m + xr) mod q */ if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */ if (!BN_add(s, &xr, &m)) goto err; /* s = m + xr */ if (BN_cmp(s,dsa->q) > 0) BN_sub(s,s,dsa->q); if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; ret= DSA_SIG_new(); if (ret == NULL) goto err; ret->r = r; ret->s = s; err: if (!ret) { DSAerr(DSA_F_DSA_DO_SIGN,reason); BN_free(r); BN_free(s); } if (ctx != NULL) BN_CTX_free(ctx); BN_clear_free(&m); BN_clear_free(&xr); if (kinv != NULL) /* dsa->kinv is NULL now if we used it */ BN_clear_free(kinv); return(ret); }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const uint8_t *digest, size_t digest_len) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return 0; } } else { ctx = ctx_in; } k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } tmp_point = EC_POINT_new(group); if (tmp_point == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } do { /* If possible, we'll include the private key and message digest in the k * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is * being used. */ do { int ok; if (digest_len > 0) { ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey), digest, digest_len, ctx); } else { ok = BN_rand_range(k, order); } if (!ok) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* We do not want timing information to leak the length of k, * so we compute G*k using an equivalent scalar of fixed * bit-length. */ if (!BN_add(k, k, order)) { goto err; } if (BN_num_bits(k) <= BN_num_bits(order)) { if (!BN_add(k, k, order)) { goto err; } } /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, X, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (!BN_mod_inverse(k, k, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx_in == NULL) { BN_CTX_free(ctx); } BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return ret; }
static bool bp_script_eval(GPtrArray *stack, const GString *script, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { struct const_buffer pc = { script->str, script->len }; struct const_buffer pend = { script->str + script->len, 0 }; struct const_buffer pbegincodehash = { script->str, script->len }; struct bscript_op op; bool rc = false; GByteArray *vfExec = g_byte_array_new(); GPtrArray *altstack = g_ptr_array_new_with_free_func( (GDestroyNotify) buffer_free); BIGNUM bn; BN_init(&bn); if (script->len > 10000) goto out; bool fStrictEncodings = flags & SCRIPT_VERIFY_STRICTENC; unsigned int nOpCount = 0; struct bscript_parser bp; bsp_start(&bp, &pc); while (pc.p < pend.p) { bool fExec = !count_false(vfExec); if (!bsp_getop(&op, &bp)) goto out; enum opcodetype opcode = op.op; if (op.data.len > 520) goto out; if (opcode > OP_16 && ++nOpCount > 201) goto out; if (disabled_op[opcode]) goto out; if (fExec && is_bsp_pushdata(opcode)) stack_push(stack, (struct buffer *) &op.data); else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: bn_set_int(&bn, (int)opcode - (int)(OP_1 - 1)); stack_push_str(stack, bn_getvch(&bn)); break; // // Control // case OP_NOP: case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } guint8 vc = (guint8) fValue; g_byte_array_append(vfExec, &vc, 1); break; } case OP_ELSE: { if (vfExec->len == 0) goto out; guint8 *v = &vfExec->data[vfExec->len - 1]; *v = !(*v); break; } case OP_ENDIF: if (vfExec->len == 0) goto out; g_byte_array_remove_index(vfExec, vfExec->len - 1); break; case OP_VERIFY: { if (stack->len < 1) goto out; bool fValue = CastToBool(stacktop(stack, -1)); if (fValue) popstack(stack); else goto out; break; } case OP_RETURN: goto out; // // Stack ops // case OP_TOALTSTACK: if (stack->len < 1) goto out; stack_push(altstack, stacktop(stack, -1)); popstack(stack); break; case OP_FROMALTSTACK: if (altstack->len < 1) goto out; stack_push(stack, stacktop(altstack, -1)); popstack(altstack); break; case OP_2DROP: // (x1 x2 -- ) if (stack->len < 2) goto out; popstack(stack); popstack(stack); break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack->len < 3) goto out; struct buffer *vch1 = stacktop(stack, -3); struct buffer *vch2 = stacktop(stack, -2); struct buffer *vch3 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); stack_push(stack, vch3); break; } case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack->len < 4) goto out; struct buffer *vch1 = stacktop(stack, -4); struct buffer *vch2 = stacktop(stack, -3); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack->len < 6) goto out; struct buffer *vch1 = stack_take(stack, -6); struct buffer *vch2 = stack_take(stack, -5); g_ptr_array_remove_range(stack, stack->len - 6, 2); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2SWAP: // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack->len < 4) goto out; stack_swap(stack, -4, -2); stack_swap(stack, -3, -1); break; case OP_IFDUP: { // (x - 0 | x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); if (CastToBool(vch)) stack_push(stack, vch); break; } case OP_DEPTH: // -- stacksize BN_set_word(&bn, stack->len); stack_push_str(stack, bn_getvch(&bn)); break; case OP_DROP: // (x -- ) if (stack->len < 1) goto out; popstack(stack); break; case OP_DUP: { // (x -- x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); stack_push(stack, vch); break; } case OP_NIP: // (x1 x2 -- x2) if (stack->len < 2) goto out; g_ptr_array_remove_index(stack, stack->len - 2); break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -2); stack_push(stack, vch); break; } case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack->len < 2) goto out; int n = stackint(stack, -1); popstack(stack); if (n < 0 || n >= (int)stack->len) goto out; struct buffer *vch = stacktop(stack, -n-1); if (opcode == OP_ROLL) { vch = buffer_copy(vch->p, vch->len); g_ptr_array_remove_index(stack, stack->len - n - 1); stack_push_nocopy(stack, vch); } else stack_push(stack, vch); break; } case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack->len < 3) goto out; stack_swap(stack, -3, -2); stack_swap(stack, -2, -1); break; } case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack->len < 2) goto out; stack_swap(stack, -2, -1); break; } case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -1); stack_insert(stack, vch, -2); break; } case OP_SIZE: { // (in -- in size) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); BN_set_word(&bn, vch->len); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_EQUAL: case OP_EQUALVERIFY: { // (x1 x2 - bool) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); bool fEqual = ((vch1->len == vch2->len) && memcmp(vch1->p, vch2->p, vch1->len) == 0); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack_push_char(stack, fEqual ? 1 : 0); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else goto out; } break; } // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack->len < 1) goto out; if (!CastToBigNum(&bn, stacktop(stack, -1))) goto out; switch (opcode) { case OP_1ADD: BN_add_word(&bn, 1); break; case OP_1SUB: BN_sub_word(&bn, 1); break; case OP_NEGATE: BN_set_negative(&bn, !BN_is_negative(&bn)); break; case OP_ABS: if (BN_is_negative(&bn)) BN_set_negative(&bn, 0); break; case OP_NOT: BN_set_word(&bn, BN_is_zero(&bn) ? 1 : 0); break; case OP_0NOTEQUAL: BN_set_word(&bn, BN_is_zero(&bn) ? 0 : 1); break; default: // impossible goto out; } popstack(stack); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack->len < 2) goto out; BIGNUM bn1, bn2; BN_init(&bn1); BN_init(&bn2); if (!CastToBigNum(&bn1, stacktop(stack, -2)) || !CastToBigNum(&bn2, stacktop(stack, -1))) { BN_clear_free(&bn1); BN_clear_free(&bn2); goto out; } switch (opcode) { case OP_ADD: BN_add(&bn, &bn1, &bn2); break; case OP_SUB: BN_sub(&bn, &bn1, &bn2); break; case OP_BOOLAND: BN_set_word(&bn, (!BN_is_zero(&bn1) && !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_BOOLOR: BN_set_word(&bn, (!BN_is_zero(&bn1) || !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) == 0) ? 1 : 0); break; case OP_NUMNOTEQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) != 0) ? 1 : 0); break; case OP_LESSTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) < 0) ? 1 : 0); break; case OP_GREATERTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) > 0) ? 1 : 0); break; case OP_LESSTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) <= 0) ? 1 : 0); break; case OP_GREATERTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) >= 0) ? 1 : 0); break; case OP_MIN: if (BN_cmp(&bn1, &bn2) < 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; case OP_MAX: if (BN_cmp(&bn1, &bn2) > 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; default: // impossible break; } popstack(stack); popstack(stack); stack_push_str(stack, bn_getvch(&bn)); BN_clear_free(&bn1); BN_clear_free(&bn2); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(stack, -1))) popstack(stack); else goto out; } break; } case OP_WITHIN: { // (x min max -- out) if (stack->len < 3) goto out; BIGNUM bn1, bn2, bn3; BN_init(&bn1); BN_init(&bn2); BN_init(&bn3); bool rc1 = CastToBigNum(&bn1, stacktop(stack, -3)); bool rc2 = CastToBigNum(&bn2, stacktop(stack, -2)); bool rc3 = CastToBigNum(&bn3, stacktop(stack, -1)); bool fValue = (BN_cmp(&bn2, &bn1) <= 0 && BN_cmp(&bn1, &bn3) < 0); popstack(stack); popstack(stack); popstack(stack); stack_push_char(stack, fValue ? 1 : 0); BN_clear_free(&bn1); BN_clear_free(&bn2); BN_clear_free(&bn3); if (!rc1 || !rc2 || !rc3) goto out; break; } // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); unsigned int hashlen; unsigned char md[32]; switch (opcode) { case OP_RIPEMD160: hashlen = 20; RIPEMD160(vch->p, vch->len, md); break; case OP_SHA1: hashlen = 20; SHA1(vch->p, vch->len, md); break; case OP_SHA256: hashlen = 32; SHA256(vch->p, vch->len, md); break; case OP_HASH160: hashlen = 20; bu_Hash160(md, vch->p, vch->len); break; case OP_HASH256: hashlen = 32; bu_Hash(md, vch->p, vch->len); break; default: // impossible goto out; } popstack(stack); struct buffer buf = { md, hashlen }; stack_push(stack, &buf); break; } case OP_CODESEPARATOR: // Hash starts after the code separator memcpy(&pbegincodehash, &pc, sizeof(pc)); break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack->len < 2) goto out; struct buffer *vchSig = stacktop(stack, -2); struct buffer *vchPubKey = stacktop(stack, -1); ////// debug print //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n"); //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n"); // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signature, since there's no way for // a signature to sign itself string_find_del(scriptCode, vchSig); bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fSuccess) fSuccess = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); g_string_free(scriptCode, TRUE); popstack(stack); popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack->len < i) goto out; int nKeysCount = stackint(stack, -i); if (nKeysCount < 0 || nKeysCount > 20) goto out; nOpCount += nKeysCount; if (nOpCount > 201) goto out; int ikey = ++i; i += nKeysCount; if ((int)stack->len < i) goto out; int nSigsCount = stackint(stack, -i); if (nSigsCount < 0 || nSigsCount > nKeysCount) goto out; int isig = ++i; i += nSigsCount; if ((int)stack->len < i) goto out; // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signatures, since there's no way for // a signature to sign itself int k; for (k = 0; k < nSigsCount; k++) { struct buffer *vchSig =stacktop(stack, -isig-k); string_find_del(scriptCode, vchSig); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { struct buffer *vchSig = stacktop(stack, -isig); struct buffer *vchPubKey = stacktop(stack, -ikey); // Check signature bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fOk) fOk = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } g_string_free(scriptCode, TRUE); while (i-- > 0) popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } default: goto out; } if (stack->len + altstack->len > 1000) goto out; } rc = (vfExec->len == 0 && bp.error == false); out: BN_clear_free(&bn); g_ptr_array_free(altstack, TRUE); g_byte_array_unref(vfExec); return rc; }
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0, i; BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; const BIGNUM *priv_key; ecdsa = ecdsa_check(eckey); group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL || ecdsa == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); return NULL; } ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; } i = BN_num_bits(order); /* * Need to truncate digest if it is too long: first truncate whole bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7) / 8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } do { if (in_kinv == NULL || in_r == NULL) { if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* * if kinv and r have been supplied by the caller don't to * generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else /* s != 0 => we have a valid signature */ break; } while (1); ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } if (ctx) BN_CTX_free(ctx); if (m) BN_clear_free(m); if (tmp) BN_clear_free(tmp); if (order) BN_free(order); if (kinv) BN_clear_free(kinv); return ret; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ order = BN_new(); X = BN_new(); if (!k || !r || !order || !X) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* * We do not want timing information to leak the length of k, so we * compute G*k using an equivalent scalar of fixed bit-length. */ if (!BN_add(k, k, order)) goto err; if (BN_num_bits(k) <= BN_num_bits(order)) if (!BN_add(k, k, order)) goto err; /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ if (EC_GROUP_get_mont_data(group) != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } /* clear old values if necessary */ if (*rp != NULL) BN_clear_free(*rp); if (*kinvp != NULL) BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { if (k != NULL) BN_clear_free(k); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order != NULL) BN_free(order); EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return (ret); }
int __ops_elgamal_private_decrypt(uint8_t *out, const uint8_t *g_to_k, const uint8_t *in, size_t length, const __ops_elgamal_seckey_t *seckey, const __ops_elgamal_pubkey_t *pubkey) { BIGNUM *bndiv; BIGNUM *c1x; BN_CTX *tmp; BIGNUM *c1; BIGNUM *c2; BIGNUM *p; BIGNUM *x; BIGNUM *m; int ret; ret = 0; /* c1 and c2 are in g_to_k and in, respectively*/ c1 = BN_bin2bn(g_to_k, (int)length, NULL); c2 = BN_bin2bn(in, (int)length, NULL); /* other bits */ p = pubkey->p; x = seckey->x; c1x = BN_new(); bndiv = BN_new(); m = BN_new(); tmp = BN_CTX_new(); if (!c1 || !c2 || !p || !x || !c1x || !bndiv || !m || !tmp) { goto done; } /* * m = c2 / (c1^x) */ if (!BN_mod_exp(c1x, c1, x, p, tmp)) { goto done; } if (!BN_mod_inverse(bndiv, c1x, p, tmp)) { goto done; } if (!BN_mod_mul(m, c2, bndiv, p, tmp)) { goto done; } /* result */ ret = BN_bn2bin(m, out); done: if (tmp) { BN_CTX_free(tmp); } if (m) { BN_clear_free(m); } if (bndiv) { BN_clear_free(bndiv); } if (c1x) { BN_clear_free(c1x); } if (x) { BN_clear_free(x); } if (p) { BN_clear_free(p); } if (c1) { BN_clear_free(c1); } if (c2) { BN_clear_free(c2); } return ret; }
/* * Checks if the user has an authentication agent, and if so, tries to * authenticate using the agent. */ static int try_agent_authentication(void) { int type; char *comment; AuthenticationConnection *auth; u_char response[16]; u_int i; Key *key; BIGNUM *challenge; /* Get connection to the agent. */ auth = ssh_get_authentication_connection(); if (!auth) return 0; if ((challenge = BN_new()) == NULL) fatal("try_agent_authentication: BN_new failed"); /* Loop through identities served by the agent. */ for (key = ssh_get_first_identity(auth, &comment, 1); key != NULL; key = ssh_get_next_identity(auth, &comment, 1)) { /* Try this identity. */ debug("Trying RSA authentication via agent with '%.100s'", comment); free(comment); /* Tell the server that we are willing to authenticate using this key. */ packet_start(SSH_CMSG_AUTH_RSA); packet_put_bignum(key->rsa->n); packet_send(); packet_write_wait(); /* Wait for server's response. */ type = packet_read(); /* The server sends failure if it doesn't like our key or does not support RSA authentication. */ if (type == SSH_SMSG_FAILURE) { debug("Server refused our key."); key_free(key); continue; } /* Otherwise it should have sent a challenge. */ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) packet_disconnect("Protocol error during RSA authentication: %d", type); packet_get_bignum(challenge); packet_check_eom(); debug("Received RSA challenge from server."); /* Ask the agent to decrypt the challenge. */ if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) { /* * The agent failed to authenticate this identifier * although it advertised it supports this. Just * return a wrong value. */ logit("Authentication agent failed to decrypt challenge."); memset(response, 0, sizeof(response)); } key_free(key); debug("Sending response to RSA challenge."); /* Send the decrypted challenge back to the server. */ packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); for (i = 0; i < 16; i++) packet_put_char(response[i]); packet_send(); packet_write_wait(); /* Wait for response from the server. */ type = packet_read(); /* The server returns success if it accepted the authentication. */ if (type == SSH_SMSG_SUCCESS) { ssh_close_authentication_connection(auth); BN_clear_free(challenge); debug("RSA authentication accepted by server."); return 1; } /* Otherwise it should return failure. */ if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error waiting RSA auth response: %d", type); } ssh_close_authentication_connection(auth); BN_clear_free(challenge); debug("RSA authentication using agent refused."); return 0; }
int __ops_elgamal_public_encrypt(uint8_t *g_to_k, uint8_t *encm, const uint8_t *in, size_t size, const __ops_elgamal_pubkey_t *pubkey) { int ret = 0; int k_bits; BIGNUM *m; BIGNUM *p; BIGNUM *g; BIGNUM *y; BIGNUM *k; BIGNUM *yk; BIGNUM *c1; BIGNUM *c2; BN_CTX *tmp; m = BN_bin2bn(in, (int)size, NULL); p = pubkey->p; g = pubkey->g; y = pubkey->y; k = BN_new(); yk = BN_new(); c1 = BN_new(); c2 = BN_new(); tmp = BN_CTX_new(); if (!m || !p || !g || !y || !k || !yk || !c1 || !c2 || !tmp) { goto done; } /* * generate k */ k_bits = decide_k_bits(BN_num_bits(p)); if (!BN_rand(k, k_bits, 0, 0)) { goto done; } /* * c1 = g^k c2 = m * y^k */ if (!BN_mod_exp(c1, g, k, p, tmp)) { goto done; } if (!BN_mod_exp(yk, y, k, p, tmp)) { goto done; } if (!BN_mod_mul(c2, m, yk, p, tmp)) { goto done; } /* result */ BN_bn2bin(c1, g_to_k); ret = BN_num_bytes(c1); /* c1 = g^k */ BN_bn2bin(c2, encm); ret += BN_num_bytes(c2); /* c2 = m * y^k */ done: if (tmp) { BN_CTX_free(tmp); } if (c2) { BN_clear_free(c2); } if (c1) { BN_clear_free(c1); } if (yk) { BN_clear_free(yk); } if (k) { BN_clear_free(k); } if (g) { BN_clear_free(g); } return ret; }
static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) { BIGNUM *private_key = (BIGNUM *)ctx->data; BN_clear_free(private_key); }
int GOST_KEY_set_private_key(GOST_KEY *key, const BIGNUM *priv_key) { BN_clear_free(key->priv_key); key->priv_key = BN_dup(priv_key); return (key->priv_key == NULL) ? 0 : 1; }
static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { DSA_SIG *to_return = NULL; int s_len = 160, r_len = 160, d_len, fd; BIGNUM m, *r = NULL, *s = NULL; BN_init(&m); s = BN_new(); r = BN_new(); if ((s == NULL) || (r == NULL)) goto err; d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen); if (!bn_wexpand(r, (160 + BN_BITS2 - 1) / BN_BITS2) || (!bn_wexpand(s, (160 + BN_BITS2 - 1) / BN_BITS2))) { UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); goto err; } if (BN_bin2bn(dgst, dlen, &m) == NULL) { UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); goto err; } if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { const DSA_METHOD *meth; fd = 0; UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_UNIT_FAILURE); meth = DSA_OpenSSL(); to_return = meth->dsa_do_sign(dgst, dlen, dsa); goto err; } if (p_UBSEC_dsa_sign_ioctl(fd, /* compute hash before signing */ 0, (unsigned char *)dgst, d_len, NULL, /* compute random value */ 0, (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key), (unsigned char *)r->d, &r_len, (unsigned char *)s->d, &s_len) != 0) { const DSA_METHOD *meth; UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_REQUEST_FAILED); p_UBSEC_ubsec_close(fd); meth = DSA_OpenSSL(); to_return = meth->dsa_do_sign(dgst, dlen, dsa); goto err; } p_UBSEC_ubsec_close(fd); r->top = (160 + BN_BITS2 - 1) / BN_BITS2; s->top = (160 + BN_BITS2 - 1) / BN_BITS2; to_return = DSA_SIG_new(); if (to_return == NULL) { UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); goto err; } to_return->r = r; to_return->s = s; err: if (!to_return) { if (r) BN_free(r); if (s) BN_free(s); } BN_clear_free(&m); return to_return; }
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { // Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm // (cf. Henri Cohen, "A Course in Algebraic Computational Number Theory", // algorithm 1.5.1). |p| is assumed to be a prime. BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) { BN_free(ret); } return NULL; } return ret; } OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); return (NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) { BN_free(ret); } return NULL; } return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) { goto end; } if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } // A = a mod p if (!BN_nnmod(A, a, p, ctx)) { goto end; } // now write |p| - 1 as 2^e*q where q is odd e = 1; while (!BN_is_bit_set(p, e)) { e++; } // we'll set q later (if needed) if (e == 1) { // The easy case: (|p|-1)/2 is odd, so 2 has an inverse // modulo (|p|-1)/2, and square roots can be computed // directly by modular exponentiation. // We have // 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), // so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. if (!BN_rshift(q, p, 2)) { goto end; } q->neg = 0; if (!BN_add_word(q, 1) || !BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) { goto end; } err = 0; goto vrfy; } if (e == 2) { // |p| == 5 (mod 8) // // In this case 2 is always a non-square since // Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. // So if a really is a square, then 2*a is a non-square. // Thus for // b := (2*a)^((|p|-5)/8), // i := (2*a)*b^2 // we have // i^2 = (2*a)^((1 + (|p|-5)/4)*2) // = (2*a)^((p-1)/2) // = -1; // so if we set // x := a*b*(i-1), // then // x^2 = a^2 * b^2 * (i^2 - 2*i + 1) // = a^2 * b^2 * (-2*i) // = a*(-i)*(2*a*b^2) // = a*(-i)*i // = a. // // (This is due to A.O.L. Atkin, // <URL: //http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, // November 1992.) // t := 2*a if (!bn_mod_lshift1_consttime(t, A, p, ctx)) { goto end; } // b := (2*a)^((|p|-5)/8) if (!BN_rshift(q, p, 3)) { goto end; } q->neg = 0; if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) { goto end; } // y := b^2 if (!BN_mod_sqr(y, b, p, ctx)) { goto end; } // t := (2*a)*b^2 - 1 if (!BN_mod_mul(t, t, y, p, ctx) || !BN_sub_word(t, 1)) { goto end; } // x = a*b*t if (!BN_mod_mul(x, A, b, p, ctx) || !BN_mod_mul(x, x, t, p, ctx)) { goto end; } if (!BN_copy(ret, x)) { goto end; } err = 0; goto vrfy; } // e > 2, so we really have to use the Tonelli/Shanks algorithm. // First, find some y that is not a square. if (!BN_copy(q, p)) { goto end; // use 'q' as temp } q->neg = 0; i = 2; do { // For efficiency, try small numbers first; // if this fails, try random numbers. if (i < 22) { if (!BN_set_word(y, i)) { goto end; } } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) { goto end; } if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) { goto end; } } // now 0 <= y < |p| if (BN_is_zero(y)) { if (!BN_set_word(y, i)) { goto end; } } } r = bn_jacobi(y, q, ctx); // here 'q' is |p| if (r < -1) { goto end; } if (r == 0) { // m divides p OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { // Many rounds and still no non-square -- this is more likely // a bug than just bad luck. // Even if p is not prime, we should have found some y // such that r == -1. OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS); goto end; } // Here's our actual 'q': if (!BN_rshift(q, q, e)) { goto end; } // Now that we have some non-square, we can find an element // of order 2^e by computing its q'th power. if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) { goto end; } if (BN_is_one(y)) { OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); goto end; } // Now we know that (if p is indeed prime) there is an integer // k, 0 <= k < 2^e, such that // // a^q * y^k == 1 (mod p). // // As a^q is a square and y is not, k must be even. // q+1 is even, too, so there is an element // // X := a^((q+1)/2) * y^(k/2), // // and it satisfies // // X^2 = a^q * a * y^k // = a, // // so it is the square root that we are looking for. // t := (q-1)/2 (note that q is odd) if (!BN_rshift1(t, q)) { goto end; } // x := a^((q-1)/2) if (BN_is_zero(t)) // special case: p = 2^e + 1 { if (!BN_nnmod(t, A, p, ctx)) { goto end; } if (BN_is_zero(t)) { // special case: a == 0 (mod p) BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) { goto end; } } else { if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) { goto end; } if (BN_is_zero(x)) { // special case: a == 0 (mod p) BN_zero(ret); err = 0; goto end; } } // b := a*x^2 (= a^q) if (!BN_mod_sqr(b, x, p, ctx) || !BN_mod_mul(b, b, A, p, ctx)) { goto end; } // x := a*x (= a^((q+1)/2)) if (!BN_mod_mul(x, x, A, p, ctx)) { goto end; } while (1) { // Now b is a^q * y^k for some even k (0 <= k < 2^E // where E refers to the original value of e, which we // don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). // // We have a*b = x^2, // y^2^(e-1) = -1, // b^2^(e-1) = 1. if (BN_is_one(b)) { if (!BN_copy(ret, x)) { goto end; } err = 0; goto vrfy; } // find smallest i such that b^(2^i) = 1 i = 1; if (!BN_mod_sqr(t, b, p, ctx)) { goto end; } while (!BN_is_one(t)) { i++; if (i == e) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) { goto end; } } // t := y^2^(e - i - 1) if (!BN_copy(t, y)) { goto end; } for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) { goto end; } } if (!BN_mod_mul(y, t, t, p, ctx) || !BN_mod_mul(x, x, t, p, ctx) || !BN_mod_mul(b, b, y, p, ctx)) { goto end; } e = i; } vrfy: if (!err) { // verify the result -- the input might have been not a square // (test added in 0.9.8) if (!BN_mod_sqr(x, ret, p, ctx)) { err = 1; } if (!err && 0 != BN_cmp(x, A)) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); return ret; }
void ec_GFp_simple_group_clear_finish(EC_GROUP *group) { BN_clear_free(&group->field); BN_clear_free(&group->a); BN_clear_free(&group->b); }
BIGNUM * BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) /* Returns 'ret' such that * ret^2 == a (mod p), * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course * in Algebraic Computational Number Theory", algorithm 1.5.1). * 'p' must be prime! */ { BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); return (NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto end; if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; /* A = a mod p */ if (!BN_nnmod(A, a, p, ctx)) goto end; /* now write |p| - 1 as 2^e*q where q is odd */ e = 1; while (!BN_is_bit_set(p, e)) e++; /* we'll set q later (if needed) */ if (e == 1) { /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse * modulo (|p|-1)/2, and square roots can be computed * directly by modular exponentiation. * We have * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. */ if (!BN_rshift(q, p, 2)) goto end; q->neg = 0; if (!BN_add_word(q, 1)) goto end; if (!BN_mod_exp(ret, A, q, p, ctx)) goto end; err = 0; goto vrfy; } if (e == 2) { /* |p| == 5 (mod 8) * * In this case 2 is always a non-square since * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. * So if a really is a square, then 2*a is a non-square. * Thus for * b := (2*a)^((|p|-5)/8), * i := (2*a)*b^2 * we have * i^2 = (2*a)^((1 + (|p|-5)/4)*2) * = (2*a)^((p-1)/2) * = -1; * so if we set * x := a*b*(i-1), * then * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) * = a^2 * b^2 * (-2*i) * = a*(-i)*(2*a*b^2) * = a*(-i)*i * = a. * * (This is due to A.O.L. Atkin, * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, * November 1992.) */ /* t := 2*a */ if (!BN_mod_lshift1_quick(t, A, p)) goto end; /* b := (2*a)^((|p|-5)/8) */ if (!BN_rshift(q, p, 3)) goto end; q->neg = 0; if (!BN_mod_exp(b, t, q, p, ctx)) goto end; /* y := b^2 */ if (!BN_mod_sqr(y, b, p, ctx)) goto end; /* t := (2*a)*b^2 - 1*/ if (!BN_mod_mul(t, t, y, p, ctx)) goto end; if (!BN_sub_word(t, 1)) goto end; /* x = a*b*t */ if (!BN_mod_mul(x, A, b, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* e > 2, so we really have to use the Tonelli/Shanks algorithm. * First, find some y that is not a square. */ if (!BN_copy(q, p)) goto end; /* use 'q' as temp */ q->neg = 0; i = 2; do { /* For efficiency, try small numbers first; * if this fails, try random numbers. */ if (i < 22) { if (!BN_set_word(y, i)) goto end; } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end; if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end; } /* now 0 <= y < |p| */ if (BN_is_zero(y)) if (!BN_set_word(y, i)) goto end; } r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ if (r < -1) goto end; if (r == 0) { /* m divides p */ BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { /* Many rounds and still no non-square -- this is more likely * a bug than just bad luck. * Even if p is not prime, we should have found some y * such that r == -1. */ BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); goto end; } /* Here's our actual 'q': */ if (!BN_rshift(q, q, e)) goto end; /* Now that we have some non-square, we can find an element * of order 2^e by computing its q'th power. */ if (!BN_mod_exp(y, y, q, p, ctx)) goto end; if (BN_is_one(y)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } /* Now we know that (if p is indeed prime) there is an integer * k, 0 <= k < 2^e, such that * * a^q * y^k == 1 (mod p). * * As a^q is a square and y is not, k must be even. * q+1 is even, too, so there is an element * * X := a^((q+1)/2) * y^(k/2), * * and it satisfies * * X^2 = a^q * a * y^k * = a, * * so it is the square root that we are looking for. */ /* t := (q-1)/2 (note that q is odd) */ if (!BN_rshift1(t, q)) goto end; /* x := a^((q-1)/2) */ if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ { if (!BN_nnmod(t, A, p, ctx)) goto end; if (BN_is_zero(t)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) goto end; } else { if (!BN_mod_exp(x, A, t, p, ctx)) goto end; if (BN_is_zero(x)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } } /* b := a*x^2 (= a^q) */ if (!BN_mod_sqr(b, x, p, ctx)) goto end; if (!BN_mod_mul(b, b, A, p, ctx)) goto end; /* x := a*x (= a^((q+1)/2)) */ if (!BN_mod_mul(x, x, A, p, ctx)) goto end; while (1) { /* Now b is a^q * y^k for some even k (0 <= k < 2^E * where E refers to the original value of e, which we * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). * * We have a*b = x^2, * y^2^(e-1) = -1, * b^2^(e-1) = 1. */ if (BN_is_one(b)) { if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* find smallest i such that b^(2^i) = 1 */ i = 1; if (!BN_mod_sqr(t, b, p, ctx)) goto end; while (!BN_is_one(t)) { i++; if (i == e) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) goto end; } /* t := y^2^(e - i - 1) */ if (!BN_copy(t, y)) goto end; for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) goto end; } if (!BN_mod_mul(y, t, t, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_mod_mul(b, b, y, p, ctx)) goto end; e = i; } vrfy: if (!err) { /* verify the result -- the input might have been not a square * (test added in 0.9.8) */ if (!BN_mod_sqr(x, ret, p, ctx)) err = 1; if (!err && 0 != BN_cmp(x, A)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != NULL && ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); bn_check_top(ret); return ret; }
ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0; BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; const BIGNUM *priv_key; group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER); return NULL; } ret = ECDSA_SIG_new(); if (!ret) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB); goto err; } if (!digest_to_bn(m, digest, digest_len, order)) { goto err; } for (;;) { if (in_kinv == NULL || in_r == NULL) { if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* if kinv and r have been supplied by the caller * don't to generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else { /* s != 0 => we have a valid signature */ break; } } ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } BN_CTX_free(ctx); BN_clear_free(m); BN_clear_free(tmp); BN_free(order); BN_clear_free(kinv); return ret; }
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { BIGNUM *kinv=NULL,*r=NULL,*s=NULL; BIGNUM m; BIGNUM xr; BN_CTX *ctx=NULL; int i,reason=ERR_R_BN_LIB; DSA_SIG *ret=NULL; BN_init(&m); BN_init(&xr); if (!dsa->p || !dsa->q || !dsa->g) { reason=DSA_R_MISSING_PARAMETERS; goto err; } s=BN_new(); if (s == NULL) goto err; i=BN_num_bytes(dsa->q); /* should be 20 */ if ((dlen > i) || (dlen > 50)) { reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE; goto err; } ctx=BN_CTX_new(); if (ctx == NULL) goto err; if ((dsa->kinv == NULL) || (dsa->r == NULL)) { if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err; } else { kinv=dsa->kinv; dsa->kinv=NULL; r=dsa->r; dsa->r=NULL; } if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err; /* Compute s = inv(k) (m + xr) mod q */ if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */ if (!BN_add(s, &xr, &m)) goto err; /* s = m + xr */ if (BN_cmp(s,dsa->q) > 0) BN_sub(s,s,dsa->q); if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; ret=DSA_SIG_new(); if (ret == NULL) goto err; ret->r = r; ret->s = s; err: if (!ret) { DSAerr(DSA_F_DSA_DO_SIGN,reason); BN_free(r); BN_free(s); } if (ctx != NULL) BN_CTX_free(ctx); BN_clear_free(&m); BN_clear_free(&xr); if (kinv != NULL) /* dsa->kinv is NULL now if we used it */ BN_clear_free(kinv); return(ret); }
static int vg_prefix_context_add_patterns(vg_context_t *vcp, const char ** const patterns, int npatterns) { vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp; prefix_case_iter_t caseiter; vg_prefix_t *vp, *vp2; BN_CTX *bnctx; BIGNUM bntmp, bntmp2, bntmp3; BIGNUM *ranges[4]; int ret = 0; int i, impossible = 0; int case_impossible; unsigned long npfx; char *dbuf; bnctx = BN_CTX_new(); BN_init(&bntmp); BN_init(&bntmp2); BN_init(&bntmp3); npfx = 0; for (i = 0; i < npatterns; i++) { if (!vcpp->vcp_caseinsensitive) { vp = NULL; ret = get_prefix_ranges(vcpp->base.vc_addrtype, patterns[i], ranges, bnctx); if (!ret) { vp = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, NULL); } } else { /* Case-enumerate the prefix */ if (!prefix_case_iter_init(&caseiter, patterns[i])) { fprintf(stderr, "Prefix '%s' is too long\n", patterns[i]); continue; } if (caseiter.ci_nbits > 16) { fprintf(stderr, "WARNING: Prefix '%s' has " "2^%d case-varied derivatives\n", patterns[i], caseiter.ci_nbits); } case_impossible = 0; vp = NULL; do { ret = get_prefix_ranges(vcpp->base.vc_addrtype, caseiter.ci_prefix, ranges, bnctx); if (ret == -2) { case_impossible++; ret = 0; continue; } if (ret) break; vp2 = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, vp); if (!vp2) { ret = -1; break; } if (!vp) vp = vp2; } while (prefix_case_iter_next(&caseiter)); if (!vp && case_impossible) ret = -2; if (ret && vp) { vg_prefix_delete(&vcpp->vcp_avlroot, vp); vp = NULL; } } if (ret == -2) { fprintf(stderr, "Prefix '%s' not possible\n", patterns[i]); impossible++; } if (!vp) continue; npfx++; /* Determine the probability of finding a match */ vg_prefix_range_sum(vp, &bntmp, &bntmp2); BN_add(&bntmp2, &vcpp->vcp_difficulty, &bntmp); BN_copy(&vcpp->vcp_difficulty, &bntmp2); if (vcp->vc_verbose > 1) { BN_clear(&bntmp2); BN_set_bit(&bntmp2, 192); BN_div(&bntmp3, NULL, &bntmp2, &bntmp, bnctx); dbuf = BN_bn2dec(&bntmp3); fprintf(stderr, "Prefix difficulty: %20s %s\n", dbuf, patterns[i]); OPENSSL_free(dbuf); } } vcpp->base.vc_npatterns += npfx; vcpp->base.vc_npatterns_start += npfx; if (!npfx && impossible) { const char *ats = "bitcoin", *bw = "\"1\""; switch (vcpp->base.vc_addrtype) { case 5: ats = "bitcoin script"; bw = "\"3\""; break; case 111: ats = "testnet"; bw = "\"m\" or \"n\""; break; case 52: ats = "namecoin"; bw = "\"M\" or \"N\""; break; case 48: ats = "litecoin"; bw = "\"L\""; break; default: break; } fprintf(stderr, "Hint: valid %s addresses begin with %s\n", ats, bw); } if (npfx) vg_prefix_context_next_difficulty(vcpp, &bntmp, &bntmp2, bnctx); ret = (npfx != 0); BN_clear_free(&bntmp); BN_clear_free(&bntmp2); BN_clear_free(&bntmp3); BN_CTX_free(bnctx); return ret; }
/* * Generate Schnorr signature to prove knowledge of private value 'x' used * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' * using the hash function "hash_alg". * 'idlen' bytes from 'id' will be included in the signature hash as an anti- * replay salt. * * On success, 0 is returned. The signature values are returned as *e_p * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values. * On failure, -1 is returned. */ int schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, int hash_alg, const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) { int success = -1; BIGNUM *h, *tmp, *v, *g_v, *r; BN_CTX *bn_ctx; SCHNORR_DEBUG_BN((x, "%s: x = ", __func__)); SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); /* Avoid degenerate cases: g^0 yields a spoofable signature */ if (BN_cmp(g_x, BN_value_one()) <= 0) { error("%s: g_x < 1", __func__); return -1; } if (BN_cmp(g_x, grp_p) >= 0) { error("%s: g_x > g", __func__); return -1; } h = g_v = r = tmp = v = NULL; if ((bn_ctx = BN_CTX_new()) == NULL) { error("%s: BN_CTX_new", __func__); goto out; } if ((g_v = BN_new()) == NULL || (r = BN_new()) == NULL || (tmp = BN_new()) == NULL) { error("%s: BN_new", __func__); goto out; } /* * v must be a random element of Zq, so 1 <= v < q * we also exclude v = 1, since g^1 looks dangerous */ if ((v = bn_rand_range_gt_one(grp_p)) == NULL) { error("%s: bn_rand_range2", __func__); goto out; } SCHNORR_DEBUG_BN((v, "%s: v = ", __func__)); /* g_v = g^v mod p */ if (BN_mod_exp(g_v, grp_g, v, grp_p, bn_ctx) == -1) { error("%s: BN_mod_exp (g^v mod p)", __func__); goto out; } SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); /* h = H(g || g^v || g^x || id) */ if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x, id, idlen)) == NULL) { error("%s: schnorr_hash failed", __func__); goto out; } /* r = v - xh mod q */ if (BN_mod_mul(tmp, x, h, grp_q, bn_ctx) == -1) { error("%s: BN_mod_mul (tmp = xv mod q)", __func__); goto out; } if (BN_mod_sub(r, v, tmp, grp_q, bn_ctx) == -1) { error("%s: BN_mod_mul (r = v - tmp)", __func__); goto out; } SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__)); SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); *e_p = g_v; *r_p = r; success = 0; out: BN_CTX_free(bn_ctx); if (h != NULL) BN_clear_free(h); if (v != NULL) BN_clear_free(v); BN_clear_free(tmp); return success; }
/* * 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)) <= 0) { /* * 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; }
/* * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and * 'grp_g' using hash "hash_alg". * Signature hash will be salted with 'idlen' bytes from 'id'. * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. */ int schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, const BIGNUM *r, const BIGNUM *e) { int success = -1; BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL; BIGNUM *expected = NULL; BN_CTX *bn_ctx; SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); /* Avoid degenerate cases: g^0 yields a spoofable signature */ if (BN_cmp(g_x, BN_value_one()) <= 0) { error("%s: g_x <= 1", __func__); return -1; } if (BN_cmp(g_x, grp_p) >= 0) { error("%s: g_x >= p", __func__); return -1; } h = g_xh = g_r = expected = NULL; if ((bn_ctx = BN_CTX_new()) == NULL) { error("%s: BN_CTX_new", __func__); goto out; } if ((g_xh = BN_new()) == NULL || (g_r = BN_new()) == NULL || (gx_q = BN_new()) == NULL || (expected = BN_new()) == NULL) { error("%s: BN_new", __func__); goto out; } SCHNORR_DEBUG_BN((e, "%s: e = ", __func__)); SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); /* gx_q = (g^x)^q must === 1 mod p */ if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) { error("%s: BN_mod_exp (g_x^q mod p)", __func__); goto out; } if (BN_cmp(gx_q, BN_value_one()) != 0) { error("%s: Invalid signature (g^x)^q != 1 mod p", __func__); goto out; } SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); /* h = H(g || g^v || g^x || id) */ if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x, id, idlen)) == NULL) { error("%s: schnorr_hash failed", __func__); goto out; } /* g_xh = (g^x)^h */ if (BN_mod_exp(g_xh, g_x, h, grp_p, bn_ctx) == -1) { error("%s: BN_mod_exp (g_x^h mod p)", __func__); goto out; } SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); /* g_r = g^r */ if (BN_mod_exp(g_r, grp_g, r, grp_p, bn_ctx) == -1) { error("%s: BN_mod_exp (g_x^h mod p)", __func__); goto out; } SCHNORR_DEBUG_BN((g_r, "%s: g_r = ", __func__)); /* expected = g^r * g_xh */ if (BN_mod_mul(expected, g_r, g_xh, grp_p, bn_ctx) == -1) { error("%s: BN_mod_mul (expected = g_r mod p)", __func__); goto out; } SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__)); /* Check e == expected */ success = BN_cmp(expected, e) == 0; out: BN_CTX_free(bn_ctx); if (h != NULL) BN_clear_free(h); if (gx_q != NULL) BN_clear_free(gx_q); if (g_xh != NULL) BN_clear_free(g_xh); if (g_r != NULL) BN_clear_free(g_r); if (expected != NULL) BN_clear_free(expected); return success; }
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { BN_CTX *ctx; BIGNUM k,kq,*K,*kinv=NULL,*r=NULL; int ret=0; if (!dsa->p || !dsa->q || !dsa->g) { DSAerr(DSA_F_DSA_SIGN_SETUP,DSA_R_MISSING_PARAMETERS); return 0; } BN_init(&k); BN_init(&kq); if (ctx_in == NULL) { if ((ctx=BN_CTX_new()) == NULL) goto err; } else ctx=ctx_in; if ((r=BN_new()) == NULL) goto err; /* Get random k */ do if (!BN_rand_range(&k, dsa->q)) goto err; while (BN_is_zero(&k)); if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { BN_set_flags(&k, BN_FLG_CONSTTIME); } if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p, CRYPTO_LOCK_DSA, dsa->p, ctx)) goto err; } /* Compute r = (g^k mod p) mod q */ if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { if (!BN_copy(&kq, &k)) goto err; /* We do not want timing information to leak the length of k, * so we compute g^k using an equivalent exponent of fixed length. * * (This is a kludge that we need because the BN_mod_exp_mont() * does not let us specify the desired timing behaviour.) */ if (!BN_add(&kq, &kq, dsa->q)) goto err; if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) { if (!BN_add(&kq, &kq, dsa->q)) goto err; } K = &kq; } else { K = &k; } if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,K,dsa->p,ctx, (BN_MONT_CTX *)dsa->method_mont_p)) goto err; if (!BN_mod(r,r,dsa->q,ctx)) goto err; /* Compute part of 's = inv(k) (m + xr) mod q' */ if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err; if (*kinvp != NULL) BN_clear_free(*kinvp); *kinvp=kinv; kinv=NULL; if (*rp != NULL) BN_clear_free(*rp); *rp=r; ret=1; err: if (!ret) { DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB); if (kinv != NULL) BN_clear_free(kinv); if (r != NULL) BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); if (kinv != NULL) BN_clear_free(kinv); BN_clear_free(&k); BN_clear_free(&kq); return(ret); }
/* * Checks if the user has an authentication agent, and if so, tries to * authenticate using the agent. */ static int try_agent_authentication(void) { int r, type, agent_fd, ret = 0; u_char response[16]; size_t i; BIGNUM *challenge; struct ssh_identitylist *idlist = NULL; /* Get connection to the agent. */ if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) debug("%s: ssh_get_authentication_socket: %s", __func__, ssh_err(r)); return 0; } if ((challenge = BN_new()) == NULL) fatal("try_agent_authentication: BN_new failed"); /* Loop through identities served by the agent. */ if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) { if (r != SSH_ERR_AGENT_NO_IDENTITIES) debug("%s: ssh_fetch_identitylist: %s", __func__, ssh_err(r)); goto out; } for (i = 0; i < idlist->nkeys; i++) { /* Try this identity. */ debug("Trying RSA authentication via agent with '%.100s'", idlist->comments[i]); /* Tell the server that we are willing to authenticate using this key. */ packet_start(SSH_CMSG_AUTH_RSA); packet_put_bignum(idlist->keys[i]->rsa->n); packet_send(); packet_write_wait(); /* Wait for server's response. */ type = packet_read(); /* The server sends failure if it doesn't like our key or does not support RSA authentication. */ if (type == SSH_SMSG_FAILURE) { debug("Server refused our key."); continue; } /* Otherwise it should have sent a challenge. */ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) packet_disconnect("Protocol error during RSA authentication: %d", type); packet_get_bignum(challenge); packet_check_eom(); debug("Received RSA challenge from server."); /* Ask the agent to decrypt the challenge. */ if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i], challenge, session_id, response)) != 0) { /* * The agent failed to authenticate this identifier * although it advertised it supports this. Just * return a wrong value. */ logit("Authentication agent failed to decrypt " "challenge: %s", ssh_err(r)); explicit_bzero(response, sizeof(response)); } debug("Sending response to RSA challenge."); /* Send the decrypted challenge back to the server. */ packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); for (i = 0; i < 16; i++) packet_put_char(response[i]); packet_send(); packet_write_wait(); /* Wait for response from the server. */ type = packet_read(); /* * The server returns success if it accepted the * authentication. */ if (type == SSH_SMSG_SUCCESS) { debug("RSA authentication accepted by server."); ret = 1; break; } else if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error waiting RSA auth " "response: %d", type); } if (ret != 1) debug("RSA authentication using agent refused."); out: ssh_free_identitylist(idlist); ssh_close_authentication_socket(agent_fd); BN_clear_free(challenge); return ret; }
void kexgex_server(Kex *kex) { BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; Key *server_host_key; DH *dh; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int sbloblen, klen, slen, hashlen; int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1; int type, kout; if (kex->load_host_key == NULL) fatal("Cannot load hostkey"); server_host_key = kex->load_host_key(kex->hostkey_type); if (server_host_key == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); type = packet_read(); switch (type) { case SSH2_MSG_KEX_DH_GEX_REQUEST: debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); omin = min = packet_get_int(); onbits = nbits = packet_get_int(); omax = max = packet_get_int(); min = MAX(DH_GRP_MIN, min); max = MIN(DH_GRP_MAX, max); nbits = MAX(DH_GRP_MIN, nbits); nbits = MIN(DH_GRP_MAX, nbits); break; case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); onbits = nbits = packet_get_int(); /* unused for old GEX */ omin = min = DH_GRP_MIN; omax = max = DH_GRP_MAX; break; default: fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); } packet_check_eom(); if (omax < omin || onbits < omin || omax < onbits) fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", omin, onbits, omax); /* Contact privileged parent */ dh = PRIVSEP(choose_dh(min, nbits, max)); if (dh == NULL) packet_disconnect("Protocol error: no matching DH grp found"); debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); packet_put_bignum2(dh->p); packet_put_bignum2(dh->g); packet_send(); /* flush */ packet_write_wait(); /* Compute our exchange value in parallel with the client */ dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); /* key, cert */ if ((dh_client_pub = BN_new()) == NULL) fatal("dh_client_pub == NULL"); packet_get_bignum2(dh_client_pub); packet_check_eom(); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif if (!dh_pub_is_valid(dh, dh_client_pub)) packet_disconnect("bad client public DH value"); klen = DH_size(dh); kbuf = xmalloc(klen); if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) fatal("DH_compute_key: failed"); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif if ((shared_secret = BN_new()) == NULL) fatal("kexgex_server: BN_new failed"); if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) fatal("kexgex_server: BN_bin2bn failed"); memset(kbuf, 0, klen); xfree(kbuf); key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) omin = min = omax = max = -1; /* calc H */ kexgex_hash( kex->evp_md, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, omin, onbits, omax, dh->p, dh->g, dh_client_pub, dh->pub_key, shared_secret, &hash, &hashlen ); BN_clear_free(dh_client_pub); /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if (PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, hashlen)) < 0) fatal("kexgex_server: key_sign failed"); /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); packet_put_string(server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key); /* f */ packet_put_string(signature, slen); packet_send(); xfree(signature); xfree(server_host_key_blob); /* have keys, free DH */ DH_free(dh); kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }
/* * compute a "random" secret point on an elliptic curve based * on the password and identities. */ int compute_password_element(EAP_PWD_group *grp, u16 num, const u8 *password, size_t password_len, const u8 *id_server, size_t id_server_len, const u8 *id_peer, size_t id_peer_len, const u8 *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; struct crypto_hash *hash; unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; int nid, is_odd, ret = 0; size_t primebytelen, primebitlen; switch (num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; #ifndef OPENSSL_IS_BORINGSSL case 25: nid = NID_X9_62_prime192v1; break; #endif /* OPENSSL_IS_BORINGSSL */ case 26: nid = NID_secp224r1; break; default: wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num); return -1; } grp->pwe = NULL; grp->order = NULL; grp->prime = NULL; if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP"); goto fail; } if (((rnd = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((grp->pwe = EC_POINT_new(grp->group)) == NULL) || ((grp->order = BN_new()) == NULL) || ((grp->prime = BN_new()) == NULL) || ((x_candidate = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); goto fail; } if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp " "curve"); goto fail; } if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve"); goto fail; } if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for " "curve"); goto fail; } primebitlen = BN_num_bits(grp->prime); primebytelen = BN_num_bytes(grp->prime); if ((prfbuf = os_malloc(primebytelen)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " "buffer"); goto fail; } os_memset(prfbuf, 0, primebytelen); ctr = 0; while (1) { if (ctr > 30) { wpa_printf(MSG_INFO, "EAP-pwd: unable to find random " "point on curve for group %d, something's " "fishy", num); goto fail; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fail; eap_pwd_h_update(hash, token, sizeof(u32)); eap_pwd_h_update(hash, id_peer, id_peer_len); eap_pwd_h_update(hash, id_server, id_server_len); eap_pwd_h_update(hash, password, password_len); eap_pwd_h_update(hash, &ctr, sizeof(ctr)); eap_pwd_h_final(hash, pwe_digest); BN_bin2bn(pwe_digest, SHA256_MAC_LEN, rnd); if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN, (u8 *) "EAP-pwd Hunting And Pecking", os_strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen) < 0) goto fail; BN_bin2bn(prfbuf, primebytelen, x_candidate); /* * eap_pwd_kdf() returns a string of bits 0..primebitlen but * BN_bin2bn will treat that string of bits as a big endian * number. If the primebitlen is not an even multiple of 8 * then excessive bits-- those _after_ primebitlen-- so now * we have to shift right the amount we masked off. */ if (primebitlen % 8) BN_rshift(x_candidate, x_candidate, (8 - (primebitlen % 8))); if (BN_ucmp(x_candidate, grp->prime) >= 0) continue; wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate", prfbuf, primebytelen); /* * need to unambiguously identify the solution, if there is * one... */ if (BN_is_odd(rnd)) is_odd = 1; else is_odd = 0; /* * solve the quadratic equation, if it's not solvable then we * don't have a point */ if (!EC_POINT_set_compressed_coordinates_GFp(grp->group, grp->pwe, x_candidate, is_odd, NULL)) continue; /* * If there's a solution to the equation then the point must be * on the curve so why check again explicitly? OpenSSL code * says this is required by X9.62. We're not X9.62 but it can't * hurt just to be sure. */ if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve"); continue; } if (BN_cmp(cofactor, BN_value_one())) { /* make sure the point is not in a small sub-group */ if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe, cofactor, NULL)) { wpa_printf(MSG_INFO, "EAP-pwd: cannot " "multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) { wpa_printf(MSG_INFO, "EAP-pwd: point is at " "infinity"); continue; } } /* if we got here then we have a new generator. */ break; } wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr); grp->group_num = num; if (0) { fail: EC_GROUP_free(grp->group); grp->group = NULL; EC_POINT_clear_free(grp->pwe); grp->pwe = NULL; BN_clear_free(grp->order); grp->order = NULL; BN_clear_free(grp->prime); grp->prime = NULL; ret = 1; } /* cleanliness and order.... */ BN_clear_free(cofactor); BN_clear_free(x_candidate); BN_clear_free(rnd); os_free(prfbuf); return ret; }
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp, *tmp_Z; BIGNUM **prod_Z = NULL; size_t i; int ret = 0; if (num == 0) { return 1; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); tmp_Z = BN_CTX_get(ctx); if (tmp == NULL || tmp_Z == NULL) { goto err; } prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); if (prod_Z == NULL) { goto err; } memset(prod_Z, 0, num * sizeof(prod_Z[0])); for (i = 0; i < num; i++) { prod_Z[i] = BN_new(); if (prod_Z[i] == NULL) { goto err; } } /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, * skipping any zero-valued inputs (pretend that they're 1). */ if (!BN_is_zero(&points[0]->Z)) { if (!BN_copy(prod_Z[0], &points[0]->Z)) { goto err; } } else { if (BN_copy(prod_Z[0], &group->one) == NULL) { goto err; } } for (i = 1; i < num; i++) { if (!BN_is_zero(&points[i]->Z)) { if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) { goto err; } } else { if (!BN_copy(prod_Z[i], prod_Z[i - 1])) { goto err; } } } /* Now use a single explicit inversion to replace every * non-zero points[i]->Z by its inverse. */ if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } if (group->meth->field_encode != NULL) { /* In the Montgomery case, we just turned R*H (representing H) * into 1/(R*H), but we need R*(1/H) (representing 1/H); * i.e. we need to multiply by the Montgomery factor twice. */ if (!group->meth->field_encode(group, tmp, tmp, ctx) || !group->meth->field_encode(group, tmp, tmp, ctx)) { goto err; } } for (i = num - 1; i > 0; --i) { /* Loop invariant: tmp is the product of the inverses of * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */ if (BN_is_zero(&points[i]->Z)) { continue; } /* Set tmp_Z to the inverse of points[i]->Z (as product * of Z inverses 0 .. i, Z values 0 .. i - 1). */ if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) || /* Update tmp to satisfy the loop invariant for i - 1. */ !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) || /* Replace points[i]->Z by its inverse. */ !BN_copy(&points[i]->Z, tmp_Z)) { goto err; } } /* Replace points[0]->Z by its inverse. */ if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) { goto err; } /* Finally, fix up the X and Y coordinates for all points. */ for (i = 0; i < num; i++) { EC_POINT *p = points[i]; if (!BN_is_zero(&p->Z)) { /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). */ if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) || !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) || !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) { goto err; } if (BN_copy(&p->Z, &group->one) == NULL) { goto err; } } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); if (prod_Z != NULL) { for (i = 0; i < num; i++) { if (prod_Z[i] == NULL) { break; } BN_clear_free(prod_Z[i]); } OPENSSL_free(prod_Z); } return ret; }
void kexecdh_server(Kex *kex) { EC_POINT *client_public; EC_KEY *server_key; const EC_GROUP *group; BIGNUM *shared_secret; Key *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf, *hash; u_int klen, slen, sbloblen, hashlen; if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) fatal("%s: EC_KEY_new_by_curve_name failed", __func__); if (EC_KEY_generate_key(server_key) != 1) fatal("%s: EC_KEY_generate_key failed", __func__); group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); key_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) fatal("Cannot load hostkey"); server_host_public = kex->load_host_public_key(kex->hostkey_type); if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); if (server_host_private == NULL) fatal("Missing private key for hostkey type %d", kex->hostkey_type); debug("expecting SSH2_MSG_KEX_ECDH_INIT"); packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); if ((client_public = EC_POINT_new(group)) == NULL) fatal("%s: EC_POINT_new failed", __func__); packet_get_ecpoint(group, client_public); packet_check_eom(); if (key_ec_validate_public(group, client_public) != 0) fatal("%s: invalid client public key", __func__); #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); key_dump_ec_point(group, client_public); #endif /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; kbuf = xmalloc(klen); if (ECDH_compute_key(kbuf, klen, client_public, server_key, NULL) != (int)klen) fatal("%s: ECDH_compute_key failed", __func__); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, klen); #endif if ((shared_secret = BN_new()) == NULL) fatal("%s: BN_new failed", __func__); if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) fatal("%s: BN_bin2bn failed", __func__); memset(kbuf, 0, klen); free(kbuf); /* calc H */ key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); kex_ecdh_hash( kex->evp_md, group, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, &hash, &hashlen ); EC_POINT_clear_free(client_public); /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, hashlen)) < 0) fatal("kexdh_server: key_sign failed"); /* destroy_sensitive_data(); */ /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ packet_start(SSH2_MSG_KEX_ECDH_REPLY); packet_put_string(server_host_key_blob, sbloblen); packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); packet_put_string(signature, slen); packet_send(); free(signature); free(server_host_key_blob); /* have keys, free server key */ EC_KEY_free(server_key); kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }