]>
Commit | Line | Data |
---|---|---|
6a2b8ff3 | 1 | /* |
fecb3aae | 2 | * Copyright 2020-2022 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; | |
29 | ||
30 | /* | |
31 | * Context used for EncryptedPrivateKeyInfo to PrivateKeyInfo decoding. | |
32 | */ | |
33 | struct epki2pki_ctx_st { | |
34 | PROV_CTX *provctx; | |
35 | }; | |
36 | ||
37 | static void *epki2pki_newctx(void *provctx) | |
38 | { | |
39 | struct epki2pki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
40 | ||
41 | if (ctx != NULL) | |
42 | ctx->provctx = provctx; | |
43 | return ctx; | |
44 | } | |
45 | ||
46 | static void epki2pki_freectx(void *vctx) | |
47 | { | |
48 | struct epki2pki_ctx_st *ctx = vctx; | |
49 | ||
50 | OPENSSL_free(ctx); | |
51 | } | |
52 | ||
53 | /* | |
54 | * The selection parameter in epki2pki_decode() is not used by this function | |
55 | * because it's not relevant just to decode EncryptedPrivateKeyInfo to | |
56 | * PrivateKeyInfo. | |
57 | */ | |
58 | static int epki2pki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, | |
59 | OSSL_CALLBACK *data_cb, void *data_cbarg, | |
60 | OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) | |
61 | { | |
62 | struct epki2pki_ctx_st *ctx = vctx; | |
63 | BUF_MEM *mem = NULL; | |
64 | unsigned char *der = NULL; | |
65 | const unsigned char *pder = NULL; | |
66 | long der_len = 0; | |
67 | X509_SIG *p8 = NULL; | |
68 | PKCS8_PRIV_KEY_INFO *p8inf = NULL; | |
69 | const X509_ALGOR *alg = NULL; | |
70 | BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); | |
352a0bca | 71 | int ok = 0; |
6a2b8ff3 | 72 | |
352a0bca | 73 | if (in == NULL) |
74 | return 0; | |
75 | ||
76 | ok = (asn1_d2i_read_bio(in, &mem) >= 0); | |
6a2b8ff3 RL |
77 | BIO_free(in); |
78 | ||
79 | /* We return "empty handed". This is not an error. */ | |
80 | if (!ok) | |
81 | return 1; | |
82 | ||
83 | pder = der = (unsigned char *)mem->data; | |
84 | der_len = (long)mem->length; | |
85 | OPENSSL_free(mem); | |
86 | ||
87 | ok = 1; /* Assume good */ | |
88 | ERR_set_mark(); | |
89 | if ((p8 = d2i_X509_SIG(NULL, &pder, der_len)) != NULL) { | |
90 | char pbuf[1024]; | |
91 | size_t plen = 0; | |
92 | ||
93 | ERR_clear_last_mark(); | |
94 | ||
95 | if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) { | |
96 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE); | |
42fe3e84 | 97 | ok = 0; |
6a2b8ff3 RL |
98 | } else { |
99 | const ASN1_OCTET_STRING *oct; | |
100 | unsigned char *new_der = NULL; | |
101 | int new_der_len = 0; | |
102 | ||
103 | X509_SIG_get0(p8, &alg, &oct); | |
104 | if (!PKCS12_pbe_crypt_ex(alg, pbuf, plen, | |
105 | oct->data, oct->length, | |
106 | &new_der, &new_der_len, 0, | |
107 | PROV_LIBCTX_OF(ctx->provctx), NULL)) { | |
108 | ok = 0; | |
109 | } else { | |
110 | OPENSSL_free(der); | |
111 | der = new_der; | |
112 | der_len = new_der_len; | |
113 | } | |
114 | alg = NULL; | |
115 | } | |
116 | X509_SIG_free(p8); | |
117 | } else { | |
118 | ERR_pop_to_mark(); | |
119 | } | |
120 | ||
121 | ERR_set_mark(); | |
122 | pder = der; | |
123 | p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pder, der_len); | |
124 | ERR_pop_to_mark(); | |
125 | ||
126 | if (p8inf != NULL && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)) { | |
127 | /* | |
128 | * We have something and recognised it as PrivateKeyInfo, so let's | |
129 | * pass all the applicable data to the callback. | |
130 | */ | |
131 | char keytype[OSSL_MAX_NAME_SIZE]; | |
132 | OSSL_PARAM params[5], *p = params; | |
133 | int objtype = OSSL_OBJECT_PKEY; | |
134 | ||
135 | OBJ_obj2txt(keytype, sizeof(keytype), alg->algorithm, 0); | |
136 | ||
137 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, | |
138 | keytype, 0); | |
139 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, | |
140 | "PrivateKeyInfo", 0); | |
141 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, | |
142 | der, der_len); | |
143 | *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); | |
144 | *p = OSSL_PARAM_construct_end(); | |
145 | ||
146 | ok = data_cb(params, data_cbarg); | |
147 | } | |
148 | PKCS8_PRIV_KEY_INFO_free(p8inf); | |
149 | OPENSSL_free(der); | |
150 | return ok; | |
151 | } | |
152 | ||
153 | const OSSL_DISPATCH ossl_EncryptedPrivateKeyInfo_der_to_der_decoder_functions[] = { | |
154 | { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))epki2pki_newctx }, | |
155 | { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))epki2pki_freectx }, | |
156 | { OSSL_FUNC_DECODER_DECODE, (void (*)(void))epki2pki_decode }, | |
157 | { 0, NULL } | |
158 | }; |