diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 322116b3c1a8cbb7adcf9432c8535f78d99de652..942087528fd093900dd2124c7f5e53cf15b95b46 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -387,51 +387,29 @@ typedef enum { static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) { - unsigned char *buffer = NULL; const char *ecstr; - size_t priv_len = 0, pub_len = 0, buf_len = 0; - int ret = 0, reason = ERR_R_BIO_LIB; - BIGNUM *pub_key = NULL; - BN_CTX *ctx = NULL; + unsigned char *priv = NULL, *pub = NULL; + size_t privlen = 0, publen = 0; + int ret = 0; const EC_GROUP *group; - const EC_POINT *public_key = NULL; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { - reason = ERR_R_PASSED_NULL_PARAMETER; - goto err; + ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER); + return 0; } if (ktype != EC_KEY_PRINT_PARAM) { - public_key = EC_KEY_get0_public_key(x); - if (public_key != NULL) { - pub_len = EC_POINT_point2oct(group, public_key, - EC_KEY_get_conv_form(x), - NULL, 0, NULL); - if (pub_len == 0) { - reason = ERR_R_EC_LIB; - goto err; - } - buf_len = pub_len; - } + 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) { - priv_len = EC_KEY_priv2oct(x, NULL, 0); - if (priv_len == 0) { - reason = ERR_R_EC_LIB; + privlen = EC_KEY_priv2buf(x, &priv); + if (privlen == 0) goto err; - } - if (priv_len > buf_len) - buf_len = priv_len; } - if (buf_len != 0) { - buffer = OPENSSL_malloc(buf_len); - if (buffer == NULL) { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - } if (ktype == EC_KEY_PRINT_PRIVATE) ecstr = "Private-Key"; else if (ktype == EC_KEY_PRINT_PUBLIC) @@ -445,23 +423,17 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) EC_GROUP_order_bits(group)) <= 0) goto err; - if (priv_len != 0) { + if (privlen != 0) { if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0) goto err; - if (EC_KEY_priv2oct(x, buffer, priv_len) == 0) - goto err; - if (ASN1_buf_print(bp, buffer, priv_len, off + 4) == 0) + if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0) goto err; } - if (pub_len != 0) { + if (publen != 0) { if (BIO_printf(bp, "%*spub:\n", off, "") <= 0) goto err; - if (EC_POINT_point2oct(group, public_key, - EC_KEY_get_conv_form(x), - buffer, pub_len, NULL) == 0) - goto err; - if (ASN1_buf_print(bp, buffer, pub_len, off + 4) == 0) + if (ASN1_buf_print(bp, pub, publen, off + 4) == 0) goto err; } @@ -470,10 +442,9 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) ret = 1; err: if (!ret) - ECerr(EC_F_DO_EC_KEY_PRINT, reason); - BN_free(pub_key); - BN_CTX_free(ctx); - OPENSSL_clear_free(buffer, buf_len); + ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB); + OPENSSL_clear_free(priv, privlen); + OPENSSL_free(pub); return ret; } diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 92bfe06ec56ab5d71436d61a03a4c315c4bfd633..fe2a979892c94b6e9b1fa979522a9fbc0871d54e 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -1075,8 +1075,9 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) { int ret = 0, ok = 0; - unsigned char *buffer = NULL; - size_t buf_len = 0, tmp_len; + unsigned char *priv= NULL, *pub= NULL; + size_t privlen, publen; + EC_PRIVATEKEY *priv_key = NULL; if (a == NULL || a->group == NULL || @@ -1092,28 +1093,15 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) priv_key->version = a->version; - buf_len = EC_KEY_priv2oct(a, NULL, 0); + privlen = EC_KEY_priv2buf(a, &priv); - if (buf_len == 0) { + if (privlen == 0) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; } - buffer = OPENSSL_malloc(buf_len); - if (buffer == NULL) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (EC_KEY_priv2oct(a, buffer, buf_len) == 0) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - - if (!ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } + ASN1_STRING_set0(priv_key->privateKey, priv, privlen); + priv = NULL; if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) { if ((priv_key->parameters = @@ -1131,31 +1119,17 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) goto err; } - tmp_len = EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, NULL, 0, NULL); + publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL); - if (tmp_len > buf_len) { - unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); - if (!tmp_buffer) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - goto err; - } - buffer = tmp_buffer; - buf_len = tmp_len; - } - - if (!EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, buffer, buf_len, NULL)) { + if (publen == 0) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); goto err; } priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (!ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } + ASN1_STRING_set0(priv_key->publicKey, pub, publen); + pub = NULL; } if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { @@ -1164,7 +1138,8 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) } ok = 1; err: - OPENSSL_free(buffer); + OPENSSL_clear_free(priv, privlen); + OPENSSL_free(pub); EC_PRIVATEKEY_free(priv_key); return (ok ? ret : 0); } diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 19628b143539167f633dfa712d09c3d026cd49d3..57388da91ea408dadc3f2c4051f107738d83779d 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -591,3 +591,22 @@ int EC_KEY_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len) } return 1; } + +size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) +{ + size_t len; + unsigned char *buf; + len = EC_KEY_priv2oct(eckey, NULL, 0); + if (len == 0) + return 0; + buf = OPENSSL_malloc(len); + if (buf == NULL) + return 0; + len = EC_KEY_priv2oct(eckey, buf, len); + if (len == 0) { + OPENSSL_free(buf); + return 0; + } + *pbuf = buf; + return len; +} diff --git a/include/openssl/ec.h b/include/openssl/ec.h index 7fed45f7e60d308db5f3ba983b35b7450bb5adaa..e39704b355b3d51e98a1b76b70197220215cbfe5 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -953,6 +953,13 @@ int EC_KEY_oct2priv(EC_KEY *key, unsigned char *buf, size_t len); size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len); +/** Encodes an EC_KEY private key to an allocated octet string + * \param key key to encode + * \param pbuf returns pointer to allocated buffer + * \return the length of the encoded octet string or 0 if an error occurred + */ + +size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf); /********************************************************************/ /* de- and encoding functions for SEC1 ECPrivateKey */