Add EC_KEY_priv2buf()
authorDr. Stephen Henson <steve@openssl.org>
Thu, 4 Feb 2016 23:18:57 +0000 (23:18 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 5 Feb 2016 00:33:33 +0000 (00:33 +0000)
Add new function EC_KEY_priv2buf() to allocated and encode private
key octet in one call. Update and simplify ASN.1 and print routines.

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
crypto/ec/ec_ameth.c
crypto/ec/ec_asn1.c
crypto/ec/ec_key.c
include/openssl/ec.h

index 322116b..9420875 100644 (file)
@@ -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;
 }
 
index 92bfe06..fe2a979 100644 (file)
@@ -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);
 }
index 19628b1..57388da 100644 (file)
@@ -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;
+}
index 7fed45f..e39704b 100644 (file)
@@ -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          */