xref: /freebsd/crypto/openssl/crypto/asn1/d2i_pr.c (revision d485c77f203fb0f4cdc08dea5ff81631b51d8809)
1 /*
2  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/bn.h>
13 #include <openssl/evp.h>
14 #include <openssl/objects.h>
15 #include <openssl/engine.h>
16 #include <openssl/x509.h>
17 #include <openssl/asn1.h>
18 #include "crypto/asn1.h"
19 #include "crypto/evp.h"
20 
21 EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
22                          long length)
23 {
24     EVP_PKEY *ret;
25     const unsigned char *p = *pp;
26 
27     if ((a == NULL) || (*a == NULL)) {
28         if ((ret = EVP_PKEY_new()) == NULL) {
29             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
30             return NULL;
31         }
32     } else {
33         ret = *a;
34 #ifndef OPENSSL_NO_ENGINE
35         ENGINE_finish(ret->engine);
36         ret->engine = NULL;
37 #endif
38     }
39 
40     if (!EVP_PKEY_set_type(ret, type)) {
41         ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
42         goto err;
43     }
44 
45     if (!ret->ameth->old_priv_decode ||
46         !ret->ameth->old_priv_decode(ret, &p, length)) {
47         if (ret->ameth->priv_decode) {
48             EVP_PKEY *tmp;
49             PKCS8_PRIV_KEY_INFO *p8 = NULL;
50             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
51             if (!p8)
52                 goto err;
53             tmp = EVP_PKCS82PKEY(p8);
54             PKCS8_PRIV_KEY_INFO_free(p8);
55             if (tmp == NULL)
56                 goto err;
57             EVP_PKEY_free(ret);
58             ret = tmp;
59             if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret))
60                 goto err;
61         } else {
62             ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
63             goto err;
64         }
65     }
66     *pp = p;
67     if (a != NULL)
68         (*a) = ret;
69     return ret;
70  err:
71     if (a == NULL || *a != ret)
72         EVP_PKEY_free(ret);
73     return NULL;
74 }
75 
76 /*
77  * This works like d2i_PrivateKey() except it automatically works out the
78  * type
79  */
80 
81 EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
82                              long length)
83 {
84     STACK_OF(ASN1_TYPE) *inkey;
85     const unsigned char *p;
86     int keytype;
87     p = *pp;
88     /*
89      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
90      * analyzing it we can determine the passed structure: this assumes the
91      * input is surrounded by an ASN1 SEQUENCE.
92      */
93     inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
94     p = *pp;
95     /*
96      * Since we only need to discern "traditional format" RSA and DSA keys we
97      * can just count the elements.
98      */
99     if (sk_ASN1_TYPE_num(inkey) == 6)
100         keytype = EVP_PKEY_DSA;
101     else if (sk_ASN1_TYPE_num(inkey) == 4)
102         keytype = EVP_PKEY_EC;
103     else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
104                                               * traditional format */
105         PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
106         EVP_PKEY *ret;
107 
108         sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
109         if (!p8) {
110             ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
111                     ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
112             return NULL;
113         }
114         ret = EVP_PKCS82PKEY(p8);
115         PKCS8_PRIV_KEY_INFO_free(p8);
116         if (ret == NULL)
117             return NULL;
118         *pp = p;
119         if (a) {
120             *a = ret;
121         }
122         return ret;
123     } else
124         keytype = EVP_PKEY_RSA;
125     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
126     return d2i_PrivateKey(keytype, a, pp, length);
127 }
128