Tighten extension handling
[openssl.git] / crypto / ec / ec_asn1.c
index 6ff94a356362e99d755efef3935f523377b23cdf..ebafc10de7aa38b26d143eaede1adb4caa4cea3f 100644 (file)
@@ -317,10 +317,8 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
         return 0;
 
     /* clear the old values (if necessary) */
-    if (field->fieldType != NULL)
-        ASN1_OBJECT_free(field->fieldType);
-    if (field->p.other != NULL)
-        ASN1_TYPE_free(field->p.other);
+    ASN1_OBJECT_free(field->fieldType);
+    ASN1_TYPE_free(field->p.other);
 
     nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
     /* set OID for the field */
@@ -423,8 +421,8 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
 
     ok = 1;
 
- err:if (tmp)
-        BN_free(tmp);
+ err:
+    BN_free(tmp);
     return (ok);
 }
 
@@ -499,8 +497,8 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
     }
 
     /* set a and b */
-    if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
-        !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
+    if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
+        !ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
         ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
         goto err;
     }
@@ -520,29 +518,23 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
             goto err;
         }
     } else {
-        if (curve->seed) {
-            ASN1_BIT_STRING_free(curve->seed);
-            curve->seed = NULL;
-        }
+        ASN1_BIT_STRING_free(curve->seed);
+        curve->seed = NULL;
     }
 
     ok = 1;
 
- err:if (buffer_1)
-        OPENSSL_free(buffer_1);
-    if (buffer_2)
-        OPENSSL_free(buffer_2);
-    if (tmp_1)
-        BN_free(tmp_1);
-    if (tmp_2)
-        BN_free(tmp_2);
+ err:
+    OPENSSL_free(buffer_1);
+    OPENSSL_free(buffer_2);
+    BN_free(tmp_1);
+    BN_free(tmp_2);
     return (ok);
 }
 
 static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
                                               ECPARAMETERS *param)
 {
-    int ok = 0;
     size_t len = 0;
     ECPARAMETERS *ret = NULL;
     BIGNUM *tmp = NULL;
@@ -628,18 +620,14 @@ static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
         }
     }
 
-    ok = 1;
+    return ret;
 
- err:if (!ok) {
-        if (ret && !param)
-            ECPARAMETERS_free(ret);
-        ret = NULL;
-    }
-    if (tmp)
-        BN_free(tmp);
-    if (buffer)
-        OPENSSL_free(buffer);
-    return (ret);
+ err:
+    if (!param)
+        ECPARAMETERS_free(ret);
+    BN_free(tmp);
+    OPENSSL_free(buffer);
+    return NULL;
 }
 
 ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
@@ -654,7 +642,7 @@ ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
             return NULL;
         }
     } else {
-        if (ret->type == 0 && ret->value.named_curve)
+        if (ret->type == 0)
             ASN1_OBJECT_free(ret->value.named_curve);
         else if (ret->type == 1 && ret->value.parameters)
             ECPARAMETERS_free(ret->value.parameters);
@@ -849,9 +837,8 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
 
     /* extract seed (optional) */
     if (params->curve->seed != NULL) {
-        if (ret->seed != NULL)
-            OPENSSL_free(ret->seed);
-        if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) {
+        OPENSSL_free(ret->seed);
+        if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) {
             ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
             goto err;
         }
@@ -895,10 +882,8 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
 
     /* extract the cofactor (optional) */
     if (params->cofactor == NULL) {
-        if (b) {
-            BN_free(b);
-            b = NULL;
-        }
+        BN_free(b);
+        b = NULL;
     } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
         ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
         goto err;
@@ -911,20 +896,16 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
 
     ok = 1;
 
- err:if (!ok) {
-        if (ret)
-            EC_GROUP_clear_free(ret);
+ err:
+    if (!ok) {
+        EC_GROUP_clear_free(ret);
         ret = NULL;
     }
 
-    if (p)
-        BN_free(p);
-    if (a)
-        BN_free(a);
-    if (b)
-        BN_free(b);
-    if (point)
-        EC_POINT_free(point);
+    BN_free(p);
+    BN_free(a);
+    BN_free(b);
+    EC_POINT_free(point);
     return (ret);
 }
 
@@ -983,10 +964,10 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
         return NULL;
     }
 
-    if (a && *a)
+    if (a) {
         EC_GROUP_clear_free(*a);
-    if (a)
         *a = group;
+    }
 
     ECPKPARAMETERS_free(params);
     return (group);
