int ecdh_compute_key_point(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 = NULL; EC_POINT *tmp=NULL; const BIGNUM *priv_key; const EC_GROUP* group; int ret= -1; size_t buflen; unsigned char *buf=NULL; check((outlen < INT_MAX), "out of memory"); /* sort of, anyway */ if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); priv_key = EC_KEY_get0_private_key(ecdh); check(priv_key, "No pivate key"); group = EC_KEY_get0_group(ecdh); tmp = EC_POINT_new(group); check(tmp, "Out of memory"); check((EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)), "Arithmetic error"); buflen = EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh), NULL, 0, ctx); check((buflen != 0), "Failed to convert point to hex"); buf = OPENSSL_malloc(buflen); check(buf, "Out of memory"); check((buflen == EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh), buf, buflen, ctx)), "Failed to convert point to hex"); if (KDF != 0) { check((KDF(buf, buflen, out, &outlen) != NULL), "Key derivation function failed"); ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: if (tmp) EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); if (ctx) BN_CTX_free(ctx); if (buf) OPENSSL_free(buf); return(ret); }
// Extract the private and public keys from the PEM file, using the supplied // password to decrypt the file if encrypted. priv_key and pub_key must point to // an array o at least 65 and 131 character respectively. int load_pem_key(char *pemstr, size_t pemstr_len, char *password, char *out_priv_key, char *out_pub_key) { BIO *in = NULL; BN_CTX *ctx = NULL; const EC_GROUP *group; EC_KEY *eckey = NULL; const EC_POINT *pub_key_point = NULL; const BIGNUM *priv_key = NULL, *pub_key = NULL; char *priv_key_hex = NULL; char *pub_key_hex = NULL; in = BIO_new_mem_buf(pemstr, (int)pemstr_len); // Read key from stream, decrypting with password if not NULL if (password != NULL && strcmp("", password) != 0) { // Initialize ciphers ERR_load_crypto_strings (); OpenSSL_add_all_algorithms (); eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, password); if (eckey == NULL) { return -1; // Failed to decrypt or decode private key } } else { if ((eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL)) == NULL) { return -1; // Failed to decode private key } } BIO_free(in); // Deconstruct key into big numbers if ((ctx = BN_CTX_new()) == NULL) { return -2; // Failed to create new big number context } if ((group = EC_KEY_get0_group(eckey)) == NULL) { return -3; // Failed to load group } if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) { return -4; // Failed to load private key } if ((pub_key_point = EC_KEY_get0_public_key(eckey)) == NULL) { return -5; // Failed to load public key point } pub_key = EC_POINT_point2bn(group, pub_key_point, EC_KEY_get_conv_form(eckey), NULL, ctx); if (pub_key == NULL) { return -6; // Failed to construct public key from point } priv_key_hex = BN_bn2hex(priv_key); pub_key_hex = BN_bn2hex(pub_key); strncpy_s(out_priv_key, 64 + 1, priv_key_hex, 64 + 1); strncpy_s(out_pub_key, 130 + 1, pub_key_hex, 130 + 1); OPENSSL_free(priv_key_hex); OPENSSL_free(pub_key_hex); return 0; }
BUF_MEM * EC_POINT_point2buf(const EC_KEY * ecdh, BN_CTX * bn_ctx, const EC_POINT * ecp) { size_t len; BUF_MEM * out; len = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp, EC_KEY_get_conv_form(ecdh), NULL, 0, bn_ctx); if (len == 0) return NULL; out = BUF_MEM_create(len); if (!out) return NULL; out->length = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp, EC_KEY_get_conv_form(ecdh), (unsigned char *) out->data, out->max, bn_ctx); return out; }
static int openssl_ec_key_parse(lua_State*L) { EC_KEY* ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key"); int basic = luaL_opt(L,lua_toboolean, 2, 0); const EC_POINT* point = EC_KEY_get0_public_key(ec); const EC_GROUP* group = EC_KEY_get0_group(ec); const BIGNUM *priv = EC_KEY_get0_private_key(ec); lua_newtable(L); if (basic) { BIGNUM* x = BN_new(); BIGNUM* y = BN_new(); AUXILIAR_SET(L, -1, "enc_flag", EC_KEY_get_enc_flags(ec), integer); AUXILIAR_SET(L, -1, "conv_form", EC_KEY_get_conv_form(ec), integer); AUXILIAR_SET(L, -1, "curve_name", EC_GROUP_get_curve_name(group), integer); AUXILIAR_SETOBJECT(L, BN_dup(priv), "openssl.bn", -1, "d"); if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, NULL) == 1) { AUXILIAR_SETOBJECT(L, x, "openssl.bn", -1, "x"); AUXILIAR_SETOBJECT(L, y, "openssl.bn", -1, "y"); }; } else { AUXILIAR_SET(L, -1, "enc_flag", EC_KEY_get_enc_flags(ec), integer); AUXILIAR_SET(L, -1, "conv_form", EC_KEY_get_conv_form(ec), integer); point = EC_POINT_dup(point, group); AUXILIAR_SETOBJECT(L, point, "openssl.ec_point", -1, "pub_key"); group = EC_GROUP_dup(group); AUXILIAR_SETOBJECT(L, group, "openssl.ec_group", -1, "group"); OPENSSL_PKEY_GET_BN(priv, priv_key); } return 1; };
QString pki_key::ecPubKey() { QString pub; if (key->type == EVP_PKEY_EC) { EC_KEY *ec = key->pkey.ec; BIGNUM *pub_key = EC_POINT_point2bn(EC_KEY_get0_group(ec), EC_KEY_get0_public_key(ec), EC_KEY_get_conv_form(ec), NULL, NULL); if (pub_key) { pub = BN2QString(pub_key); BN_free(pub_key); } } return pub; }
/* For an EC key set TLS ID and required compression based on parameters. */ static int tls1_set_ec_id(uint16_t *curve_id, uint8_t *comp_id, EC_KEY *ec) { const EC_GROUP *grp; const EC_METHOD *meth; int is_prime = 0; int nid, id; if (ec == NULL) return (0); /* Determine if it is a prime field. */ if ((grp = EC_KEY_get0_group(ec)) == NULL) return (0); if ((meth = EC_GROUP_method_of(grp)) == NULL) return (0); if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field) is_prime = 1; /* Determine curve ID. */ nid = EC_GROUP_get_curve_name(grp); id = tls1_ec_nid2curve_id(nid); /* If we have an ID set it, otherwise set arbitrary explicit curve. */ if (id != 0) *curve_id = id; else *curve_id = is_prime ? 0xff01 : 0xff02; /* Specify the compression identifier. */ if (comp_id != NULL) { if (EC_KEY_get0_public_key(ec) == NULL) return (0); if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { *comp_id = is_prime ? TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime : TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; } else { *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; } } return (1); }
int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey, const CRYPTO_BUFFER *leaf) { SSL *const ssl = hs->ssl; assert(ssl3_protocol_version(ssl) < TLS1_3_VERSION); /* Check the certificate's type matches the cipher. */ if (!(hs->new_cipher->algorithm_auth & ssl_cipher_auth_mask_for_key(pkey))) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE); return 0; } /* Check key usages for all key types but RSA. This is needed to distinguish * ECDH certificates, which we do not support, from ECDSA certificates. In * principle, we should check RSA key usages based on cipher, but this breaks * buggy antivirus deployments. Other key types are always used for signing. * * TODO(davidben): Get more recent data on RSA key usages. */ if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) { CBS leaf_cbs; CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf)); if (!ssl_cert_check_digital_signature_key_usage(&leaf_cbs)) { return 0; } } if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { /* Check the key's group and point format are acceptable. */ EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); uint16_t group_id; if (!ssl_nid_to_group_id( &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) || !tls1_check_group_id(ssl, group_id) || EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT); return 0; } } return 1; }
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { unsigned char *buffer=NULL; const char *ecstr; size_t buf_len=0, i; int ret=0, reason=ERR_R_BIO_LIB; BIGNUM *pub_key=NULL, *order=NULL; BN_CTX *ctx=NULL; const EC_GROUP *group; const EC_POINT *public_key; const BIGNUM *priv_key; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } if (ktype > 0) { public_key = EC_KEY_get0_public_key(x); if (public_key != NULL) { if ((pub_key = EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) { reason = ERR_R_EC_LIB; goto err; } buf_len = (size_t)BN_num_bytes(pub_key); } } if (ktype == 2) { priv_key = EC_KEY_get0_private_key(x); if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) buf_len = i; } else priv_key = NULL; if (ktype > 0) { buf_len += 10; if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } } if (ktype == 2) ecstr = "Private-Key"; else if (ktype == 1) ecstr = "Public-Key"; else ecstr = "ECDSA-Parameters"; if (!BIO_indent(bp, off, 128)) goto err; if ((order = BN_new()) == NULL) goto err; if (!EC_GROUP_get_order(group, order, NULL)) goto err; if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) goto err; if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) goto err; if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, buffer, off)) goto err; if (!ECPKParameters_print(bp, group, off)) goto err; ret=1; err: if (!ret) ECerr(EC_F_DO_EC_KEY_PRINT, reason); if (pub_key) BN_free(pub_key); if (order) BN_free(order); if (ctx) BN_CTX_free(ctx); if (buffer != NULL) OPENSSL_free(buffer); return(ret); }
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { uint8_t *buffer = NULL; const char *ecstr; size_t buf_len = 0, i; int ret = 0, reason = ERR_R_BIO_LIB; BN_CTX *ctx = NULL; const EC_GROUP *group; const EC_POINT *public_key; const BIGNUM *priv_key; uint8_t *pub_key_bytes = NULL; size_t pub_key_bytes_len = 0; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; } ctx = BN_CTX_new(); if (ctx == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } if (ktype > 0) { public_key = EC_KEY_get0_public_key(x); if (public_key != NULL) { pub_key_bytes_len = EC_POINT_point2oct( group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx); if (pub_key_bytes_len == 0) { reason = ERR_R_MALLOC_FAILURE; goto err; } pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len); if (pub_key_bytes == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } pub_key_bytes_len = EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x), pub_key_bytes, pub_key_bytes_len, ctx); if (pub_key_bytes_len == 0) { reason = ERR_R_MALLOC_FAILURE; goto err; } buf_len = pub_key_bytes_len; } } if (ktype == 2) { priv_key = EC_KEY_get0_private_key(x); if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) { buf_len = i; } } else { priv_key = NULL; } if (ktype > 0) { buf_len += 10; if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { reason = ERR_R_MALLOC_FAILURE; goto err; } } if (ktype == 2) { ecstr = "Private-Key"; } else if (ktype == 1) { ecstr = "Public-Key"; } else { ecstr = "ECDSA-Parameters"; } if (!BIO_indent(bp, off, 128)) { goto err; } const BIGNUM *order = EC_GROUP_get0_order(group); if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) { goto err; } if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) { goto err; } if (pub_key_bytes != NULL) { BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off); } /* TODO(fork): implement */ /* if (!ECPKParameters_print(bp, group, off)) goto err; */ ret = 1; err: if (!ret) { OPENSSL_PUT_ERROR(EVP, reason); } OPENSSL_free(pub_key_bytes); BN_CTX_free(ctx); OPENSSL_free(buffer); return ret; }
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) { const char *ecstr; unsigned char *priv = NULL, *pub = NULL; size_t privlen = 0, publen = 0; int ret = 0; const EC_GROUP *group; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) { publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL); if (publen == 0) goto err; } if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) { privlen = EC_KEY_priv2buf(x, &priv); if (privlen == 0) goto err; } if (ktype == EC_KEY_PRINT_PRIVATE) ecstr = "Private-Key"; else if (ktype == EC_KEY_PRINT_PUBLIC) ecstr = "Public-Key"; else ecstr = "ECDSA-Parameters"; if (!BIO_indent(bp, off, 128)) goto err; if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, EC_GROUP_order_bits(group)) <= 0) goto err; if (privlen != 0) { if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0) goto err; if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0) goto err; } if (publen != 0) { if (BIO_printf(bp, "%*spub:\n", off, "") <= 0) goto err; if (ASN1_buf_print(bp, pub, publen, off + 4) == 0) goto err; } if (!ECPKParameters_print(bp, group, off)) goto err; ret = 1; err: if (!ret) ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB); OPENSSL_clear_free(priv, privlen); OPENSSL_free(pub); return ret; }