int MKEM_decode_message(const MKEM *kp, uint8_t *secret, const uint8_t *message) { int use_curve0 = !(message[0] & kp->params->curve_bit); const EC_GROUP *ca = use_curve0 ? kp->params->c0 : kp->params->c1; const BIGNUM *sa = use_curve0 ? kp->s0 : kp->s1; EC_POINT *q = 0, *r = 0; uint8_t *unpadded = 0; BIGNUM x, y; size_t mlen = kp->params->msgsize; int rv; if (!kp->s0 || !kp->s1) /* secret key not available */ return -1; BN_init(&x); BN_init(&y); FAILZ(q = EC_POINT_new(ca)); FAILZ(r = EC_POINT_new(ca)); FAILZ(unpadded = malloc(mlen + 1)); /* Copy the message, erase the padding bits, and put an 0x02 byte on the front so we can use EC_POINT_oct2point to recover the y-coordinate. */ unpadded[0] = 0x02; unpadded[1] = (message[0] & ~(kp->params->pad_mask|kp->params->curve_bit)); memcpy(&unpadded[2], &message[1], mlen - 1); FAILZ(EC_POINT_oct2point(ca, q, unpadded, mlen + 1, kp->params->ctx)); FAILZ(EC_POINT_mul(ca, r, 0, q, sa, kp->params->ctx)); FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, q, &x, &y, kp->params->ctx)); if (bn2bin_padhi(&x, secret, mlen) != mlen) goto fail; FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, r, &x, &y, kp->params->ctx)); if (bn2bin_padhi(&x, secret + mlen, mlen) != mlen) goto fail; rv = 0; done: if (unpadded) { memset(unpadded, 0, mlen + 1); free(unpadded); } if (q) EC_POINT_clear_free(q); if (r) EC_POINT_clear_free(r); BN_clear(&x); BN_clear(&y); return rv; fail: rv = -1; memset(secret, 0, mlen * 2); goto done; }
static int ec_get_pubkey(EC_KEY *key, BIGNUM *x, BIGNUM *y) { const EC_POINT *pt; const EC_GROUP *grp; const EC_METHOD *meth; int rv; BN_CTX *ctx; ctx = BN_CTX_new(); if (!ctx) return 0; grp = EC_KEY_get0_group(key); pt = EC_KEY_get0_public_key(key); meth = EC_GROUP_method_of(grp); if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field) rv = EC_POINT_get_affine_coordinates_GFp(grp, pt, x, y, ctx); else # ifdef OPENSSL_NO_EC2M { fprintf(stderr, "ERROR: GF2m not supported\n"); exit(1); } # else rv = EC_POINT_get_affine_coordinates_GF2m(grp, pt, x, y, ctx); # endif BN_CTX_free(ctx); return rv; }
/* Forces the given EC_POINT to internally use affine coordinates. */ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *x, *y; int ret = 0; if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) return 1; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; if (!BN_copy(&point->X, x)) goto err; if (!BN_copy(&point->Y, y)) goto err; if (!BN_one(&point->Z)) goto err; ret = 1; err: if (ctx) BN_CTX_end(ctx); if (new_ctx) BN_CTX_free(new_ctx); return ret; }
/*- * Indicates whether two points are equal. * Return values: * -1 error * 0 equal (in affine coordinates) * 1 not equal */ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { BIGNUM *aX, *aY, *bX, *bY; BN_CTX *new_ctx = NULL; int ret = -1; if (EC_POINT_is_at_infinity(group, a)) { return EC_POINT_is_at_infinity(group, b) ? 0 : 1; } if (EC_POINT_is_at_infinity(group, b)) return 1; if (a->Z_is_one && b->Z_is_one) { return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return -1; } BN_CTX_start(ctx); aX = BN_CTX_get(ctx); aY = BN_CTX_get(ctx); bX = BN_CTX_get(ctx); bY = BN_CTX_get(ctx); if (bY == NULL) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err; ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; err: if (ctx) BN_CTX_end(ctx); if (new_ctx) BN_CTX_free(new_ctx); return ret; }
Handle<JwkEc> JwkEc::From(Handle<ScopedEVP_PKEY> pkey, int &key_type) { LOG_FUNC(); LOG_INFO("Check key_type"); if (!(key_type == NODESSL_KT_PRIVATE || key_type == NODESSL_KT_PUBLIC)) { THROW_ERROR("Wrong value of key_type"); } LOG_INFO("Check pkey"); if (pkey == nullptr) { THROW_ERROR("Key value is nullptr"); } if (pkey->Get()->type != EVP_PKEY_EC) { THROW_ERROR("Key is not EC type"); } LOG_INFO("Create JWK Object"); Handle<JwkEc> jwk(new JwkEc()); EC_KEY *ec = nullptr; const EC_POINT *point = nullptr; ScopedBN_CTX ctx(nullptr); const EC_GROUP *group = nullptr; LOG_INFO("Convert EC to JWK"); ec = pkey->Get()->pkey.ec; point = EC_KEY_get0_public_key(const_cast<const EC_KEY*>(ec)); group = EC_KEY_get0_group(ec); ctx = BN_CTX_new(); LOG_INFO("Get curve name"); jwk->crv = EC_GROUP_get_curve_name(group); ScopedBIGNUM x, y; x = BN_CTX_get(ctx.Get()); y = BN_CTX_get(ctx.Get()); LOG_INFO("Get public key"); if (1 != EC_POINT_get_affine_coordinates_GF2m(group, point, x.Get(), y.Get(), ctx.Get())) { THROW_OPENSSL("EC_POINT_get_affine_coordinates_GF2m"); } jwk->x = BN_dup(x.Get()); jwk->y = BN_dup(y.Get()); if (key_type == NODESSL_KT_PRIVATE) { const BIGNUM *d = EC_KEY_get0_private_key(const_cast<const EC_KEY*>(ec)); jwk->d = BN_dup(d); if (jwk->d.isEmpty()) { THROW_OPENSSL("EC_KEY_get0_private_key"); } } return jwk; }
BUF_MEM * Comp(EVP_PKEY *key, const BUF_MEM *pub, BN_CTX *bn_ctx, EVP_MD_CTX *md_ctx) { BUF_MEM *out = NULL; const EC_GROUP *group; EC_POINT *ecp = NULL; EC_KEY *ec = NULL; BIGNUM *x = NULL, *y = NULL; check((key && pub), "Invalid arguments"); switch (EVP_PKEY_base_id(key)) { case EVP_PKEY_DH: out = hash(EVP_sha1(), md_ctx, NULL, pub); break; case EVP_PKEY_EC: ec = EVP_PKEY_get1_EC_KEY(key); if (!ec) goto err; group = EC_KEY_get0_group(ec); ecp = EC_POINT_new(group); x = BN_CTX_get(bn_ctx); y = BN_CTX_get(bn_ctx); if(!ecp || !x || !y || !EC_POINT_oct2point(group, ecp, (unsigned char *) pub->data, pub->length, bn_ctx) || !EC_POINT_get_affine_coordinates_GF2m(group, ecp, x, y, bn_ctx)) goto err; out = BUF_MEM_create(BN_num_bytes(x)); if(!out || !BN_bn2bin(x, (unsigned char *) out->data)) goto err; break; default: log_err("Unknown protocol"); goto err; } err: if (ecp) EC_POINT_free(ecp); /* Decrease the reference count, the key is still available in the EVP_PKEY * structure */ if (ec) EC_KEY_free(ec); if (x) BN_free(x); if (y) BN_free(y); return out; }
static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) { EC_KEY *a = NULL; EC_KEY *b = NULL; BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; char buf[12]; unsigned char *abuf = NULL, *bbuf = NULL; int i, alen, blen, aout, bout, ret = 0; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); b = EC_KEY_new_by_curve_name(nid); if (a == NULL || b == NULL) goto err; group = EC_KEY_get0_group(a); if ((x_a = BN_new()) == NULL) goto err; if ((y_a = BN_new()) == NULL) goto err; if ((x_b = BN_new()) == NULL) goto err; if ((y_b = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); # ifdef NOISY BIO_puts(out, "\n"); # else (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(a)) 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, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 1="); BN_print(out, a->priv_key); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); # else BIO_printf(out, " ."); (void)BIO_flush(out); # endif if (!EC_KEY_generate_key(b)) 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, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } # endif # ifdef NOISY BIO_puts(out, " pri 2="); BN_print(out, b->priv_key); BIO_puts(out, "\n pub 2="); BN_print(out, x_b); BIO_puts(out, ","); BN_print(out, y_b); BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif alen = KDF1_SHA1_len; abuf = (unsigned char *)OPENSSL_malloc(alen); aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key1 ="); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif blen = KDF1_SHA1_len; bbuf = (unsigned char *)OPENSSL_malloc(blen); bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); # ifdef NOISY BIO_puts(out, " key2 ="); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); # else BIO_printf(out, "."); (void)BIO_flush(out); # endif if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { # ifndef NOISY BIO_printf(out, " failed\n\n"); BIO_printf(out, "key a:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(a)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_a); BIO_printf(out, ","); BN_print(out, y_a); BIO_printf(out, "\nkey b:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(b)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_b); BIO_printf(out, ","); BN_print(out, y_b); BIO_printf(out, "\n"); BIO_printf(out, "generated key a: "); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); BIO_printf(out, "generated key b: "); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); # endif fprintf(stderr, "Error in ECDH routines\n"); ret = 0; } else { # ifndef NOISY BIO_printf(out, " ok\n"); # endif ret = 1; } err: ERR_print_errors_fp(stderr); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (x_b) BN_free(x_b); if (y_b) BN_free(y_b); if (b) EC_KEY_free(b); if (a) EC_KEY_free(a); return (ret); }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { 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 (!BN_rand_range(k, order)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_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)) { 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; } } 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; } } 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 (!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); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return(ret); }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (8 * dgst_len > BN_num_bits(order)) { /* XXX * * Should provide for optional hash truncation: * Keep the BN_num_bits(order) leftmost bits of dgst * (see March 2006 FIPS 186-3 draft, which has a few * confusing errors in this part though) */ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); ret = 0; goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, 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, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (point) EC_POINT_free(point); return ret; }
SM2CiphertextValue *SM2_do_encrypt(const EVP_MD *md, const unsigned char *in, size_t inlen, EC_KEY *ec_key) { SM2CiphertextValue *ret = NULL; SM2CiphertextValue *cv = NULL; const EC_GROUP *group; const EC_POINT *pub_key; KDF_FUNC kdf; EC_POINT *ephem_point = NULL; EC_POINT *share_point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BIGNUM *k = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; int nbytes; size_t len; size_t i; unsigned int hashlen; /* check arguments */ if (!md || !in || !ec_key) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (inlen < SM2_MIN_PLAINTEXT_LENGTH || inlen > SM2_MAX_PLAINTEXT_LENGTH) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PLAINTEXT_LENGTH); return 0; } if (!(kdf = KDF_get_x9_63(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_DIGEST_ALGOR); return 0; } if (!(group = EC_KEY_get0_group(ec_key)) || !(pub_key = EC_KEY_get0_public_key(ec_key))) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_EC_KEY); return 0; } /* malloc */ if (!(cv = SM2CiphertextValue_new()) || !(ephem_point = EC_POINT_new(group)) || !(share_point = EC_POINT_new(group)) || !(n = BN_new()) || !(h = BN_new()) || !(k = BN_new()) || !(bn_ctx = BN_CTX_new()) || !(md_ctx = EVP_MD_CTX_new())) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); goto end; } if (!ASN1_OCTET_STRING_set(cv->ciphertext, NULL, (int)inlen) || !ASN1_OCTET_STRING_set(cv->hash, NULL, EVP_MD_size(md))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_ASN1_LIB); goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(group, n, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) { ECerr(EC_F_SM2_DO_ENCRYPT, EC_R_ERROR); goto end; } nbytes = (EC_GROUP_get_degree(group) + 7) / 8; /* check [h]P_B != O */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } if (EC_POINT_is_at_infinity(group, share_point)) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_INVALID_PUBLIC_KEY); goto end; } do { size_t size; /* rand k in [1, n-1] */ do { BN_rand_range(k, n); } while (BN_is_zero(k)); /* compute ephem_point [k]G = (x1, y1) */ if (!EC_POINT_mul(group, ephem_point, k, NULL, NULL, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute ECDH share_point [k]P_B = (x2, y2) */ if (!EC_POINT_mul(group, share_point, NULL, pub_key, k, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } /* compute t = KDF(x2 || y2, klen) */ if (!(len = EC_POINT_point2oct(group, share_point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } size = cv->ciphertext->length; kdf(buf + 1, len - 1, cv->ciphertext->data, &size); if (size != inlen) { SM2err(SM2_F_SM2_DO_ENCRYPT, SM2_R_KDF_FAILURE); goto end; } /* ASN1_OCTET_STRING_is_zero in asn1.h and a_octet.c */ } while (ASN1_OCTET_STRING_is_zero(cv->ciphertext)); /* set x/yCoordinates as (x1, y1) */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, ephem_point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EC_LIB); goto end; } } /* ciphertext = t xor in */ for (i = 0; i < inlen; i++) { cv->ciphertext->data[i] ^= in[i]; } /* generate hash = Hash(x2 || M || y2) */ hashlen = cv->hash->length; if (!EVP_DigestInit_ex(md_ctx, md, NULL) || !EVP_DigestUpdate(md_ctx, buf + 1, nbytes) || !EVP_DigestUpdate(md_ctx, in, inlen) || !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes) || !EVP_DigestFinal_ex(md_ctx, cv->hash->data, &hashlen)) { SM2err(SM2_F_SM2_DO_ENCRYPT, ERR_R_EVP_LIB); goto end; } ret = cv; cv = NULL; end: SM2CiphertextValue_free(cv); EC_POINT_free(share_point); EC_POINT_free(ephem_point); BN_free(n); BN_free(h); BN_clear_free(k); BN_CTX_free(bn_ctx); EVP_MD_CTX_free(md_ctx); return ret; }
/* This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH * Finally an optional KDF is applied. */ static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen, len; unsigned char *buf=NULL; if (outlen > INT_MAX) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */ return -1; } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if ((tmp=EC_POINT_new(group)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); 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, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7)/8; len = BN_num_bytes(x); if (len > buflen) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR); goto err; } if ((buf = malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); free(buf); return(ret); }
void char2_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL; EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z, *cof; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "13")) ABORT; if (!BN_hex2bn(&a, "3")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n(0x... means binary polynomial)\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); cof = BN_new(); if (!x || !y || !z || !cof) ABORT; if (!BN_hex2bn(&x, "6")) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT; #else if (!BN_hex2bn(&y, "8")) ABORT; if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif if (!EC_POINT_is_on_curve(group, Q, ctx)) { /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octet string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve K-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-163", "0800000000000000000000000000000000000000C9", "1", "1", "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", "0289070FB05D38FF58321F2E800536D538CCDAA3D9", 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, C2_K163 ); /* Curve B-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-163", "0800000000000000000000000000000000000000C9", "1", "020A601907B8C953CA1481EB10512F78744A3205FD", "03F0EBA16286A2D57EA0991168D4994637E8343E36", "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, C2_B163 ); /* Curve K-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-233", "020000000000000000000000000000000000000004000000000000000001", "0", "1", "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", 0, "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", "4", 233, C2_K233 ); /* Curve B-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-233", "020000000000000000000000000000000000000004000000000000000001", "000000000000000000000000000000000000000000000000000000000001", "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", 1, "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", "2", 233, C2_B233 ); /* Curve K-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "0", "1", "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", 0, "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", "4", 283, C2_K283 ); /* Curve B-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "000000000000000000000000000000000000000000000000000000000000000000000001", "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", "2", 283, C2_B283 ); /* Curve K-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "0", "1", "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", 1, "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", "4", 409, C2_K409 ); /* Curve B-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", 1, "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", "2", 409, C2_B409 ); /* Curve K-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "0", "1", "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", 0, "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", "4", 571, C2_K571 ); /* Curve B-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", "2", 571, C2_B571 ); /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(C2_K163, TIMING_BASE_PT, ctx); timings(C2_K163, TIMING_RAND_PT, ctx); timings(C2_K163, TIMING_SIMUL, ctx); timings(C2_B163, TIMING_BASE_PT, ctx); timings(C2_B163, TIMING_RAND_PT, ctx); timings(C2_B163, TIMING_SIMUL, ctx); timings(C2_K233, TIMING_BASE_PT, ctx); timings(C2_K233, TIMING_RAND_PT, ctx); timings(C2_K233, TIMING_SIMUL, ctx); timings(C2_B233, TIMING_BASE_PT, ctx); timings(C2_B233, TIMING_RAND_PT, ctx); timings(C2_B233, TIMING_SIMUL, ctx); timings(C2_K283, TIMING_BASE_PT, ctx); timings(C2_K283, TIMING_RAND_PT, ctx); timings(C2_K283, TIMING_SIMUL, ctx); timings(C2_B283, TIMING_BASE_PT, ctx); timings(C2_B283, TIMING_RAND_PT, ctx); timings(C2_B283, TIMING_SIMUL, ctx); timings(C2_K409, TIMING_BASE_PT, ctx); timings(C2_K409, TIMING_RAND_PT, ctx); timings(C2_K409, TIMING_SIMUL, ctx); timings(C2_B409, TIMING_BASE_PT, ctx); timings(C2_B409, TIMING_RAND_PT, ctx); timings(C2_B409, TIMING_SIMUL, ctx); timings(C2_K571, TIMING_BASE_PT, ctx); timings(C2_K571, TIMING_RAND_PT, ctx); timings(C2_K571, TIMING_SIMUL, ctx); timings(C2_B571, TIMING_BASE_PT, ctx); timings(C2_B571, TIMING_RAND_PT, ctx); timings(C2_B571, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); BN_free(cof); if (C2_K163) EC_GROUP_free(C2_K163); if (C2_B163) EC_GROUP_free(C2_B163); if (C2_K233) EC_GROUP_free(C2_K233); if (C2_B233) EC_GROUP_free(C2_B233); if (C2_K283) EC_GROUP_free(C2_K283); if (C2_B283) EC_GROUP_free(C2_B283); if (C2_K409) EC_GROUP_free(C2_K409); if (C2_B409) EC_GROUP_free(C2_B409); if (C2_K571) EC_GROUP_free(C2_K571); if (C2_B571) EC_GROUP_free(C2_B571); }
/* * Computes a + b and stores the result in r. r could be a or b, a could be * b. Uses algorithm A.10.2 of IEEE P1363. */ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; int ret = 0; if (EC_POINT_is_at_infinity(group, a)) { if (!EC_POINT_copy(r, b)) return 0; return 1; } if (EC_POINT_is_at_infinity(group, b)) { if (!EC_POINT_copy(r, a)) return 0; return 1; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); x0 = BN_CTX_get(ctx); y0 = BN_CTX_get(ctx); x1 = BN_CTX_get(ctx); y1 = BN_CTX_get(ctx); x2 = BN_CTX_get(ctx); y2 = BN_CTX_get(ctx); s = BN_CTX_get(ctx); t = BN_CTX_get(ctx); if (t == NULL) goto err; if (a->Z_is_one) { if (!BN_copy(x0, &a->X)) goto err; if (!BN_copy(y0, &a->Y)) goto err; } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err; } if (b->Z_is_one) { if (!BN_copy(x1, &b->X)) goto err; if (!BN_copy(y1, &b->Y)) goto err; } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err; } if (BN_GF2m_cmp(x0, x1)) { if (!BN_GF2m_add(t, x0, x1)) goto err; if (!BN_GF2m_add(s, y0, y1)) goto err; if (!group->meth->field_div(group, s, s, t, ctx)) goto err; if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; if (!BN_GF2m_add(x2, x2, &group->a)) goto err; if (!BN_GF2m_add(x2, x2, s)) goto err; if (!BN_GF2m_add(x2, x2, t)) goto err; } else { if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { if (!EC_POINT_set_to_infinity(group, r)) goto err; ret = 1; goto err; } if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err; if (!BN_GF2m_add(s, s, x1)) goto err; if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; if (!BN_GF2m_add(x2, x2, s)) goto err; if (!BN_GF2m_add(x2, x2, &group->a)) goto err; } if (!BN_GF2m_add(y2, x1, x2)) goto err; if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err; if (!BN_GF2m_add(y2, y2, x2)) goto err; if (!BN_GF2m_add(y2, y2, y1)) goto err; if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err; ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
// unsigned char *rgbHashData, 哈希数值 // unsigned char *rgbKeyPb, SM2公钥数据,Px Py 不含标志位 point_conversion_form_t // unsigned char *rs 待验证的签名数据 unsigned char eccVerifySignature(unsigned char *rgbHashData, unsigned char *rgbKeyPb, unsigned char *rs) { int ret = SM2_VERIFY_INNER_ERROR; EC_POINT *point = NULL; BN_CTX *ctx = NULL; BIGNUM *order = NULL; BIGNUM *e = NULL; BIGNUM *t = NULL; int i; EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); BIGNUM *x = BN_new();; BIGNUM *y = BN_new();; if (!BN_bin2bn(rgbKeyPb, 32, x)) { goto err; } if (!BN_bin2bn(rgbKeyPb + 32, 32, y)) { goto err; } if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) { goto err; } const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key); BIGNUM *r= BN_new(), *s = BN_new(); BN_bin2bn(rs, 32, r); BN_bin2bn(rs + 32, 32, s); //// 相当于 //EC_KEY *ret = EC_KEY_new(); EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); ctx = BN_CTX_new(); order = BN_new(); e = BN_new(); t = BN_new(); if (!ctx || !order || !e || !t) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } /* check r, s in [1, n-1] and r + s != 0 (mod n) */ if (BN_is_zero(r) || BN_is_negative(r) || BN_ucmp(r, order) >= 0 || BN_is_zero(s) || BN_is_negative(s) || BN_ucmp(s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; goto err; } /* check t = r + s != 0 */ if (!BN_mod_add(t, r, s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_is_zero(t)) { ret = 0; goto err; } /* convert digest to e */ i = BN_num_bits(order); #if 0 if (8 * dgstlen > i) { dgstlen = (i + 7)/8; } #endif if (!BN_bin2bn(rgbHashData, 32, e)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #if 0 if ((8 * dgstlen > i) && !BN_rshift(e, e, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } #endif /* compute (x, y) = sG + tP, P is pub_key */ if (!(point = EC_POINT_new(ec_group))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(ec_group, point, s, pub_key, t, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, t, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } if (!BN_nnmod(t, t, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* check (sG + tP).x + e == sig.r */ if (!BN_mod_add(t, t, e, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (BN_ucmp(t, r) == 0) { ret = SM2_VERIFY_SUCCESS; } else { ret = SM2_VERIFY_FAILED; } err: if (point) EC_POINT_free(point); if (order) BN_free(order); if (e) BN_free(e); if (t) BN_free(t); if (ctx) BN_CTX_free(ctx); return 0; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ 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_VERIFY, 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_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, 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, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, 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, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (point) EC_POINT_free(point); return ret; }
static int compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) { const EC_GROUP* group; int ret; group = EC_KEY_get0_group(ecdh); // only use our solution if the curve name is SECT163K1 if (EC_GROUP_get_curve_name(group) == NID_sect163k1) { const BIGNUM* rkey; BN_CTX *ctx; BIGNUM* x, *y; mm256_point_t p, q; mm_256 mkey; int r; ctx = BN_CTX_new(); BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); rkey = EC_KEY_get0_private_key(ecdh); memset(&mkey, 0, sizeof(mkey)); memcpy(&mkey, rkey->d, sizeof(rkey->d[0]) * rkey->top); ec2m_import_key(&mkey); r = EC_POINT_get_affine_coordinates_GF2m(group, pub_key, x, y, ctx); memset(&p, 0, sizeof(p)); memcpy(&p.x, x->d, sizeof(x->d[0]) * x->top); memcpy(&p.y, y->d, sizeof(y->d[0]) * y->top); p.z.iv[0] = 1; r = ec2m_private_operation(&p, &q); if (r < 0) { fprintf(stderr, "invalid result: %d\n", r); } int xlen = (163 + 7) / 8; if (KDF != 0) { if (KDF(&q.x, xlen, out, &outlen) == NULL) { return -1; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > xlen) outlen = xlen; memcpy(out, &q.x, outlen); ret = outlen; } BN_CTX_end(ctx); BN_CTX_free(ctx); } else { // use the default method const ECDH_METHOD* meth = ECDH_OpenSSL(); return meth->compute_key(out, outlen, pub_key, ecdh, KDF); } return ret; }
/*- * This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH */ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh) { BN_CTX *ctx; EC_POINT *tmp = NULL; BIGNUM *x = NULL, *y = NULL; const BIGNUM *priv_key; const EC_GROUP *group; int ret = 0; size_t buflen, len; unsigned char *buf = NULL; if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { if (!EC_GROUP_get_cofactor(group, x, NULL) || !BN_mul(x, x, priv_key, ctx)) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); 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, x, y, ctx)) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7) / 8; len = BN_num_bytes(x); if (len > buflen) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB); goto err; } *pout = buf; *poutlen = buflen; buf = NULL; ret = 1; err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_free(buf); return ret; }
int main(int argc, char *argv[]) { void *bb; BN_CTX *ctx = NULL; int nid; BIO *out; CRYPTO_malloc_debug_init(); CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); const char *text = "NIST Prime-Curve P-192"; #ifdef OPENSSL_SYS_WIN32 CRYPTO_malloc_init(); #endif RAND_seed(rnd_seed, sizeof rnd_seed); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); if ((ctx = BN_CTX_new()) == NULL) goto err; nid = NID_X9_62_prime192v1; //EC_POINT *bb; EC_KEY *a = NULL; //EC_KEY is a structure BIGNUM *x_a = NULL, *y_a = NULL; char buf[12]; //unsigned char *abuf=NULL,*bbuf=NULL; int i, alen, blen, aout, bout; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); if (a == NULL) goto err; group = EC_KEY_get0_group(a); if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); if (!EC_KEY_generate_key(a)) goto err; printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } BIO_puts(out, " pri 1="); BN_print(out, EC_KEY_get0_private_key(a)); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); func(EC_KEY_get0_public_key(a)); err: ERR_print_errors_fp(stderr); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (a) EC_KEY_free(a); if (ctx) BN_CTX_free(ctx); BIO_free(out); CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); CRYPTO_mem_leaks_fp(stderr); return 0; }
return NULL; #endif } int main(void) { unsigned char *abuf = NULL; //const EC_POINT *public_key; int i, alen, aout, jj = 0; int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information socklen_t sin_size; int yes = 1, numbytes; char buf[MAXDATASIZE]; /*//////////////////////////////////////////////////////////////Generating Keys/////////////////////////////////////*/ BN_CTX *ctx = NULL; int nid; BIO *out; CRYPTO_malloc_debug_init(); CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); const char *text = "NIST Prime-Curve P-192"; #ifdef OPENSSL_SYS_WIN32 CRYPTO_malloc_init(); #endif RAND_seed(rnd_seed, sizeof rnd_seed); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); if ((ctx = BN_CTX_new()) == NULL) goto err; nid = NID_X9_62_prime192v1; EC_KEY *a = NULL; //EC_KEY is a structure BIGNUM *x_a = NULL, *y_a = NULL; const BIGNUM *BIG = NULL; char *buff; //unsigned char *abuf=NULL,*bbuf=NULL; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); if (a == NULL) goto err; group = EC_KEY_get0_group(a); // aa=EC_POINT_new(group); if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; // if ((BIG=BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); if (!EC_KEY_generate_key(a)) goto err; printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } BIO_puts(out, " pri 1="); BN_print(out, EC_KEY_get0_private_key(a)); BIO_puts(out, "\n pub 1="); BN_print(out, x_a); BIO_puts(out, ","); BN_print(out, y_a); BIO_puts(out, "\n"); /* printf("importnt work\n"); //BN_print(out,x_a); buff=BN_bn2dec(x_a); printf("%s\n",buff); BN_dec2bn(&(x_a),buff); printf("%s\n",buff); BN_print(out,x_a); */ /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof my_addr) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } while (1) { // main accept() loop sin_size = sizeof their_addr; if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); // BN_print(out,x_a); // if ((jj=send(new_fd, &aa, sizeof(BIGNUM), 0)) == -1) // perror("send"); ////////////////////////////////////////////////////////////////////////////// //printf("side %d\n",sizeof(EC_POINT*)); //aa= EC_KEY_get0_public_key(a); //printf("side %d\n",sizeof(aa)); // if ((jj=send(new_fd, &aa, sizeof(EC_POINT*), 0)) == -1) //perror("send"); //printf("\nbytes send %d\n",jj); //////////////////////////////////////////////////////////////////////////////// //x_a=(BIGNUM*)&buff; //BN_print(out,x_a); //printf("%d",sizeof(EC_POINT)); //buff=(char*)&x_a; //if (send(new_fd, &x_a, sizeof(x_a), 0) == -1) //perror("send"); //buff[10]='\0'; //BIG =EC_KEY_get0_private_key(a); //BN_print(out,BIG); /* buff=BN_bn2dec(x_a); // BN_print(out,BIG); buff=(char*)&x_a; //buff[10]='\0'; printf("%s\n",buff); x_a=(BIGNUM*)&buff; BN_dec2bn(&(y_a),buff); printf("%s",buff); */ //sprintf(buff,"%u",EC_KEY_get0_private_key(a)); //printf("send: %d\n",BIG); //printf("%s",buff); //printf("%d",strlen(buff)); // float data1; //char data2[64]; //BIG=(BIGNUM*)(buff); //BIO_puts(out,BIG); //memcpy((void*)buff, (void*)EC_KEY_get0_private_key(a), 20); //printf("%s",buff); //for (i=0; i<10; i++) //{ //printf("%c",buff[i]); //BIO_puts(out,buff); //} //if (send(new_fd,buff,strlen(buff), 0) == -1) // { // perror("send"); // } //printf("\npublic key send\n"); /* //EC_POINT *bb; if ((numbytes=recv(new_fd,(char*)&bb,500, 0)) == -1) { perror("recv"); exit(1); } printf("\npublic key received\n"); */ /* if ((numbytes=recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } */ // buf[numbytes] = '\0'; /* printf("Received: %d",numbytes); printf("working\n"); alen=KDF1_SHA1_len; ///it is a static constant integer. printf("working\n"); abuf=(unsigned char *)OPENSSL_malloc(alen); printf("working\n"); if(abuf==NULL || bb==NULL || a==NULL) printf("i hate you error\n"); aout=ECDH_compute_key(abuf,alen,bb,a,KDF1_SHA1); //generating session key printf("working\n"); // BN_print(out, abuf); //BIO_puts(out,"\n"); BIO_puts(out," key1 ="); for (i=0; i<aout; i++) { sprintf(buf,"%02X",abuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); */ close(new_fd); exit(0); close(new_fd); // parent doesn't need this } err: ERR_print_errors_fp(stderr); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (a) EC_KEY_free(a); if (ctx) BN_CTX_free(ctx); BIO_free(out); CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0);
static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) { printf("in ecdh test\n"); EC_KEY *a = NULL; //EC_KEY is a structure EC_KEY *b = NULL; BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; char buf[12]; unsigned char *abuf = NULL, *bbuf = NULL; int i, alen, blen, aout, bout, ret = 0; const EC_GROUP *group; a = EC_KEY_new_by_curve_name(nid); // creates a new key according to the curve specified //it fills in the EC_KEY structure // use function called EC_KEY *EC_KEY_new(void) //also use a function called EC_GROUP_new_by_curve_name() creates a EC_GROUP structure specified by a curve name (in form of a NID) */ // the group returned is set in the EC_KEY structure. b = EC_KEY_new_by_curve_name(nid); if (a == NULL || b == NULL) goto err; group = EC_KEY_get0_group(a); //returns the EC_GROUP structure created by the EC_KEY structure //EC_GROUP structure is present in the EC_KEY structure. if ((x_a = BN_new()) == NULL) goto err; //BN_new returns a pointer to the bignum if ((y_a = BN_new()) == NULL) goto err; if ((x_b = BN_new()) == NULL) goto err; if ((y_b = BN_new()) == NULL) goto err; BIO_puts(out, "Testing key generation with "); BIO_puts(out, text); #ifdef NOISY printf ("noisy"); BIO_puts(out,"\n"); BIO_puts(out,"\n"); BIO_puts(out,"\n"); #else BIO_flush(out); #endif //public key number one is created here if (!EC_KEY_generate_key(a)) goto err; //pass the filled EC_KEY structure and it will create a public or private ec key. //it places the key in a->priv_key a->pub_key /// PUBLIC AND PVT KEYS ARE GENERATED BY THE SCALAR MULTIPLICATION printf("\n1 ) generating keys\n"); if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //returns the public key else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; } //BN_print_fp(stdout, a->pub_key); printf("private key is : "); BN_print_fp(stdout, EC_KEY_get0_private_key(a)); printf("\nAffine cordinates x:"); BN_print_fp(stdout, x_a); printf("\nAffine cordinates y:"); BN_print_fp(stdout, y_a); printf( "\n2 ) generated keys , generated affine points x and y , and also determided the primse brinary case\n"); #ifdef NOISY printf("no generation"); BIO_puts(out," pri 1="); BN_print(out,a->priv_key); BIO_puts(out,"\n pub 1="); BN_print(out,x_a); BIO_puts(out,","); BN_print(out,y_a); BIO_puts(out,"\n"); #else BIO_printf(out, " ."); BIO_flush(out); #endif //public key number two is created here if (!EC_KEY_generate_key(b)) 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, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; // not well } else { if (!EC_POINT_get_affine_coordinates_GF2m(group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; } // printf("public key is : "); // BN_print_fp(stdout, EC_KEY_get0_private_key(b)); // for public key they will exchange the whole EC_POINT structure printf("private key is : "); BN_print_fp(stdout, EC_KEY_get0_private_key(b)); printf("\nAffine cordinates x"); BN_print_fp(stdout, x_b); printf("\nAffine cordinates y"); BN_print_fp(stdout, y_b); #ifdef NOISY BIO_puts(out," pri 2="); BN_print(out,b->priv_key); BIO_puts(out,"\n pub 2="); BN_print(out,x_b); BIO_puts(out,","); BN_print(out,y_b); BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif alen = KDF1_SHA1_len; ///it is a static constant integer. abuf = (unsigned char *) OPENSSL_malloc(alen); aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); //generating session key // BN_print(out, abuf); //BIO_puts(out,"\n"); #ifdef NOISY BIO_puts(out," key1 ="); for (i=0; i<aout; i++) { sprintf(buf,"%02X",abuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif blen = KDF1_SHA1_len; bbuf = (unsigned char *) OPENSSL_malloc(blen); bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); // BN_print(out, bbuf); // BIO_puts(out,"\n"); #ifdef NOISY BIO_puts(out," key2 ="); for (i=0; i<bout; i++) { sprintf(buf,"%02X",bbuf[i]); BIO_puts(out,buf); } BIO_puts(out,"\n"); #else BIO_printf(out, "."); BIO_flush(out); #endif if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { #ifndef NOISY BIO_printf(out, " failed\n\n"); BIO_printf(out, "key a:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(a)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_a); BIO_printf(out, ","); BN_print(out, y_a); BIO_printf(out, "\nkey b:\n"); BIO_printf(out, "private key: "); BN_print(out, EC_KEY_get0_private_key(b)); BIO_printf(out, "\n"); BIO_printf(out, "public key (x,y): "); BN_print(out, x_b); BIO_printf(out, ","); BN_print(out, y_b); BIO_printf(out, "\n"); BIO_printf(out, "generated key a: "); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); BIO_printf(out, "generated key b: "); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_printf(out, "\n"); #endif fprintf(stderr, "Error in ECDH routines\n"); ret = 0; } else { #ifndef NOISY BIO_printf(out, " ok\n"); #endif ret = 1; } err: ERR_print_errors_fp(stderr); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if (x_a) BN_free(x_a); if (y_a) BN_free(y_a); if (x_b) BN_free(x_b); if (y_b) BN_free(y_b); if (b) EC_KEY_free(b); if (a) EC_KEY_free(a); return (ret); }
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) { BN_CTX *ctx = NULL; BIGNUM *tx, *ty; EC_POINT *point = NULL; int ok = 0; #ifndef OPENSSL_NO_EC2M int tmp_nid, is_char_two = 0; #endif if (key == NULL || key->group == NULL || x == NULL || y == NULL) { ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } ctx = BN_CTX_new(); if (ctx == NULL) return 0; BN_CTX_start(ctx); point = EC_POINT_new(key->group); if (point == NULL) goto err; tx = BN_CTX_get(ctx); ty = BN_CTX_get(ctx); if (ty == NULL) goto err; #ifndef OPENSSL_NO_EC2M tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); if (tmp_nid == NID_X9_62_characteristic_two_field) is_char_two = 1; if (is_char_two) { if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, x, y, ctx)) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, tx, ty, ctx)) goto err; } else #endif { if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx)) goto err; if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) goto err; } /* * Check if retrieved coordinates match originals and are less than field * order: if not values are out of range. */ if (BN_cmp(x, tx) || BN_cmp(y, ty) || (BN_cmp(x, key->group->field) >= 0) || (BN_cmp(y, key->group->field) >= 0)) { ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } if (!EC_KEY_set_public_key(key, point)) goto err; if (EC_KEY_check_key(key) == 0) goto err; ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(point); return ok; }
/* * Converts an EC_POINT to an octet string. If buf is NULL, the encoded * length will be returned. If the length len of buf is smaller than required * an error will be returned. */ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx) { size_t ret; BN_CTX *new_ctx = NULL; int used_ctx = 0; BIGNUM *x, *y, *yxi; size_t field_len, i, skip; if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); goto err; } if (EC_POINT_is_at_infinity(group, point)) { /* encodes to a single 0 octet */ if (buf != NULL) { if (len < 1) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); return 0; } buf[0] = 0; } return 1; } /* ret := required output buffer length */ field_len = (EC_GROUP_get_degree(group) + 7) / 8; ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; /* if 'buf' is NULL, just return required length */ if (buf != NULL) { if (len < ret) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); goto err; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); used_ctx = 1; x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); yxi = BN_CTX_get(ctx); if (yxi == NULL) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; buf[0] = form; if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) { if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; if (BN_is_odd(yxi)) buf[0]++; } i = 1; skip = field_len - BN_num_bytes(x); if (skip > field_len) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { buf[i++] = 0; skip--; } skip = BN_bn2bin(x, buf + i); i += skip; if (i != 1 + field_len) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) { skip = field_len - BN_num_bytes(y); if (skip > field_len) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { buf[i++] = 0; skip--; } skip = BN_bn2bin(y, buf + i); i += skip; } if (i != ret) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } } if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; err: if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return 0; }
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) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); 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 */ order = BN_new(); X = BN_new(); if (k == NULL || r == NULL || order == 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; } if (!EC_GROUP_get_order(group, order, ctx)) { ECerr(EC_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)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_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)) { 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)); /* 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)) { 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, EC_GROUP_get_mont_data(group))) { 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); BN_free(order); EC_POINT_free(tmp_point); BN_clear_free(X); return (ret); }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { 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; int order_bits; 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; } /* 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 (!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. * * We unconditionally perform both of these additions to prevent a * small timing information leakage. We then choose the sum that is * one bit longer than the order. This guarantees the code * path used in the constant time implementations elsewhere. * * TODO: revisit the BN_copy aiming for a memory access agnostic * conditional copy. */ if (!BN_add(r, k, order) || !BN_add(X, r, order) || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X)) 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); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return (ret); }
int MKEM_generate_message_u(const MKEM *kp, const BIGNUM *uraw, uint8_t pad, uint8_t *secret, uint8_t *message) { BIGNUM u, x, y; int use_curve0 = (BN_cmp(uraw, kp->params->n0) < 0); const EC_GROUP *ca; const EC_POINT *ga; const EC_POINT *pa; EC_POINT *q = 0, *r = 0; size_t mlen = kp->params->msgsize; int rv; BN_init(&u); BN_init(&x); BN_init(&y); if (use_curve0) { ca = kp->params->c0; ga = kp->params->g0; pa = kp->p0; FAILZ(BN_copy(&u, uraw)); } else { ca = kp->params->c1; ga = kp->params->g1; pa = kp->p1; FAILZ(BN_sub(&u, uraw, kp->params->n0)); FAILZ(BN_add(&u, &u, BN_value_one())); } FAILZ(q = EC_POINT_new(ca)); FAILZ(r = EC_POINT_new(ca)); FAILZ(EC_POINT_mul(ca, q, 0, ga, &u, kp->params->ctx)); FAILZ(EC_POINT_mul(ca, r, 0, pa, &u, kp->params->ctx)); FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, q, &x, &y, kp->params->ctx)); if (bn2bin_padhi(&x, message, mlen) != mlen) goto fail; if (message[0] & (kp->params->pad_mask|kp->params->curve_bit)) /* see below */ goto fail; memcpy(secret, message, mlen); FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, r, &x, &y, kp->params->ctx)); if (bn2bin_padhi(&x, secret + mlen, mlen) != mlen) goto fail; /* K high bits of the message will be zero. Fill in the high K-1 of them with random bits from the pad, and use the lowest bit to identify the curve in use. That bit will have a bias on the order of 2^{-d/2} where d is the bit-degree of the curve; 2^{-81} for the only curve presently implemented. This is acceptably small since an elliptic curve of d bits gives only about d/2 bits of security anyway, and is much better than allowing a timing attack via the recipient having to attempt point decompression twice for curve 1 but only once for curve 0 (or, alternatively, doubling the time required for all decryptions). */ pad &= kp->params->pad_mask; pad |= (use_curve0 ? 0 : kp->params->curve_bit); message[0] |= pad; rv = 0; done: BN_clear(&u); BN_clear(&x); BN_clear(&y); if (q) EC_POINT_clear_free(q); if (r) EC_POINT_clear_free(r); return rv; fail: memset(message, 0, mlen); memset(secret, 0, mlen * 2); rv = -1; goto done; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { 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; } #ifdef OPENSSL_FIPS if (!fips_check_ec_prng(eckey)) goto err; #endif do { /* get random k */ do 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)); #ifdef ECDSA_POINT_MUL_NO_CONSTTIME /* 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; #endif /* def(ECDSA_POINT_MUL_NO_CONSTTIME) */ /* 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 (!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); if (tmp_point != NULL) EC_POINT_free(tmp_point); if (X) BN_clear_free(X); return(ret); }
/* k in [1, n-1], (x, y) = kG */ static int sm2_sign_setup(EC_KEY *ec_key, BN_CTX *ctx_in, BIGNUM **kp, BIGNUM **xp) { int ret = 0; const EC_GROUP *ec_group; BN_CTX *ctx = NULL; BIGNUM *k = NULL; BIGNUM *x = NULL; BIGNUM *order = NULL; EC_POINT *point = NULL; if (ec_key == NULL || (ec_group = EC_KEY_get0_group(ec_key)) == 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(); x = BN_new(); order = BN_new(); if (!k || !x || !order) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if ((point = EC_POINT_new(ec_group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } do { /* get random k */ do { 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)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(ec_group, 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(ec_group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } else /* NID_X9_62_characteristic_two_field */ { if (!EC_POINT_get_affine_coordinates_GF2m(ec_group, point, x, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB); goto err; } } //FIXME: do we need this? if (!BN_nnmod(x, x, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(x)); /* clear old values if necessary */ if (*kp != NULL) BN_clear_free(*kp); if (*xp != NULL) BN_clear_free(*xp); /* save the pre-computed values */ *kp = k; *xp = x; ret = 1; err: if (!ret) { if (k) BN_clear_free(k); if (x) BN_clear_free(x); } if (ctx_in == NULL) BN_CTX_free(ctx); if (order) BN_free(order); if (point) EC_POINT_free(point); return(ret); }