2 * Copyright 1995-2023 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
10 /* We need to use some deprecated APIs */
11 #define OPENSSL_SUPPRESS_DEPRECATED
14 #include <openssl/buffer.h>
15 #include <openssl/objects.h>
16 #include <openssl/evp.h>
17 #include <openssl/x509.h>
18 #include <openssl/pkcs12.h>
19 #include <openssl/pem.h>
20 #include <openssl/engine.h>
21 #include <openssl/dh.h>
22 #include <openssl/decoder.h>
23 #include <openssl/ui.h>
24 #include "internal/cryptlib.h"
25 #include "internal/passphrase.h"
26 #include "crypto/asn1.h"
27 #include "crypto/x509.h"
28 #include "crypto/evp.h"
29 #include "pem_local.h"
31 int ossl_pem_check_suffix(const char *pem_str
, const char *suffix
);
33 static EVP_PKEY
*pem_read_bio_key_decoder(BIO
*bp
, EVP_PKEY
**x
,
34 pem_password_cb
*cb
, void *u
,
39 EVP_PKEY
*pkey
= NULL
;
40 OSSL_DECODER_CTX
*dctx
= NULL
;
43 if ((pos
= BIO_tell(bp
)) < 0)
44 /* We can depend on BIO_tell() thanks to the BIO_f_readbuffer() */
47 dctx
= OSSL_DECODER_CTX_new_for_pkey(&pkey
, "PEM", NULL
, NULL
,
48 selection
, libctx
, propq
);
54 cb
= PEM_def_callback
;
56 if (!OSSL_DECODER_CTX_set_pem_password_cb(dctx
, cb
, u
))
60 while (!OSSL_DECODER_from_bio(dctx
, bp
) || pkey
== NULL
)
61 if (BIO_eof(bp
) != 0 || (newpos
= BIO_tell(bp
)) < 0 || newpos
<= pos
) {
62 ERR_clear_last_mark();
65 if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_UNSUPPORTED
) {
66 /* unsupported PEM data, try again */
70 /* other error, bail out */
71 ERR_clear_last_mark();
78 /* if we were asked for private key, the public key is optional */
79 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0)
80 selection
= selection
& ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY
;
82 if (!evp_keymgmt_util_has(pkey
, selection
)) {
85 ERR_raise(ERR_LIB_PEM
, PEM_R_UNSUPPORTED_KEY_COMPONENTS
);
95 OSSL_DECODER_CTX_free(dctx
);
99 static EVP_PKEY
*pem_read_bio_key_legacy(BIO
*bp
, EVP_PKEY
**x
,
100 pem_password_cb
*cb
, void *u
,
101 OSSL_LIB_CTX
*libctx
,
106 const unsigned char *p
= NULL
;
107 unsigned char *data
= NULL
;
110 EVP_PKEY
*ret
= NULL
;
112 ERR_set_mark(); /* not interested in PEM read errors */
113 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0) {
114 if (!PEM_bytes_read_bio_secmem(&data
, &len
, &nm
,
121 const char *pem_string
= PEM_STRING_PARAMETERS
;
123 if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
124 pem_string
= PEM_STRING_PUBLIC
;
125 if (!PEM_bytes_read_bio(&data
, &len
, &nm
,
132 ERR_clear_last_mark();
135 if (strcmp(nm
, PEM_STRING_PKCS8INF
) == 0) {
136 PKCS8_PRIV_KEY_INFO
*p8inf
;
138 if ((p8inf
= d2i_PKCS8_PRIV_KEY_INFO(NULL
, &p
, len
)) == NULL
)
140 ret
= evp_pkcs82pkey_legacy(p8inf
, libctx
, propq
);
145 PKCS8_PRIV_KEY_INFO_free(p8inf
);
146 } else if (strcmp(nm
, PEM_STRING_PKCS8
) == 0) {
147 PKCS8_PRIV_KEY_INFO
*p8inf
;
150 char psbuf
[PEM_BUFSIZE
];
152 if ((p8
= d2i_X509_SIG(NULL
, &p
, len
)) == NULL
)
155 klen
= cb(psbuf
, PEM_BUFSIZE
, 0, u
);
157 klen
= PEM_def_callback(psbuf
, PEM_BUFSIZE
, 0, u
);
159 ERR_raise(ERR_LIB_PEM
, PEM_R_BAD_PASSWORD_READ
);
163 p8inf
= PKCS8_decrypt(p8
, psbuf
, klen
);
165 OPENSSL_cleanse(psbuf
, klen
);
168 ret
= evp_pkcs82pkey_legacy(p8inf
, libctx
, propq
);
173 PKCS8_PRIV_KEY_INFO_free(p8inf
);
174 } else if ((slen
= ossl_pem_check_suffix(nm
, "PRIVATE KEY")) > 0) {
175 const EVP_PKEY_ASN1_METHOD
*ameth
;
176 ameth
= EVP_PKEY_asn1_find_str(NULL
, nm
, slen
);
177 if (ameth
== NULL
|| ameth
->old_priv_decode
== NULL
)
179 ret
= ossl_d2i_PrivateKey_legacy(ameth
->pkey_id
, x
, &p
, len
, libctx
,
181 } else if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) == 0
182 && (selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0) {
183 /* Trying legacy PUBKEY decoding only if we do not want private key. */
184 ret
= ossl_d2i_PUBKEY_legacy(x
, &p
, len
);
185 } else if ((selection
& EVP_PKEY_KEYPAIR
) == 0
186 && (slen
= ossl_pem_check_suffix(nm
, "PARAMETERS")) > 0) {
187 /* Trying legacy params decoding only if we do not want a key. */
188 ret
= EVP_PKEY_new();
191 if (!EVP_PKEY_set_type_str(ret
, nm
, slen
)
192 || !ret
->ameth
->param_decode
193 || !ret
->ameth
->param_decode(ret
, &p
, len
)) {
205 if (ret
== NULL
&& ERR_peek_last_error() == 0)
206 /* ensure some error is reported but do not hide the real one */
207 ERR_raise(ERR_LIB_PEM
, ERR_R_ASN1_LIB
);
209 OPENSSL_secure_free(nm
);
210 OPENSSL_secure_clear_free(data
, len
);
214 static EVP_PKEY
*pem_read_bio_key(BIO
*bp
, EVP_PKEY
**x
,
215 pem_password_cb
*cb
, void *u
,
216 OSSL_LIB_CTX
*libctx
,
220 EVP_PKEY
*ret
= NULL
;
223 struct ossl_passphrase_data_st pwdata
= { 0 };
225 if ((pos
= BIO_tell(bp
)) < 0) {
226 new_bio
= BIO_new(BIO_f_readbuffer());
229 bp
= BIO_push(new_bio
, bp
);
234 cb
= PEM_def_callback
;
236 if (!ossl_pw_set_pem_password_cb(&pwdata
, cb
, u
)
237 || !ossl_pw_enable_passphrase_caching(&pwdata
))
241 ret
= pem_read_bio_key_decoder(bp
, x
, ossl_pw_pem_password
, &pwdata
,
242 libctx
, propq
, selection
);
244 && (BIO_seek(bp
, pos
) < 0
245 || (ret
= pem_read_bio_key_legacy(bp
, x
,
246 ossl_pw_pem_password
, &pwdata
,
248 selection
)) == NULL
))
249 ERR_clear_last_mark();
254 ossl_pw_clear_passphrase_data(&pwdata
);
255 if (new_bio
!= NULL
) {
262 EVP_PKEY
*PEM_read_bio_PUBKEY_ex(BIO
*bp
, EVP_PKEY
**x
,
263 pem_password_cb
*cb
, void *u
,
264 OSSL_LIB_CTX
*libctx
, const char *propq
)
266 return pem_read_bio_key(bp
, x
, cb
, u
, libctx
, propq
,
267 EVP_PKEY_PUBLIC_KEY
);
270 EVP_PKEY
*PEM_read_bio_PUBKEY(BIO
*bp
, EVP_PKEY
**x
, pem_password_cb
*cb
,
273 return PEM_read_bio_PUBKEY_ex(bp
, x
, cb
, u
, NULL
, NULL
);
276 #ifndef OPENSSL_NO_STDIO
277 EVP_PKEY
*PEM_read_PUBKEY_ex(FILE *fp
, EVP_PKEY
**x
,
278 pem_password_cb
*cb
, void *u
,
279 OSSL_LIB_CTX
*libctx
, const char *propq
)
284 if ((b
= BIO_new(BIO_s_file())) == NULL
) {
285 ERR_raise(ERR_LIB_PEM
, ERR_R_BUF_LIB
);
288 BIO_set_fp(b
, fp
, BIO_NOCLOSE
);
289 ret
= PEM_read_bio_PUBKEY_ex(b
, x
, cb
, u
, libctx
, propq
);
294 EVP_PKEY
*PEM_read_PUBKEY(FILE *fp
, EVP_PKEY
**x
, pem_password_cb
*cb
, void *u
)
296 return PEM_read_PUBKEY_ex(fp
, x
, cb
, u
, NULL
, NULL
);
300 EVP_PKEY
*PEM_read_bio_PrivateKey_ex(BIO
*bp
, EVP_PKEY
**x
,
301 pem_password_cb
*cb
, void *u
,
302 OSSL_LIB_CTX
*libctx
, const char *propq
)
304 return pem_read_bio_key(bp
, x
, cb
, u
, libctx
, propq
,
305 /* we also want the public key, if available */
309 EVP_PKEY
*PEM_read_bio_PrivateKey(BIO
*bp
, EVP_PKEY
**x
, pem_password_cb
*cb
,
312 return PEM_read_bio_PrivateKey_ex(bp
, x
, cb
, u
, NULL
, NULL
);
315 PEM_write_cb_ex_fnsig(PrivateKey
, EVP_PKEY
, BIO
, write_bio
)
317 IMPLEMENT_PEM_provided_write_body_vars(pkey
, PrivateKey
, propq
);
319 IMPLEMENT_PEM_provided_write_body_pass();
320 IMPLEMENT_PEM_provided_write_body_main(pkey
, bio
);
323 if (x
!= NULL
&& (x
->ameth
== NULL
|| x
->ameth
->priv_encode
!= NULL
))
324 return PEM_write_bio_PKCS8PrivateKey(out
, x
, enc
,
325 (const char *)kstr
, klen
, cb
, u
);
326 return PEM_write_bio_PrivateKey_traditional(out
, x
, enc
, kstr
, klen
, cb
, u
);
329 PEM_write_cb_fnsig(PrivateKey
, EVP_PKEY
, BIO
, write_bio
)
331 return PEM_write_bio_PrivateKey_ex(out
, x
, enc
, kstr
, klen
, cb
, u
,
336 * Note: there is no way to tell a provided pkey encoder to use "traditional"
337 * encoding. Therefore, if the pkey is provided, we try to take a copy
339 int PEM_write_bio_PrivateKey_traditional(BIO
*bp
, const EVP_PKEY
*x
,
340 const EVP_CIPHER
*enc
,
341 const unsigned char *kstr
, int klen
,
342 pem_password_cb
*cb
, void *u
)
345 EVP_PKEY
*copy
= NULL
;
351 if (evp_pkey_is_assigned(x
)
352 && evp_pkey_is_provided(x
)
353 && evp_pkey_copy_downgraded(©
, x
))
356 if (x
->ameth
== NULL
|| x
->ameth
->old_priv_encode
== NULL
) {
357 ERR_raise(ERR_LIB_PEM
, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE
);
361 BIO_snprintf(pem_str
, 80, "%s PRIVATE KEY", x
->ameth
->pem_str
);
362 ret
= PEM_ASN1_write_bio((i2d_of_void
*)i2d_PrivateKey
,
363 pem_str
, bp
, x
, enc
, kstr
, klen
, cb
, u
);
369 static int no_password_cb(char *buf
, int num
, int rwflag
, void *userdata
)
374 EVP_PKEY
*PEM_read_bio_Parameters_ex(BIO
*bp
, EVP_PKEY
**x
,
375 OSSL_LIB_CTX
*libctx
, const char *propq
)
378 * PEM_read_bio_Parameters(_ex) should never ask for a password. Any attempt
379 * to get a password just fails.
381 return pem_read_bio_key(bp
, x
, no_password_cb
, NULL
, libctx
, propq
,
382 EVP_PKEY_KEY_PARAMETERS
);
385 EVP_PKEY
*PEM_read_bio_Parameters(BIO
*bp
, EVP_PKEY
**x
)
387 return PEM_read_bio_Parameters_ex(bp
, x
, NULL
, NULL
);
390 PEM_write_fnsig(Parameters
, EVP_PKEY
, BIO
, write_bio
)
393 IMPLEMENT_PEM_provided_write_body_vars(pkey
, Parameters
, NULL
);
395 IMPLEMENT_PEM_provided_write_body_main(pkey
, bio
);
398 if (!x
->ameth
|| !x
->ameth
->param_encode
)
401 BIO_snprintf(pem_str
, 80, "%s PARAMETERS", x
->ameth
->pem_str
);
402 return PEM_ASN1_write_bio((i2d_of_void
*)x
->ameth
->param_encode
,
403 pem_str
, out
, x
, NULL
, NULL
, 0, 0, NULL
);
406 #ifndef OPENSSL_NO_STDIO
407 EVP_PKEY
*PEM_read_PrivateKey_ex(FILE *fp
, EVP_PKEY
**x
, pem_password_cb
*cb
,
408 void *u
, OSSL_LIB_CTX
*libctx
,
414 if ((b
= BIO_new(BIO_s_file())) == NULL
) {
415 ERR_raise(ERR_LIB_PEM
, ERR_R_BUF_LIB
);
418 BIO_set_fp(b
, fp
, BIO_NOCLOSE
);
419 ret
= PEM_read_bio_PrivateKey_ex(b
, x
, cb
, u
, libctx
, propq
);
424 EVP_PKEY
*PEM_read_PrivateKey(FILE *fp
, EVP_PKEY
**x
, pem_password_cb
*cb
,
427 return PEM_read_PrivateKey_ex(fp
, x
, cb
, u
, NULL
, NULL
);
430 PEM_write_cb_ex_fnsig(PrivateKey
, EVP_PKEY
, FILE, write
)
435 if ((b
= BIO_new_fp(out
, BIO_NOCLOSE
)) == NULL
) {
436 ERR_raise(ERR_LIB_PEM
, ERR_R_BUF_LIB
);
439 ret
= PEM_write_bio_PrivateKey_ex(b
, x
, enc
, kstr
, klen
, cb
, u
,
445 PEM_write_cb_fnsig(PrivateKey
, EVP_PKEY
, FILE, write
)
447 return PEM_write_PrivateKey_ex(out
, x
, enc
, kstr
, klen
, cb
, u
, NULL
, NULL
);