]>
Commit | Line | Data |
---|---|---|
2039c421 | 1 | /* |
444b25b1 | 2 | * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
365a2d99 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
2039c421 RS |
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 | |
d02b48c6 RE |
8 | */ |
9 | ||
e4468e6d P |
10 | /* We need to use some engine deprecated APIs */ |
11 | #define OPENSSL_SUPPRESS_DEPRECATED | |
12 | ||
d02b48c6 | 13 | #include <stdio.h> |
b39fc560 | 14 | #include "internal/cryptlib.h" |
ec577822 BM |
15 | #include <openssl/bn.h> |
16 | #include <openssl/evp.h> | |
17 | #include <openssl/objects.h> | |
576892d7 | 18 | #include <openssl/decoder.h> |
3c27208f | 19 | #include <openssl/engine.h> |
94e6ae7a | 20 | #include <openssl/x509.h> |
f66c3032 | 21 | #include <openssl/asn1.h> |
25f2138b DMSP |
22 | #include "crypto/asn1.h" |
23 | #include "crypto/evp.h" | |
576892d7 | 24 | #include "internal/asn1.h" |
d02b48c6 | 25 | |
444b25b1 SL |
26 | static EVP_PKEY * |
27 | d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, | |
28 | long length, OSSL_LIB_CTX *libctx, const char *propq) | |
576892d7 SL |
29 | { |
30 | OSSL_DECODER_CTX *dctx = NULL; | |
31 | size_t len = length; | |
c1fd7102 | 32 | EVP_PKEY *pkey = NULL, *bak_a = NULL; |
576892d7 SL |
33 | EVP_PKEY **ppkey = &pkey; |
34 | const char *key_name = NULL; | |
35 | const char *input_structures[] = { "type-specific", "pkcs8", NULL }; | |
36 | int i, ret; | |
37 | ||
38 | if (keytype != EVP_PKEY_NONE) { | |
39 | key_name = evp_pkey_type2name(keytype); | |
40 | if (key_name == NULL) | |
41 | return NULL; | |
42 | } | |
576892d7 SL |
43 | |
44 | for (i = 0; i < (int)OSSL_NELEM(input_structures); ++i) { | |
444b25b1 SL |
45 | const unsigned char *p = *pp; |
46 | ||
c1fd7102 DDO |
47 | if (a != NULL && (bak_a = *a) != NULL) |
48 | ppkey = a; | |
3352dc18 SL |
49 | dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", |
50 | input_structures[i], key_name, | |
51 | EVP_PKEY_KEYPAIR, libctx, propq); | |
c1fd7102 DDO |
52 | if (a != NULL) |
53 | *a = bak_a; | |
576892d7 | 54 | if (dctx == NULL) |
6d9e045e | 55 | continue; |
576892d7 SL |
56 | |
57 | ret = OSSL_DECODER_from_data(dctx, pp, &len); | |
58 | OSSL_DECODER_CTX_free(dctx); | |
59 | if (ret) { | |
60 | if (*ppkey != NULL | |
c1fd7102 DDO |
61 | && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { |
62 | if (a != NULL) | |
63 | *a = *ppkey; | |
576892d7 | 64 | return *ppkey; |
c1fd7102 | 65 | } |
444b25b1 | 66 | *pp = p; |
576892d7 SL |
67 | goto err; |
68 | } | |
69 | } | |
70 | /* Fall through to error if all decodes failed */ | |
71 | err: | |
72 | if (ppkey != a) | |
73 | EVP_PKEY_free(*ppkey); | |
74 | return NULL; | |
75 | } | |
76 | ||
695c96ba RL |
77 | static EVP_PKEY * |
78 | d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, const unsigned char **pp, | |
79 | long length, OSSL_LIB_CTX *libctx, const char *propq) | |
0f113f3e MC |
80 | { |
81 | EVP_PKEY *ret; | |
a46c9789 | 82 | const unsigned char *p = *pp; |
d02b48c6 | 83 | |
c1fd7102 | 84 | if (a == NULL || *a == NULL) { |
0f113f3e | 85 | if ((ret = EVP_PKEY_new()) == NULL) { |
9311d0c4 | 86 | ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); |
26a7d938 | 87 | return NULL; |
0f113f3e MC |
88 | } |
89 | } else { | |
90 | ret = *a; | |
41eacc84 | 91 | #ifndef OPENSSL_NO_ENGINE |
7c96dbcd RS |
92 | ENGINE_finish(ret->engine); |
93 | ret->engine = NULL; | |
41eacc84 | 94 | #endif |
0f113f3e | 95 | } |
01b8b3c7 | 96 | |
576892d7 | 97 | if (!EVP_PKEY_set_type(ret, keytype)) { |
9311d0c4 | 98 | ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); |
0f113f3e MC |
99 | goto err; |
100 | } | |
01b8b3c7 | 101 | |
d00bd4e4 | 102 | ERR_set_mark(); |
0f113f3e | 103 | if (!ret->ameth->old_priv_decode || |
a46c9789 | 104 | !ret->ameth->old_priv_decode(ret, &p, length)) { |
472a88b7 | 105 | if (ret->ameth->priv_decode != NULL |
d8652be0 | 106 | || ret->ameth->priv_decode_ex != NULL) { |
3340e8bb | 107 | EVP_PKEY *tmp; |
0f113f3e | 108 | PKCS8_PRIV_KEY_INFO *p8 = NULL; |
a46c9789 | 109 | p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); |
d00bd4e4 DB |
110 | if (p8 == NULL) { |
111 | ERR_clear_last_mark(); | |
0f113f3e | 112 | goto err; |
d00bd4e4 | 113 | } |
4f0831b8 | 114 | tmp = evp_pkcs82pkey_legacy(p8, libctx, propq); |
0f113f3e | 115 | PKCS8_PRIV_KEY_INFO_free(p8); |
d00bd4e4 DB |
116 | if (tmp == NULL) { |
117 | ERR_clear_last_mark(); | |
605236f6 | 118 | goto err; |
d00bd4e4 | 119 | } |
3340e8bb DSH |
120 | EVP_PKEY_free(ret); |
121 | ret = tmp; | |
d00bd4e4 | 122 | ERR_pop_to_mark(); |
576892d7 | 123 | if (EVP_PKEY_type(keytype) != EVP_PKEY_base_id(ret)) |
b2952366 | 124 | goto err; |
0f113f3e | 125 | } else { |
d00bd4e4 | 126 | ERR_clear_last_mark(); |
9311d0c4 | 127 | ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); |
0f113f3e MC |
128 | goto err; |
129 | } | |
d00bd4e4 DB |
130 | } else { |
131 | ERR_clear_last_mark(); | |
0f113f3e | 132 | } |
a46c9789 | 133 | *pp = p; |
0f113f3e | 134 | if (a != NULL) |
c1fd7102 | 135 | *a = ret; |
26a7d938 | 136 | return ret; |
0f113f3e | 137 | err: |
c5ba2d99 | 138 | if (a == NULL || *a != ret) |
0f113f3e | 139 | EVP_PKEY_free(ret); |
26a7d938 | 140 | return NULL; |
0f113f3e | 141 | } |
d02b48c6 | 142 | |
444b25b1 SL |
143 | EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, |
144 | long length, OSSL_LIB_CTX *libctx, | |
145 | const char *propq) | |
146 | { | |
147 | EVP_PKEY *ret; | |
148 | ||
149 | ret = d2i_PrivateKey_decoder(keytype, a, pp, length, libctx, propq); | |
150 | /* try the legacy path if the decoder failed */ | |
151 | if (ret == NULL) | |
695c96ba | 152 | ret = d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq); |
444b25b1 SL |
153 | return ret; |
154 | } | |
155 | ||
472a88b7 MC |
156 | EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, |
157 | long length) | |
158 | { | |
159 | return d2i_PrivateKey_ex(type, a, pp, length, NULL, NULL); | |
160 | } | |
161 | ||
444b25b1 SL |
162 | static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a, |
163 | const unsigned char **pp, | |
164 | long length, | |
165 | OSSL_LIB_CTX *libctx, | |
166 | const char *propq) | |
167 | { | |
168 | STACK_OF(ASN1_TYPE) *inkey; | |
169 | const unsigned char *p; | |
170 | int keytype; | |
171 | ||
172 | p = *pp; | |
173 | /* | |
174 | * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by | |
175 | * analyzing it we can determine the passed structure: this assumes the | |
176 | * input is surrounded by an ASN1 SEQUENCE. | |
177 | */ | |
178 | inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); | |
179 | p = *pp; | |
180 | /* | |
181 | * Since we only need to discern "traditional format" RSA and DSA keys we | |
182 | * can just count the elements. | |
183 | */ | |
184 | if (sk_ASN1_TYPE_num(inkey) == 6) { | |
185 | keytype = EVP_PKEY_DSA; | |
186 | } else if (sk_ASN1_TYPE_num(inkey) == 4) { | |
187 | keytype = EVP_PKEY_EC; | |
188 | } else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not | |
189 | * traditional format */ | |
190 | PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); | |
191 | EVP_PKEY *ret; | |
192 | ||
193 | sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); | |
194 | if (p8 == NULL) { | |
195 | ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); | |
196 | return NULL; | |
197 | } | |
4f0831b8 | 198 | ret = evp_pkcs82pkey_legacy(p8, libctx, propq); |
444b25b1 SL |
199 | PKCS8_PRIV_KEY_INFO_free(p8); |
200 | if (ret == NULL) | |
201 | return NULL; | |
202 | *pp = p; | |
c1fd7102 | 203 | if (a != NULL) { |
444b25b1 SL |
204 | *a = ret; |
205 | } | |
206 | return ret; | |
207 | } else { | |
208 | keytype = EVP_PKEY_RSA; | |
209 | } | |
210 | sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); | |
695c96ba | 211 | return d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq); |
444b25b1 SL |
212 | } |
213 | ||
0f113f3e | 214 | /* |
576892d7 SL |
215 | * This works like d2i_PrivateKey() except it passes the keytype as |
216 | * EVP_PKEY_NONE, which then figures out the type during decoding. | |
0f113f3e | 217 | */ |
472a88b7 | 218 | EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp, |
b4250010 | 219 | long length, OSSL_LIB_CTX *libctx, |
472a88b7 | 220 | const char *propq) |
20432eae | 221 | { |
444b25b1 SL |
222 | EVP_PKEY *ret; |
223 | ||
224 | ret = d2i_PrivateKey_decoder(EVP_PKEY_NONE, a, pp, length, libctx, propq); | |
225 | /* try the legacy path if the decoder failed */ | |
226 | if (ret == NULL) | |
227 | ret = d2i_AutoPrivateKey_legacy(a, pp, length, libctx, propq); | |
228 | return ret; | |
472a88b7 MC |
229 | } |
230 | ||
231 | EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, | |
232 | long length) | |
233 | { | |
234 | return d2i_AutoPrivateKey_ex(a, pp, length, NULL, NULL); | |
20432eae | 235 | } |