]>
Commit | Line | Data |
---|---|---|
6a2b8ff3 | 1 | /* |
da1c088f | 2 | * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. |
6a2b8ff3 RL |
3 | * |
4 | * Licensed under the Apache License 2.0 (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 <openssl/core.h> | |
11 | #include <openssl/core_dispatch.h> | |
12 | #include <openssl/core_names.h> | |
13 | #include <openssl/core_object.h> | |
14 | #include <openssl/asn1.h> | |
15 | #include <openssl/err.h> | |
16 | #include <openssl/objects.h> | |
17 | #include <openssl/pkcs12.h> | |
18 | #include <openssl/x509.h> | |
19 | #include <openssl/proverr.h> | |
20 | #include "internal/asn1.h" | |
21 | #include "internal/sizes.h" | |
22 | #include "prov/bio.h" | |
23 | #include "prov/implementations.h" | |
24 | #include "endecoder_local.h" | |
25 | ||
26 | static OSSL_FUNC_decoder_newctx_fn epki2pki_newctx; | |
27 | static OSSL_FUNC_decoder_freectx_fn epki2pki_freectx; | |
28 | static OSSL_FUNC_decoder_decode_fn epki2pki_decode; | |
39ed7636 | 29 | static OSSL_FUNC_decoder_settable_ctx_params_fn epki2pki_settable_ctx_params; |
30 | static OSSL_FUNC_decoder_set_ctx_params_fn epki2pki_set_ctx_params; | |
6a2b8ff3 RL |
31 | |
32 | /* | |
33 | * Context used for EncryptedPrivateKeyInfo to PrivateKeyInfo decoding. | |
34 | */ | |
35 | struct epki2pki_ctx_st { | |
36 | PROV_CTX *provctx; | |
39ed7636 | 37 | char propq[OSSL_MAX_PROPQUERY_SIZE]; |
6a2b8ff3 RL |
38 | }; |
39 | ||
40 | static void *epki2pki_newctx(void *provctx) | |
41 | { | |
42 | struct epki2pki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
43 | ||
44 | if (ctx != NULL) | |
45 | ctx->provctx = provctx; | |
46 | return ctx; | |
47 | } | |
48 | ||
49 | static void epki2pki_freectx(void *vctx) | |
50 | { | |
51 | struct epki2pki_ctx_st *ctx = vctx; | |
52 | ||
53 | OPENSSL_free(ctx); | |
54 | } | |
55 | ||
39ed7636 | 56 | static const OSSL_PARAM *epki2pki_settable_ctx_params(ossl_unused void *provctx) |
57 | { | |
58 | static const OSSL_PARAM settables[] = { | |
59 | OSSL_PARAM_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, NULL, 0), | |
60 | OSSL_PARAM_END | |
61 | }; | |
62 | return settables; | |
63 | } | |
64 | ||
65 | static int epki2pki_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
66 | { | |
67 | struct epki2pki_ctx_st *ctx = vctx; | |
68 | const OSSL_PARAM *p; | |
69 | char *str = ctx->propq; | |
70 | ||
71 | p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_PROPERTIES); | |
72 | if (p != NULL && !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->propq))) | |
73 | return 0; | |
74 | ||
75 | return 1; | |
76 | } | |
77 | ||
6a2b8ff3 RL |
78 | /* |
79 | * The selection parameter in epki2pki_decode() is not used by this function | |
80 | * because it's not relevant just to decode EncryptedPrivateKeyInfo to | |
81 | * PrivateKeyInfo. | |
82 | */ | |
83 | static int epki2pki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, | |
84 | OSSL_CALLBACK *data_cb, void *data_cbarg, | |
85 | OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) | |
86 | { | |
87 | struct epki2pki_ctx_st *ctx = vctx; | |
88 | BUF_MEM *mem = NULL; | |
89 | unsigned char *der = NULL; | |
90 | const unsigned char *pder = NULL; | |
91 | long der_len = 0; | |
92 | X509_SIG *p8 = NULL; | |
93 | PKCS8_PRIV_KEY_INFO *p8inf = NULL; | |
94 | const X509_ALGOR *alg = NULL; | |
95 | BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); | |
352a0bca | 96 | int ok = 0; |
6a2b8ff3 | 97 | |
352a0bca | 98 | if (in == NULL) |
99 | return 0; | |
100 | ||
101 | ok = (asn1_d2i_read_bio(in, &mem) >= 0); | |
6a2b8ff3 RL |
102 | BIO_free(in); |
103 | ||
104 | /* We return "empty handed". This is not an error. */ | |
105 | if (!ok) | |
106 | return 1; | |
107 | ||
108 | pder = der = (unsigned char *)mem->data; | |
109 | der_len = (long)mem->length; | |
110 | OPENSSL_free(mem); | |
111 | ||
112 | ok = 1; /* Assume good */ | |
113 | ERR_set_mark(); | |
114 | if ((p8 = d2i_X509_SIG(NULL, &pder, der_len)) != NULL) { | |
115 | char pbuf[1024]; | |
116 | size_t plen = 0; | |
117 | ||
118 | ERR_clear_last_mark(); | |
119 | ||
120 | if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) { | |
121 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE); | |
42fe3e84 | 122 | ok = 0; |
6a2b8ff3 RL |
123 | } else { |
124 | const ASN1_OCTET_STRING *oct; | |
125 | unsigned char *new_der = NULL; | |
126 | int new_der_len = 0; | |
127 | ||
128 | X509_SIG_get0(p8, &alg, &oct); | |
129 | if (!PKCS12_pbe_crypt_ex(alg, pbuf, plen, | |
130 | oct->data, oct->length, | |
131 | &new_der, &new_der_len, 0, | |
39ed7636 | 132 | PROV_LIBCTX_OF(ctx->provctx), |
133 | ctx->propq)) { | |
6a2b8ff3 RL |
134 | ok = 0; |
135 | } else { | |
136 | OPENSSL_free(der); | |
137 | der = new_der; | |
138 | der_len = new_der_len; | |
139 | } | |
140 | alg = NULL; | |
141 | } | |
142 | X509_SIG_free(p8); | |
143 | } else { | |
144 | ERR_pop_to_mark(); | |
145 | } | |
146 | ||
147 | ERR_set_mark(); | |
148 | pder = der; | |
149 | p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pder, der_len); | |
150 | ERR_pop_to_mark(); | |
151 | ||
152 | if (p8inf != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)) { | |
153 | /* | |
154 | * We have something and recognised it as PrivateKeyInfo, so let's | |
155 | * pass all the applicable data to the callback. | |
156 | */ | |
157 | char keytype[OSSL_MAX_NAME_SIZE]; | |
158 | OSSL_PARAM params[5], *p = params; | |
159 | int objtype = OSSL_OBJECT_PKEY; | |
160 | ||
161 | OBJ_obj2txt(keytype, sizeof(keytype), alg->algorithm, 0); | |
162 | ||
163 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, | |
164 | keytype, 0); | |
165 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, | |
166 | "PrivateKeyInfo", 0); | |
167 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, | |
168 | der, der_len); | |
169 | *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); | |
170 | *p = OSSL_PARAM_construct_end(); | |
171 | ||
172 | ok = data_cb(params, data_cbarg); | |
173 | } | |
174 | PKCS8_PRIV_KEY_INFO_free(p8inf); | |
175 | OPENSSL_free(der); | |
176 | return ok; | |
177 | } | |
178 | ||
179 | const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[] = { | |
180 | { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))epki2pki_newctx }, | |
181 | { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))epki2pki_freectx }, | |
182 | { OSSL_FUNC_DECODER_DECODE, (void (*)(void))epki2pki_decode }, | |
39ed7636 | 183 | { OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, |
184 | (void (*)(void))epki2pki_settable_ctx_params }, | |
185 | { OSSL_FUNC_DECODER_SET_CTX_PARAMS, | |
186 | (void (*)(void))epki2pki_set_ctx_params }, | |
1e6bd31e | 187 | OSSL_DISPATCH_END |
6a2b8ff3 | 188 | }; |