2 * Copyright 2020 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>
25 #include "prov/implementations.h"
26 #include "prov/providercommonerr.h"
27 #include "endecoder_local.h"
29 static int read_pem(PROV_CTX
*provctx
, OSSL_CORE_BIO
*cin
,
30 char **pem_name
, char **pem_header
,
31 unsigned char **data
, long *len
)
33 BIO
*in
= bio_new_from_core_bio(provctx
, cin
);
34 int ok
= (PEM_read_bio(in
, pem_name
, pem_header
, data
, len
) > 0);
40 static OSSL_FUNC_decoder_newctx_fn pem2der_newctx
;
41 static OSSL_FUNC_decoder_freectx_fn pem2der_freectx
;
42 static OSSL_FUNC_decoder_gettable_params_fn pem2der_gettable_params
;
43 static OSSL_FUNC_decoder_get_params_fn pem2der_get_params
;
44 static OSSL_FUNC_decoder_decode_fn pem2der_decode
;
47 * Context used for PEM to DER decoding.
49 struct pem2der_ctx_st
{
53 static void *pem2der_newctx(void *provctx
)
55 struct pem2der_ctx_st
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
58 ctx
->provctx
= provctx
;
62 static void pem2der_freectx(void *vctx
)
64 struct pem2der_ctx_st
*ctx
= vctx
;
69 static const OSSL_PARAM
*pem2der_gettable_params(void *provctx
)
71 static const OSSL_PARAM gettables
[] = {
72 { OSSL_DECODER_PARAM_INPUT_TYPE
, OSSL_PARAM_UTF8_PTR
, NULL
, 0, 0 },
79 static int pem2der_get_params(OSSL_PARAM params
[])
83 p
= OSSL_PARAM_locate(params
, OSSL_DECODER_PARAM_INPUT_TYPE
);
84 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, "PEM"))
90 /* pem_password_cb compatible function */
91 struct pem2der_pass_data_st
{
92 OSSL_PASSPHRASE_CALLBACK
*cb
;
96 static int pem2der_pass_helper(char *buf
, int num
, int w
, void *data
)
98 struct pem2der_pass_data_st
*pass_data
= data
;
101 if (pass_data
== NULL
102 || pass_data
->cb
== NULL
103 || !pass_data
->cb(buf
, num
, &plen
, NULL
, pass_data
->cbarg
))
108 static int pem2der_decode(void *vctx
, OSSL_CORE_BIO
*cin
,
109 OSSL_CALLBACK
*data_cb
, void *data_cbarg
,
110 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
112 struct pem2der_ctx_st
*ctx
= vctx
;
113 char *pem_name
= NULL
, *pem_header
= NULL
;
114 unsigned char *der
= NULL
;
118 if (read_pem(ctx
->provctx
, cin
, &pem_name
, &pem_header
,
119 &der
, &der_len
) <= 0)
123 * 10 is the number of characters in "Proc-Type:", which
124 * PEM_get_EVP_CIPHER_INFO() requires to be present.
125 * If the PEM header has less characters than that, it's
126 * not worth spending cycles on it.
128 if (strlen(pem_header
) > 10) {
129 EVP_CIPHER_INFO cipher
;
130 struct pem2der_pass_data_st pass_data
;
132 pass_data
.cb
= pw_cb
;
133 pass_data
.cbarg
= pw_cbarg
;
134 if (!PEM_get_EVP_CIPHER_INFO(pem_header
, &cipher
)
135 || !PEM_do_header(&cipher
, der
, &der_len
,
136 pem2der_pass_helper
, &pass_data
))
141 OSSL_PARAM params
[3];
144 OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE
,
147 OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA
,
149 params
[2] = OSSL_PARAM_construct_end();
151 ok
= data_cb(params
, data_cbarg
);
155 OPENSSL_free(pem_name
);
156 OPENSSL_free(pem_header
);
161 const OSSL_DISPATCH pem_to_der_decoder_functions
[] = {
162 { OSSL_FUNC_DECODER_NEWCTX
, (void (*)(void))pem2der_newctx
},
163 { OSSL_FUNC_DECODER_FREECTX
, (void (*)(void))pem2der_freectx
},
164 { OSSL_FUNC_DECODER_GETTABLE_PARAMS
,
165 (void (*)(void))pem2der_gettable_params
},
166 { OSSL_FUNC_DECODER_GET_PARAMS
,
167 (void (*)(void))pem2der_get_params
},
168 { OSSL_FUNC_DECODER_DECODE
, (void (*)(void))pem2der_decode
},