1 /* 2 * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 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 /* We need to use some deprecated APIs */ 11 #define OPENSSL_SUPPRESS_DEPRECATED 12 13 #include <stdio.h> 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" 30 31 int ossl_pem_check_suffix(const char *pem_str, const char *suffix); 32 33 static EVP_PKEY *pem_read_bio_key_decoder(BIO *bp, EVP_PKEY **x, 34 pem_password_cb *cb, void *u, 35 OSSL_LIB_CTX *libctx, 36 const char *propq, 37 int selection) 38 { 39 EVP_PKEY *pkey = NULL; 40 OSSL_DECODER_CTX *dctx = NULL; 41 int pos, newpos; 42 43 if ((pos = BIO_tell(bp)) < 0) 44 /* We can depend on BIO_tell() thanks to the BIO_f_readbuffer() */ 45 return NULL; 46 47 dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL, 48 selection, libctx, propq); 49 50 if (dctx == NULL) 51 return NULL; 52 53 if (cb == NULL) 54 cb = PEM_def_callback; 55 56 if (!OSSL_DECODER_CTX_set_pem_password_cb(dctx, cb, u)) 57 goto err; 58 59 ERR_set_mark(); 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(); 63 goto err; 64 } else { 65 if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_UNSUPPORTED) { 66 /* unsupported PEM data, try again */ 67 ERR_pop_to_mark(); 68 ERR_set_mark(); 69 } else { 70 /* other error, bail out */ 71 ERR_clear_last_mark(); 72 goto err; 73 } 74 pos = newpos; 75 } 76 ERR_pop_to_mark(); 77 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; 81 82 if (!evp_keymgmt_util_has(pkey, selection)) { 83 EVP_PKEY_free(pkey); 84 pkey = NULL; 85 ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 86 goto err; 87 } 88 89 if (x != NULL) { 90 EVP_PKEY_free(*x); 91 *x = pkey; 92 } 93 94 err: 95 OSSL_DECODER_CTX_free(dctx); 96 return pkey; 97 } 98 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, 102 const char *propq, 103 int selection) 104 { 105 char *nm = NULL; 106 const unsigned char *p = NULL; 107 unsigned char *data = NULL; 108 long len; 109 int slen; 110 EVP_PKEY *ret = NULL; 111 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, 115 PEM_STRING_EVP_PKEY, 116 bp, cb, u)) { 117 ERR_pop_to_mark(); 118 return NULL; 119 } 120 } else { 121 const char *pem_string = PEM_STRING_PARAMETERS; 122 123 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 124 pem_string = PEM_STRING_PUBLIC; 125 if (!PEM_bytes_read_bio(&data, &len, &nm, 126 pem_string, 127 bp, cb, u)) { 128 ERR_pop_to_mark(); 129 return NULL; 130 } 131 } 132 ERR_clear_last_mark(); 133 p = data; 134 135 if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { 136 PKCS8_PRIV_KEY_INFO *p8inf; 137 138 if ((p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len)) == NULL) 139 goto p8err; 140 ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq); 141 if (x != NULL) { 142 EVP_PKEY_free(*x); 143 *x = ret; 144 } 145 PKCS8_PRIV_KEY_INFO_free(p8inf); 146 } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { 147 PKCS8_PRIV_KEY_INFO *p8inf; 148 X509_SIG *p8; 149 int klen; 150 char psbuf[PEM_BUFSIZE]; 151 152 if ((p8 = d2i_X509_SIG(NULL, &p, len)) == NULL) 153 goto p8err; 154 if (cb != NULL) 155 klen = cb(psbuf, PEM_BUFSIZE, 0, u); 156 else 157 klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); 158 if (klen < 0) { 159 ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ); 160 X509_SIG_free(p8); 161 goto err; 162 } 163 p8inf = PKCS8_decrypt(p8, psbuf, klen); 164 X509_SIG_free(p8); 165 OPENSSL_cleanse(psbuf, klen); 166 if (p8inf == NULL) 167 goto p8err; 168 ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq); 169 if (x != NULL) { 170 EVP_PKEY_free(*x); 171 *x = ret; 172 } 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) 178 goto p8err; 179 ret = ossl_d2i_PrivateKey_legacy(ameth->pkey_id, x, &p, len, libctx, 180 propq); 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(); 189 if (ret == NULL) 190 goto err; 191 if (!EVP_PKEY_set_type_str(ret, nm, slen) 192 || !ret->ameth->param_decode 193 || !ret->ameth->param_decode(ret, &p, len)) { 194 EVP_PKEY_free(ret); 195 ret = NULL; 196 goto err; 197 } 198 if (x) { 199 EVP_PKEY_free(*x); 200 *x = ret; 201 } 202 } 203 204 p8err: 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); 208 err: 209 OPENSSL_secure_free(nm); 210 OPENSSL_secure_clear_free(data, len); 211 return ret; 212 } 213 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, 217 const char *propq, 218 int selection) 219 { 220 EVP_PKEY *ret = NULL; 221 BIO *new_bio = NULL; 222 int pos; 223 struct ossl_passphrase_data_st pwdata = { 0 }; 224 225 if ((pos = BIO_tell(bp)) < 0) { 226 new_bio = BIO_new(BIO_f_readbuffer()); 227 if (new_bio == NULL) 228 return NULL; 229 bp = BIO_push(new_bio, bp); 230 pos = BIO_tell(bp); 231 } 232 233 if (cb == NULL) 234 cb = PEM_def_callback; 235 236 if (!ossl_pw_set_pem_password_cb(&pwdata, cb, u) 237 || !ossl_pw_enable_passphrase_caching(&pwdata)) 238 goto err; 239 240 ERR_set_mark(); 241 ret = pem_read_bio_key_decoder(bp, x, ossl_pw_pem_password, &pwdata, 242 libctx, propq, selection); 243 if (ret == NULL 244 && (BIO_seek(bp, pos) < 0 245 || (ret = pem_read_bio_key_legacy(bp, x, 246 ossl_pw_pem_password, &pwdata, 247 libctx, propq, 248 selection)) == NULL)) 249 ERR_clear_last_mark(); 250 else 251 ERR_pop_to_mark(); 252 253 err: 254 ossl_pw_clear_passphrase_data(&pwdata); 255 if (new_bio != NULL) { 256 BIO_pop(new_bio); 257 BIO_free(new_bio); 258 } 259 return ret; 260 } 261 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) 265 { 266 return pem_read_bio_key(bp, x, cb, u, libctx, propq, 267 EVP_PKEY_PUBLIC_KEY); 268 } 269 270 EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, 271 void *u) 272 { 273 return PEM_read_bio_PUBKEY_ex(bp, x, cb, u, NULL, NULL); 274 } 275 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) 280 { 281 BIO *b; 282 EVP_PKEY *ret; 283 284 if ((b = BIO_new(BIO_s_file())) == NULL) { 285 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 286 return 0; 287 } 288 BIO_set_fp(b, fp, BIO_NOCLOSE); 289 ret = PEM_read_bio_PUBKEY_ex(b, x, cb, u, libctx, propq); 290 BIO_free(b); 291 return ret; 292 } 293 294 EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) 295 { 296 return PEM_read_PUBKEY_ex(fp, x, cb, u, NULL, NULL); 297 } 298 #endif 299 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) 303 { 304 return pem_read_bio_key(bp, x, cb, u, libctx, propq, 305 /* we also want the public key, if available */ 306 EVP_PKEY_KEYPAIR); 307 } 308 309 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, 310 void *u) 311 { 312 return PEM_read_bio_PrivateKey_ex(bp, x, cb, u, NULL, NULL); 313 } 314 315 PEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) 316 { 317 IMPLEMENT_PEM_provided_write_body_vars(pkey, PrivateKey, propq); 318 319 IMPLEMENT_PEM_provided_write_body_pass(); 320 IMPLEMENT_PEM_provided_write_body_main(pkey, bio); 321 322 legacy: 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); 327 } 328 329 PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) 330 { 331 return PEM_write_bio_PrivateKey_ex(out, x, enc, kstr, klen, cb, u, 332 NULL, NULL); 333 } 334 335 /* 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 338 */ 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) 343 { 344 char pem_str[80]; 345 EVP_PKEY *copy = NULL; 346 int ret; 347 348 if (x == NULL) 349 return 0; 350 351 if (evp_pkey_is_assigned(x) 352 && evp_pkey_is_provided(x) 353 && evp_pkey_copy_downgraded(©, x)) 354 x = copy; 355 356 if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) { 357 ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); 358 EVP_PKEY_free(copy); 359 return 0; 360 } 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); 364 365 EVP_PKEY_free(copy); 366 return ret; 367 } 368 369 static int no_password_cb(char *buf, int num, int rwflag, void *userdata) 370 { 371 return -1; 372 } 373 374 EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x, 375 OSSL_LIB_CTX *libctx, const char *propq) 376 { 377 /* 378 * PEM_read_bio_Parameters(_ex) should never ask for a password. Any attempt 379 * to get a password just fails. 380 */ 381 return pem_read_bio_key(bp, x, no_password_cb, NULL, libctx, propq, 382 EVP_PKEY_KEY_PARAMETERS); 383 } 384 385 EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) 386 { 387 return PEM_read_bio_Parameters_ex(bp, x, NULL, NULL); 388 } 389 390 PEM_write_fnsig(Parameters, EVP_PKEY, BIO, write_bio) 391 { 392 char pem_str[80]; 393 IMPLEMENT_PEM_provided_write_body_vars(pkey, Parameters, NULL); 394 395 IMPLEMENT_PEM_provided_write_body_main(pkey, bio); 396 397 legacy: 398 if (!x->ameth || !x->ameth->param_encode) 399 return 0; 400 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); 404 } 405 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, 409 const char *propq) 410 { 411 BIO *b; 412 EVP_PKEY *ret; 413 414 if ((b = BIO_new(BIO_s_file())) == NULL) { 415 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 416 return 0; 417 } 418 BIO_set_fp(b, fp, BIO_NOCLOSE); 419 ret = PEM_read_bio_PrivateKey_ex(b, x, cb, u, libctx, propq); 420 BIO_free(b); 421 return ret; 422 } 423 424 EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, 425 void *u) 426 { 427 return PEM_read_PrivateKey_ex(fp, x, cb, u, NULL, NULL); 428 } 429 430 PEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, FILE, write) 431 { 432 BIO *b; 433 int ret; 434 435 if ((b = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { 436 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 437 return 0; 438 } 439 ret = PEM_write_bio_PrivateKey_ex(b, x, enc, kstr, klen, cb, u, 440 libctx, propq); 441 BIO_free(b); 442 return ret; 443 } 444 445 PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, FILE, write) 446 { 447 return PEM_write_PrivateKey_ex(out, x, enc, kstr, klen, cb, u, NULL, NULL); 448 } 449 #endif 450