xref: /freebsd/crypto/openssl/crypto/asn1/d2i_pr.c (revision 9a3ae0cdef9ac9a4b8c5cc66305d9a516ce8d4a0)
1e71b7053SJung-uk Kim /*
2*9a3ae0cdSJung-uk Kim  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
374664626SKris Kennaway  *
4e71b7053SJung-uk Kim  * Licensed under the OpenSSL license (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
874664626SKris Kennaway  */
974664626SKris Kennaway 
1074664626SKris Kennaway #include <stdio.h>
11e71b7053SJung-uk Kim #include "internal/cryptlib.h"
1274664626SKris Kennaway #include <openssl/bn.h>
1374664626SKris Kennaway #include <openssl/evp.h>
1474664626SKris Kennaway #include <openssl/objects.h>
151f13597dSJung-uk Kim #include <openssl/engine.h>
161f13597dSJung-uk Kim #include <openssl/x509.h>
1774664626SKris Kennaway #include <openssl/asn1.h>
1817f01e99SJung-uk Kim #include "crypto/asn1.h"
1917f01e99SJung-uk Kim #include "crypto/evp.h"
2074664626SKris Kennaway 
213b4e3dcbSSimon L. B. Nielsen EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
2274664626SKris Kennaway                          long length)
2374664626SKris Kennaway {
2474664626SKris Kennaway     EVP_PKEY *ret;
2580815a77SJung-uk Kim     const unsigned char *p = *pp;
2674664626SKris Kennaway 
276f9291ceSJung-uk Kim     if ((a == NULL) || (*a == NULL)) {
286f9291ceSJung-uk Kim         if ((ret = EVP_PKEY_new()) == NULL) {
2974664626SKris Kennaway             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
30e71b7053SJung-uk Kim             return NULL;
3174664626SKris Kennaway         }
326f9291ceSJung-uk Kim     } else {
331f13597dSJung-uk Kim         ret = *a;
341f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE
351f13597dSJung-uk Kim         ENGINE_finish(ret->engine);
361f13597dSJung-uk Kim         ret->engine = NULL;
371f13597dSJung-uk Kim #endif
381f13597dSJung-uk Kim     }
3974664626SKris Kennaway 
406f9291ceSJung-uk Kim     if (!EVP_PKEY_set_type(ret, type)) {
4174664626SKris Kennaway         ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
4274664626SKris Kennaway         goto err;
431f13597dSJung-uk Kim     }
441f13597dSJung-uk Kim 
451f13597dSJung-uk Kim     if (!ret->ameth->old_priv_decode ||
4680815a77SJung-uk Kim         !ret->ameth->old_priv_decode(ret, &p, length)) {
476f9291ceSJung-uk Kim         if (ret->ameth->priv_decode) {
48aeb5019cSJung-uk Kim             EVP_PKEY *tmp;
491f13597dSJung-uk Kim             PKCS8_PRIV_KEY_INFO *p8 = NULL;
5080815a77SJung-uk Kim             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
516f9291ceSJung-uk Kim             if (!p8)
526f9291ceSJung-uk Kim                 goto err;
53aeb5019cSJung-uk Kim             tmp = EVP_PKCS82PKEY(p8);
541f13597dSJung-uk Kim             PKCS8_PRIV_KEY_INFO_free(p8);
55aeb5019cSJung-uk Kim             if (tmp == NULL)
5680815a77SJung-uk Kim                 goto err;
57aeb5019cSJung-uk Kim             EVP_PKEY_free(ret);
58aeb5019cSJung-uk Kim             ret = tmp;
5958f35182SJung-uk Kim             if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret))
6058f35182SJung-uk Kim                 goto err;
616f9291ceSJung-uk Kim         } else {
621f13597dSJung-uk Kim             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
631f13597dSJung-uk Kim             goto err;
641f13597dSJung-uk Kim         }
6574664626SKris Kennaway     }
6680815a77SJung-uk Kim     *pp = p;
676f9291ceSJung-uk Kim     if (a != NULL)
686f9291ceSJung-uk Kim         (*a) = ret;
69e71b7053SJung-uk Kim     return ret;
7074664626SKris Kennaway  err:
71e71b7053SJung-uk Kim     if (a == NULL || *a != ret)
726f9291ceSJung-uk Kim         EVP_PKEY_free(ret);
73e71b7053SJung-uk Kim     return NULL;
7474664626SKris Kennaway }
7574664626SKris Kennaway 
766f9291ceSJung-uk Kim /*
776f9291ceSJung-uk Kim  * This works like d2i_PrivateKey() except it automatically works out the
786f9291ceSJung-uk Kim  * type
796f9291ceSJung-uk Kim  */
80f579bf8eSKris Kennaway 
81*9a3ae0cdSJung-uk Kim static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on)
82*9a3ae0cdSJung-uk Kim {
83*9a3ae0cdSJung-uk Kim     const unsigned char *p = *pp;
84*9a3ae0cdSJung-uk Kim     PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
85*9a3ae0cdSJung-uk Kim     EVP_PKEY *ret;
86*9a3ae0cdSJung-uk Kim 
87*9a3ae0cdSJung-uk Kim     if (p8 == NULL)
88*9a3ae0cdSJung-uk Kim         return NULL;
89*9a3ae0cdSJung-uk Kim 
90*9a3ae0cdSJung-uk Kim     ret = EVP_PKCS82PKEY(p8);
91*9a3ae0cdSJung-uk Kim     if (ret == NULL)
92*9a3ae0cdSJung-uk Kim         *carry_on = 0;
93*9a3ae0cdSJung-uk Kim 
94*9a3ae0cdSJung-uk Kim     PKCS8_PRIV_KEY_INFO_free(p8);
95*9a3ae0cdSJung-uk Kim 
96*9a3ae0cdSJung-uk Kim     if (ret != NULL)
97*9a3ae0cdSJung-uk Kim         *pp = p;
98*9a3ae0cdSJung-uk Kim 
99*9a3ae0cdSJung-uk Kim     return ret;
100*9a3ae0cdSJung-uk Kim }
101*9a3ae0cdSJung-uk Kim 
1023b4e3dcbSSimon L. B. Nielsen EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
103f579bf8eSKris Kennaway                              long length)
104f579bf8eSKris Kennaway {
105f579bf8eSKris Kennaway     STACK_OF(ASN1_TYPE) *inkey;
1063b4e3dcbSSimon L. B. Nielsen     const unsigned char *p;
107f579bf8eSKris Kennaway     int keytype;
108*9a3ae0cdSJung-uk Kim     EVP_PKEY *ret = NULL;
109*9a3ae0cdSJung-uk Kim     int carry_on = 1;
110*9a3ae0cdSJung-uk Kim 
111*9a3ae0cdSJung-uk Kim     ERR_set_mark();
112*9a3ae0cdSJung-uk Kim     ret = key_as_pkcs8(pp, length, &carry_on);
113*9a3ae0cdSJung-uk Kim     if (ret != NULL) {
114*9a3ae0cdSJung-uk Kim         ERR_clear_last_mark();
115*9a3ae0cdSJung-uk Kim         if (a != NULL)
116*9a3ae0cdSJung-uk Kim             *a = ret;
117*9a3ae0cdSJung-uk Kim         return ret;
118*9a3ae0cdSJung-uk Kim     }
119*9a3ae0cdSJung-uk Kim 
120*9a3ae0cdSJung-uk Kim     if (carry_on == 0) {
121*9a3ae0cdSJung-uk Kim         ERR_clear_last_mark();
122*9a3ae0cdSJung-uk Kim         ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
123*9a3ae0cdSJung-uk Kim                 ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
124*9a3ae0cdSJung-uk Kim         return NULL;
125*9a3ae0cdSJung-uk Kim     }
126f579bf8eSKris Kennaway     p = *pp;
127*9a3ae0cdSJung-uk Kim 
1286f9291ceSJung-uk Kim     /*
1296f9291ceSJung-uk Kim      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
1306f9291ceSJung-uk Kim      * analyzing it we can determine the passed structure: this assumes the
1316f9291ceSJung-uk Kim      * input is surrounded by an ASN1 SEQUENCE.
132f579bf8eSKris Kennaway      */
1331f13597dSJung-uk Kim     inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
13480815a77SJung-uk Kim     p = *pp;
1356f9291ceSJung-uk Kim     /*
1366f9291ceSJung-uk Kim      * Since we only need to discern "traditional format" RSA and DSA keys we
1376f9291ceSJung-uk Kim      * can just count the elements.
138f579bf8eSKris Kennaway      */
1393b4e3dcbSSimon L. B. Nielsen     if (sk_ASN1_TYPE_num(inkey) == 6)
1403b4e3dcbSSimon L. B. Nielsen         keytype = EVP_PKEY_DSA;
1413b4e3dcbSSimon L. B. Nielsen     else if (sk_ASN1_TYPE_num(inkey) == 4)
1423b4e3dcbSSimon L. B. Nielsen         keytype = EVP_PKEY_EC;
143*9a3ae0cdSJung-uk Kim     else
1446f9291ceSJung-uk Kim         keytype = EVP_PKEY_RSA;
145f579bf8eSKris Kennaway     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
146*9a3ae0cdSJung-uk Kim 
147*9a3ae0cdSJung-uk Kim     ret = d2i_PrivateKey(keytype, a, pp, length);
148*9a3ae0cdSJung-uk Kim     if (ret != NULL)
149*9a3ae0cdSJung-uk Kim         ERR_pop_to_mark();
150*9a3ae0cdSJung-uk Kim     else
151*9a3ae0cdSJung-uk Kim         ERR_clear_last_mark();
152*9a3ae0cdSJung-uk Kim 
153*9a3ae0cdSJung-uk Kim     return ret;
154f579bf8eSKris Kennaway }
155