2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
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
11 * RSA low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
18 #include <openssl/core_dispatch.h>
19 #include <openssl/core_names.h>
20 #include <openssl/crypto.h>
21 #include <openssl/err.h>
22 #include <openssl/params.h>
23 #include <openssl/pem.h>
24 #include <openssl/proverr.h>
25 #include "internal/nelem.h"
27 #include "prov/implementations.h"
28 #include "endecoder_local.h"
30 static int read_pem(PROV_CTX
*provctx
, OSSL_CORE_BIO
*cin
,
31 char **pem_name
, char **pem_header
,
32 unsigned char **data
, long *len
)
34 BIO
*in
= bio_new_from_core_bio(provctx
, cin
);
35 int ok
= (PEM_read_bio(in
, pem_name
, pem_header
, data
, len
) > 0);
41 static OSSL_FUNC_decoder_newctx_fn pem2der_newctx
;
42 static OSSL_FUNC_decoder_freectx_fn pem2der_freectx
;
43 static OSSL_FUNC_decoder_gettable_params_fn pem2der_gettable_params
;
44 static OSSL_FUNC_decoder_get_params_fn pem2der_get_params
;
45 static OSSL_FUNC_decoder_decode_fn pem2der_decode
;
48 * Context used for PEM to DER decoding.
50 struct pem2der_ctx_st
{
54 static void *pem2der_newctx(void *provctx
)
56 struct pem2der_ctx_st
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
59 ctx
->provctx
= provctx
;
63 static void pem2der_freectx(void *vctx
)
65 struct pem2der_ctx_st
*ctx
= vctx
;
70 static const OSSL_PARAM
*pem2der_gettable_params(void *provctx
)
72 static const OSSL_PARAM gettables
[] = {
73 { OSSL_DECODER_PARAM_INPUT_TYPE
, OSSL_PARAM_UTF8_PTR
, NULL
, 0, 0 },
80 static int pem2der_get_params(OSSL_PARAM params
[])
84 p
= OSSL_PARAM_locate(params
, OSSL_DECODER_PARAM_INPUT_TYPE
);
85 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, "PEM"))
91 /* pem_password_cb compatible function */
92 struct pem2der_pass_data_st
{
93 OSSL_PASSPHRASE_CALLBACK
*cb
;
97 static int pem2der_pass_helper(char *buf
, int num
, int w
, void *data
)
99 struct pem2der_pass_data_st
*pass_data
= data
;
102 if (pass_data
== NULL
103 || pass_data
->cb
== NULL
104 || !pass_data
->cb(buf
, num
, &plen
, NULL
, pass_data
->cbarg
))
110 * The selection parameter in pem2der_decode() is not used by this function
111 * because it's not relevant just to decode PEM to DER.
113 static int pem2der_decode(void *vctx
, OSSL_CORE_BIO
*cin
, int selection
,
114 OSSL_CALLBACK
*data_cb
, void *data_cbarg
,
115 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
117 /* Strings to peal off the pem name */
118 static const char *pealable_pem_name_endings
[] = {
120 * These entries should be in longest to shortest order to avoid
123 "ENCRYPTED PRIVATE KEY",
129 * Libcrypto currently only supports decoding keys with provider side
130 * decoders, so we don't try to peal any other PEM name. That's an
131 * exercise for when libcrypto starts to treat other types of objects
135 struct pem2der_ctx_st
*ctx
= vctx
;
136 char *pem_name
= NULL
, *pem_header
= NULL
;
137 size_t pem_name_len
, i
;
138 unsigned char *der
= NULL
;
142 if (read_pem(ctx
->provctx
, cin
, &pem_name
, &pem_header
,
143 &der
, &der_len
) <= 0)
147 * 10 is the number of characters in "Proc-Type:", which
148 * PEM_get_EVP_CIPHER_INFO() requires to be present.
149 * If the PEM header has less characters than that, it's
150 * not worth spending cycles on it.
152 if (strlen(pem_header
) > 10) {
153 EVP_CIPHER_INFO cipher
;
154 struct pem2der_pass_data_st pass_data
;
156 pass_data
.cb
= pw_cb
;
157 pass_data
.cbarg
= pw_cbarg
;
158 if (!PEM_get_EVP_CIPHER_INFO(pem_header
, &cipher
)
159 || !PEM_do_header(&cipher
, der
, &der_len
,
160 pem2der_pass_helper
, &pass_data
))
165 * Peal off certain strings from the end of |pem_name|, as they serve
166 * no further purpose.
168 for (i
= 0, pem_name_len
= strlen(pem_name
);
169 i
< OSSL_NELEM(pealable_pem_name_endings
);
171 size_t peal_len
= strlen(pealable_pem_name_endings
[i
]);
172 size_t pem_name_offset
;
174 if (peal_len
<= pem_name_len
) {
175 pem_name_offset
= pem_name_len
- peal_len
;
176 if (strcmp(pem_name
+ pem_name_offset
,
177 pealable_pem_name_endings
[i
]) == 0) {
180 pem_name
[pem_name_offset
] = '\0';
181 } while (pem_name_offset
> 0
182 && pem_name
[--pem_name_offset
] == ' ');
184 if (pem_name
[0] == '\0') {
185 OPENSSL_free(pem_name
);
194 OSSL_PARAM params
[3], *p
= params
;
196 if (pem_name
!= NULL
)
198 OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE
,
201 OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA
,
203 *p
= OSSL_PARAM_construct_end();
205 ok
= data_cb(params
, data_cbarg
);
209 OPENSSL_free(pem_name
);
210 OPENSSL_free(pem_header
);
215 const OSSL_DISPATCH ossl_pem_to_der_decoder_functions
[] = {
216 { OSSL_FUNC_DECODER_NEWCTX
, (void (*)(void))pem2der_newctx
},
217 { OSSL_FUNC_DECODER_FREECTX
, (void (*)(void))pem2der_freectx
},
218 { OSSL_FUNC_DECODER_GETTABLE_PARAMS
,
219 (void (*)(void))pem2der_gettable_params
},
220 { OSSL_FUNC_DECODER_GET_PARAMS
,
221 (void (*)(void))pem2der_get_params
},
222 { OSSL_FUNC_DECODER_DECODE
, (void (*)(void))pem2der_decode
},