static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) { assert(ctx->data == NULL); BIGNUM *private_key = BN_new(); if (private_key == NULL) { return 0; } ctx->data = private_key; /* Set up a shared |BN_CTX| for all operations. */ BN_CTX *bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) { return 0; } BN_CTX_start(bn_ctx); int ret = 0; EC_POINT *public_key = NULL; EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); if (group == NULL) { goto err; } /* Generate a private key. */ const BIGNUM *order = EC_GROUP_get0_order(group); do { if (!BN_rand_range(private_key, order)) { goto err; } } while (BN_is_zero(private_key)); /* Compute the corresponding public key and serialize it. */ public_key = EC_POINT_new(group); if (public_key == NULL || !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) || !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED, bn_ctx)) { goto err; } ret = 1; err: EC_GROUP_free(group); EC_POINT_free(public_key); BN_CTX_end(bn_ctx); BN_CTX_free(bn_ctx); return ret; }
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) { const EC_KEY *ec_key = key->pkey.ec; const EC_GROUP *group = EC_KEY_get0_group(ec_key); const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key); // See RFC 5480, section 2. CBB spki, algorithm, oid, key_bitstring; if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) || !EC_KEY_marshal_curve_name(&algorithm, group) || !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || !CBB_add_u8(&key_bitstring, 0 /* padding */) || !EC_POINT_point2cbb(&key_bitstring, group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL) || !CBB_flush(out)) { OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; } return 1; }