@@ -1013,7 +994,6 @@ int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
 
 EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
 {
-    int ok = 0;
     EC_KEY *ret = NULL;
     EC_PRIVATEKEY *priv_key = NULL;
 
@@ -1031,8 +1011,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
         ret = *a;
 
     if (priv_key->parameters) {
-        if (ret->group)
-            EC_GROUP_clear_free(ret->group);
+        EC_GROUP_clear_free(ret->group);
         ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
     }
 
@@ -1044,8 +1023,8 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
     ret->version = priv_key->version;
 
     if (priv_key->privateKey) {
-        ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
-                                  M_ASN1_STRING_length(priv_key->privateKey),
+        ret->priv_key = BN_bin2bn(ASN1_STRING_data(priv_key->privateKey),
+                                  ASN1_STRING_length(priv_key->privateKey),
                                   ret->priv_key);
         if (ret->priv_key == NULL) {
             ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB);
@@ -1056,8 +1035,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
         goto err;
     }
 
-    if (ret->pub_key)
-        EC_POINT_clear_free(ret->pub_key);
+    EC_POINT_clear_free(ret->pub_key);
     ret->pub_key = EC_POINT_new(ret->group);
     if (ret->pub_key == NULL) {
         ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
@@ -1068,8 +1046,8 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
         const unsigned char *pub_oct;
         int pub_oct_len;
 
-        pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
-        pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
+        pub_oct = ASN1_STRING_data(priv_key->publicKey);
+        pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
         /*
          * The first byte - point conversion form - must be present.
          */
@@ -1096,25 +1074,21 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
 
     if (a)
         *a = ret;
-    ok = 1;
- err:
-    if (!ok) {
-        if (ret && (a == NULL || *a != ret))
-            EC_KEY_free(ret);
-        ret = NULL;
-    }
-
-    if (priv_key)
-        EC_PRIVATEKEY_free(priv_key);
-
+    EC_PRIVATEKEY_free(priv_key);
     return (ret);
+
+ err:
+    if (a == NULL || *a != ret)
+        EC_KEY_free(ret);
+    EC_PRIVATEKEY_free(priv_key);
+    return NULL;
 }
 
 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;
+    size_t buf_len = 0, tmp_len, bn_len;
     EC_PRIVATEKEY *priv_key = NULL;
 
     if (a == NULL || a->group == NULL || a->priv_key == NULL ||
@@ -1130,19 +1104,33 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
 
     priv_key->version = a->version;
 
-    buf_len = (size_t)BN_num_bytes(a->priv_key);
+    bn_len = (size_t)BN_num_bytes(a->priv_key);
+
+    /* Octetstring may need leading zeros if BN is to short */
+
+    buf_len = (EC_GROUP_get_degree(a->group) + 7) / 8;
+
+    if (bn_len > buf_len) {
+        ECerr(EC_F_I2D_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL);
+        goto err;
+    }
+
     buffer = OPENSSL_malloc(buf_len);
     if (buffer == NULL) {
         ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
-    if (!BN_bn2bin(a->priv_key, buffer)) {
+    if (!BN_bn2bin(a->priv_key, buffer + buf_len - bn_len)) {
         ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
         goto err;
     }
 
-    if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
+    if (buf_len - bn_len > 0) {
+        memset(buffer, 0, buf_len - bn_len);
+    }
+
+    if (!ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
         ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
         goto err;
     }
@@ -1157,7 +1145,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
     }
 
     if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) {
-        priv_key->publicKey = M_ASN1_BIT_STRING_new();
+        priv_key->publicKey = ASN1_BIT_STRING_new();
         if (priv_key->publicKey == NULL) {
             ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
             goto err;
@@ -1184,7 +1172,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
 
         priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
         priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-        if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
+        if (!ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
             ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
             goto err;
         }
@@ -1196,10 +1184,8 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
     }
     ok = 1;
  err:
-    if (buffer)
-        OPENSSL_free(buffer);
-    if (priv_key)
-        EC_PRIVATEKEY_free(priv_key);
+    OPENSSL_free(buffer);
+    EC_PRIVATEKEY_free(priv_key);
     return (ok ? ret : 0);
 }
 
@@ -1226,16 +1212,19 @@ EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
             ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
             return NULL;
         }
-        if (a)
-            *a = ret;
     } else
         ret = *a;
 
     if (!d2i_ECPKParameters(&ret->group, in, len)) {
         ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
+        if (a == NULL || *a != ret)
+             EC_KEY_free(ret);
         return NULL;
     }
 
+    if (a)
+        *a = ret;
+
     return ret;
 }