Imported Upstream version 1.1.1l
[platform/upstream/openssl1.1.git] / crypto / asn1 / d2i_pr.c
index 7b127d2..2094963 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -78,13 +78,53 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
  * type
  */
 
+static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on)
+{
+    const unsigned char *p = *pp;
+    PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
+    EVP_PKEY *ret;
+
+    if (p8 == NULL)
+        return NULL;
+
+    ret = EVP_PKCS82PKEY(p8);
+    if (ret == NULL)
+        *carry_on = 0;
+
+    PKCS8_PRIV_KEY_INFO_free(p8);
+
+    if (ret != NULL)
+        *pp = p;
+
+    return ret;
+}
+
 EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
                              long length)
 {
     STACK_OF(ASN1_TYPE) *inkey;
     const unsigned char *p;
     int keytype;
+    EVP_PKEY *ret = NULL;
+    int carry_on = 1;
+
+    ERR_set_mark();
+    ret = key_as_pkcs8(pp, length, &carry_on);
+    if (ret != NULL) {
+        ERR_clear_last_mark();
+        if (a != NULL)
+            *a = ret;
+        return ret;
+    }
+
+    if (carry_on == 0) {
+        ERR_clear_last_mark();
+        ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
+                ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+        return NULL;
+    }
     p = *pp;
+
     /*
      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
      * analyzing it we can determine the passed structure: this assumes the
@@ -100,28 +140,15 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
         keytype = EVP_PKEY_DSA;
     else if (sk_ASN1_TYPE_num(inkey) == 4)
         keytype = EVP_PKEY_EC;
-    else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
-                                              * traditional format */
-        PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
-        EVP_PKEY *ret;
-
-        sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
-        if (!p8) {
-            ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
-                    ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-            return NULL;
-        }
-        ret = EVP_PKCS82PKEY(p8);
-        PKCS8_PRIV_KEY_INFO_free(p8);
-        if (ret == NULL)
-            return NULL;
-        *pp = p;
-        if (a) {
-            *a = ret;
-        }
-        return ret;
-    } else
+    else
         keytype = EVP_PKEY_RSA;
     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
-    return d2i_PrivateKey(keytype, a, pp, length);
+
+    ret = d2i_PrivateKey(keytype, a, pp, length);
+    if (ret != NULL)
+        ERR_pop_to_mark();
+    else
+        ERR_clear_last_mark();
+
+    return ret;
 }