1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* We need to use some deprecated APIs */ 11e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include <stdio.h> 14e1051a39Sopenharmony_ci#include <openssl/buffer.h> 15e1051a39Sopenharmony_ci#include <openssl/objects.h> 16e1051a39Sopenharmony_ci#include <openssl/evp.h> 17e1051a39Sopenharmony_ci#include <openssl/x509.h> 18e1051a39Sopenharmony_ci#include <openssl/pkcs12.h> 19e1051a39Sopenharmony_ci#include <openssl/pem.h> 20e1051a39Sopenharmony_ci#include <openssl/engine.h> 21e1051a39Sopenharmony_ci#include <openssl/dh.h> 22e1051a39Sopenharmony_ci#include <openssl/decoder.h> 23e1051a39Sopenharmony_ci#include <openssl/ui.h> 24e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 25e1051a39Sopenharmony_ci#include "internal/passphrase.h" 26e1051a39Sopenharmony_ci#include "crypto/asn1.h" 27e1051a39Sopenharmony_ci#include "crypto/x509.h" 28e1051a39Sopenharmony_ci#include "crypto/evp.h" 29e1051a39Sopenharmony_ci#include "pem_local.h" 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ciint ossl_pem_check_suffix(const char *pem_str, const char *suffix); 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_cistatic EVP_PKEY *pem_read_bio_key_decoder(BIO *bp, EVP_PKEY **x, 34e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 35e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, 36e1051a39Sopenharmony_ci const char *propq, 37e1051a39Sopenharmony_ci int selection) 38e1051a39Sopenharmony_ci{ 39e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 40e1051a39Sopenharmony_ci OSSL_DECODER_CTX *dctx = NULL; 41e1051a39Sopenharmony_ci int pos, newpos; 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci if ((pos = BIO_tell(bp)) < 0) 44e1051a39Sopenharmony_ci /* We can depend on BIO_tell() thanks to the BIO_f_readbuffer() */ 45e1051a39Sopenharmony_ci return NULL; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL, 48e1051a39Sopenharmony_ci selection, libctx, propq); 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci if (dctx == NULL) 51e1051a39Sopenharmony_ci return NULL; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci if (cb == NULL) 54e1051a39Sopenharmony_ci cb = PEM_def_callback; 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci if (!OSSL_DECODER_CTX_set_pem_password_cb(dctx, cb, u)) 57e1051a39Sopenharmony_ci goto err; 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci ERR_set_mark(); 60e1051a39Sopenharmony_ci while (!OSSL_DECODER_from_bio(dctx, bp) || pkey == NULL) 61e1051a39Sopenharmony_ci if (BIO_eof(bp) != 0 || (newpos = BIO_tell(bp)) < 0 || newpos <= pos) { 62e1051a39Sopenharmony_ci ERR_clear_last_mark(); 63e1051a39Sopenharmony_ci goto err; 64e1051a39Sopenharmony_ci } else { 65e1051a39Sopenharmony_ci if (ERR_GET_REASON(ERR_peek_error()) == ERR_R_UNSUPPORTED) { 66e1051a39Sopenharmony_ci /* unsupported PEM data, try again */ 67e1051a39Sopenharmony_ci ERR_pop_to_mark(); 68e1051a39Sopenharmony_ci ERR_set_mark(); 69e1051a39Sopenharmony_ci } else { 70e1051a39Sopenharmony_ci /* other error, bail out */ 71e1051a39Sopenharmony_ci ERR_clear_last_mark(); 72e1051a39Sopenharmony_ci goto err; 73e1051a39Sopenharmony_ci } 74e1051a39Sopenharmony_ci pos = newpos; 75e1051a39Sopenharmony_ci } 76e1051a39Sopenharmony_ci ERR_pop_to_mark(); 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci /* if we were asked for private key, the public key is optional */ 79e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 80e1051a39Sopenharmony_ci selection = selection & ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY; 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci if (!evp_keymgmt_util_has(pkey, selection)) { 83e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 84e1051a39Sopenharmony_ci pkey = NULL; 85e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS); 86e1051a39Sopenharmony_ci goto err; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci if (x != NULL) { 90e1051a39Sopenharmony_ci EVP_PKEY_free(*x); 91e1051a39Sopenharmony_ci *x = pkey; 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci err: 95e1051a39Sopenharmony_ci OSSL_DECODER_CTX_free(dctx); 96e1051a39Sopenharmony_ci return pkey; 97e1051a39Sopenharmony_ci} 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_cistatic EVP_PKEY *pem_read_bio_key_legacy(BIO *bp, EVP_PKEY **x, 100e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 101e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, 102e1051a39Sopenharmony_ci const char *propq, 103e1051a39Sopenharmony_ci int selection) 104e1051a39Sopenharmony_ci{ 105e1051a39Sopenharmony_ci char *nm = NULL; 106e1051a39Sopenharmony_ci const unsigned char *p = NULL; 107e1051a39Sopenharmony_ci unsigned char *data = NULL; 108e1051a39Sopenharmony_ci long len; 109e1051a39Sopenharmony_ci int slen; 110e1051a39Sopenharmony_ci EVP_PKEY *ret = NULL; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci ERR_set_mark(); /* not interested in PEM read errors */ 113e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { 114e1051a39Sopenharmony_ci if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, 115e1051a39Sopenharmony_ci PEM_STRING_EVP_PKEY, 116e1051a39Sopenharmony_ci bp, cb, u)) { 117e1051a39Sopenharmony_ci ERR_pop_to_mark(); 118e1051a39Sopenharmony_ci return NULL; 119e1051a39Sopenharmony_ci } 120e1051a39Sopenharmony_ci } else { 121e1051a39Sopenharmony_ci const char *pem_string = PEM_STRING_PARAMETERS; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 124e1051a39Sopenharmony_ci pem_string = PEM_STRING_PUBLIC; 125e1051a39Sopenharmony_ci if (!PEM_bytes_read_bio(&data, &len, &nm, 126e1051a39Sopenharmony_ci pem_string, 127e1051a39Sopenharmony_ci bp, cb, u)) { 128e1051a39Sopenharmony_ci ERR_pop_to_mark(); 129e1051a39Sopenharmony_ci return NULL; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci } 132e1051a39Sopenharmony_ci ERR_clear_last_mark(); 133e1051a39Sopenharmony_ci p = data; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { 136e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO *p8inf; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci if ((p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len)) == NULL) 139e1051a39Sopenharmony_ci goto p8err; 140e1051a39Sopenharmony_ci ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq); 141e1051a39Sopenharmony_ci if (x != NULL) { 142e1051a39Sopenharmony_ci EVP_PKEY_free(*x); 143e1051a39Sopenharmony_ci *x = ret; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO_free(p8inf); 146e1051a39Sopenharmony_ci } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { 147e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO *p8inf; 148e1051a39Sopenharmony_ci X509_SIG *p8; 149e1051a39Sopenharmony_ci int klen; 150e1051a39Sopenharmony_ci char psbuf[PEM_BUFSIZE]; 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci if ((p8 = d2i_X509_SIG(NULL, &p, len)) == NULL) 153e1051a39Sopenharmony_ci goto p8err; 154e1051a39Sopenharmony_ci if (cb != NULL) 155e1051a39Sopenharmony_ci klen = cb(psbuf, PEM_BUFSIZE, 0, u); 156e1051a39Sopenharmony_ci else 157e1051a39Sopenharmony_ci klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); 158e1051a39Sopenharmony_ci if (klen < 0) { 159e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ); 160e1051a39Sopenharmony_ci X509_SIG_free(p8); 161e1051a39Sopenharmony_ci goto err; 162e1051a39Sopenharmony_ci } 163e1051a39Sopenharmony_ci p8inf = PKCS8_decrypt(p8, psbuf, klen); 164e1051a39Sopenharmony_ci X509_SIG_free(p8); 165e1051a39Sopenharmony_ci OPENSSL_cleanse(psbuf, klen); 166e1051a39Sopenharmony_ci if (p8inf == NULL) 167e1051a39Sopenharmony_ci goto p8err; 168e1051a39Sopenharmony_ci ret = evp_pkcs82pkey_legacy(p8inf, libctx, propq); 169e1051a39Sopenharmony_ci if (x != NULL) { 170e1051a39Sopenharmony_ci EVP_PKEY_free(*x); 171e1051a39Sopenharmony_ci *x = ret; 172e1051a39Sopenharmony_ci } 173e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO_free(p8inf); 174e1051a39Sopenharmony_ci } else if ((slen = ossl_pem_check_suffix(nm, "PRIVATE KEY")) > 0) { 175e1051a39Sopenharmony_ci const EVP_PKEY_ASN1_METHOD *ameth; 176e1051a39Sopenharmony_ci ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); 177e1051a39Sopenharmony_ci if (ameth == NULL || ameth->old_priv_decode == NULL) 178e1051a39Sopenharmony_ci goto p8err; 179e1051a39Sopenharmony_ci ret = ossl_d2i_PrivateKey_legacy(ameth->pkey_id, x, &p, len, libctx, 180e1051a39Sopenharmony_ci propq); 181e1051a39Sopenharmony_ci } else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0 182e1051a39Sopenharmony_ci && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { 183e1051a39Sopenharmony_ci /* Trying legacy PUBKEY decoding only if we do not want private key. */ 184e1051a39Sopenharmony_ci ret = ossl_d2i_PUBKEY_legacy(x, &p, len); 185e1051a39Sopenharmony_ci } else if ((selection & EVP_PKEY_KEYPAIR) == 0 186e1051a39Sopenharmony_ci && (slen = ossl_pem_check_suffix(nm, "PARAMETERS")) > 0) { 187e1051a39Sopenharmony_ci /* Trying legacy params decoding only if we do not want a key. */ 188e1051a39Sopenharmony_ci ret = EVP_PKEY_new(); 189e1051a39Sopenharmony_ci if (ret == NULL) 190e1051a39Sopenharmony_ci goto err; 191e1051a39Sopenharmony_ci if (!EVP_PKEY_set_type_str(ret, nm, slen) 192e1051a39Sopenharmony_ci || !ret->ameth->param_decode 193e1051a39Sopenharmony_ci || !ret->ameth->param_decode(ret, &p, len)) { 194e1051a39Sopenharmony_ci EVP_PKEY_free(ret); 195e1051a39Sopenharmony_ci ret = NULL; 196e1051a39Sopenharmony_ci goto err; 197e1051a39Sopenharmony_ci } 198e1051a39Sopenharmony_ci if (x) { 199e1051a39Sopenharmony_ci EVP_PKEY_free(*x); 200e1051a39Sopenharmony_ci *x = ret; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci } 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci p8err: 205e1051a39Sopenharmony_ci if (ret == NULL && ERR_peek_last_error() == 0) 206e1051a39Sopenharmony_ci /* ensure some error is reported but do not hide the real one */ 207e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); 208e1051a39Sopenharmony_ci err: 209e1051a39Sopenharmony_ci OPENSSL_secure_free(nm); 210e1051a39Sopenharmony_ci OPENSSL_secure_clear_free(data, len); 211e1051a39Sopenharmony_ci return ret; 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_cistatic EVP_PKEY *pem_read_bio_key(BIO *bp, EVP_PKEY **x, 215e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 216e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, 217e1051a39Sopenharmony_ci const char *propq, 218e1051a39Sopenharmony_ci int selection) 219e1051a39Sopenharmony_ci{ 220e1051a39Sopenharmony_ci EVP_PKEY *ret = NULL; 221e1051a39Sopenharmony_ci BIO *new_bio = NULL; 222e1051a39Sopenharmony_ci int pos; 223e1051a39Sopenharmony_ci struct ossl_passphrase_data_st pwdata = { 0 }; 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ci if ((pos = BIO_tell(bp)) < 0) { 226e1051a39Sopenharmony_ci new_bio = BIO_new(BIO_f_readbuffer()); 227e1051a39Sopenharmony_ci if (new_bio == NULL) 228e1051a39Sopenharmony_ci return NULL; 229e1051a39Sopenharmony_ci bp = BIO_push(new_bio, bp); 230e1051a39Sopenharmony_ci pos = BIO_tell(bp); 231e1051a39Sopenharmony_ci } 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci if (cb == NULL) 234e1051a39Sopenharmony_ci cb = PEM_def_callback; 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci if (!ossl_pw_set_pem_password_cb(&pwdata, cb, u) 237e1051a39Sopenharmony_ci || !ossl_pw_enable_passphrase_caching(&pwdata)) 238e1051a39Sopenharmony_ci goto err; 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_ci ERR_set_mark(); 241e1051a39Sopenharmony_ci ret = pem_read_bio_key_decoder(bp, x, ossl_pw_pem_password, &pwdata, 242e1051a39Sopenharmony_ci libctx, propq, selection); 243e1051a39Sopenharmony_ci if (ret == NULL 244e1051a39Sopenharmony_ci && (BIO_seek(bp, pos) < 0 245e1051a39Sopenharmony_ci || (ret = pem_read_bio_key_legacy(bp, x, 246e1051a39Sopenharmony_ci ossl_pw_pem_password, &pwdata, 247e1051a39Sopenharmony_ci libctx, propq, 248e1051a39Sopenharmony_ci selection)) == NULL)) 249e1051a39Sopenharmony_ci ERR_clear_last_mark(); 250e1051a39Sopenharmony_ci else 251e1051a39Sopenharmony_ci ERR_pop_to_mark(); 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ci err: 254e1051a39Sopenharmony_ci ossl_pw_clear_passphrase_data(&pwdata); 255e1051a39Sopenharmony_ci if (new_bio != NULL) { 256e1051a39Sopenharmony_ci BIO_pop(new_bio); 257e1051a39Sopenharmony_ci BIO_free(new_bio); 258e1051a39Sopenharmony_ci } 259e1051a39Sopenharmony_ci return ret; 260e1051a39Sopenharmony_ci} 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x, 263e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 264e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 265e1051a39Sopenharmony_ci{ 266e1051a39Sopenharmony_ci return pem_read_bio_key(bp, x, cb, u, libctx, propq, 267e1051a39Sopenharmony_ci EVP_PKEY_PUBLIC_KEY); 268e1051a39Sopenharmony_ci} 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, 271e1051a39Sopenharmony_ci void *u) 272e1051a39Sopenharmony_ci{ 273e1051a39Sopenharmony_ci return PEM_read_bio_PUBKEY_ex(bp, x, cb, u, NULL, NULL); 274e1051a39Sopenharmony_ci} 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_STDIO 277e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x, 278e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 279e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 280e1051a39Sopenharmony_ci{ 281e1051a39Sopenharmony_ci BIO *b; 282e1051a39Sopenharmony_ci EVP_PKEY *ret; 283e1051a39Sopenharmony_ci 284e1051a39Sopenharmony_ci if ((b = BIO_new(BIO_s_file())) == NULL) { 285e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 286e1051a39Sopenharmony_ci return 0; 287e1051a39Sopenharmony_ci } 288e1051a39Sopenharmony_ci BIO_set_fp(b, fp, BIO_NOCLOSE); 289e1051a39Sopenharmony_ci ret = PEM_read_bio_PUBKEY_ex(b, x, cb, u, libctx, propq); 290e1051a39Sopenharmony_ci BIO_free(b); 291e1051a39Sopenharmony_ci return ret; 292e1051a39Sopenharmony_ci} 293e1051a39Sopenharmony_ci 294e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) 295e1051a39Sopenharmony_ci{ 296e1051a39Sopenharmony_ci return PEM_read_PUBKEY_ex(fp, x, cb, u, NULL, NULL); 297e1051a39Sopenharmony_ci} 298e1051a39Sopenharmony_ci#endif 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, 301e1051a39Sopenharmony_ci pem_password_cb *cb, void *u, 302e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 303e1051a39Sopenharmony_ci{ 304e1051a39Sopenharmony_ci return pem_read_bio_key(bp, x, cb, u, libctx, propq, 305e1051a39Sopenharmony_ci /* we also want the public key, if available */ 306e1051a39Sopenharmony_ci EVP_PKEY_KEYPAIR); 307e1051a39Sopenharmony_ci} 308e1051a39Sopenharmony_ci 309e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, 310e1051a39Sopenharmony_ci void *u) 311e1051a39Sopenharmony_ci{ 312e1051a39Sopenharmony_ci return PEM_read_bio_PrivateKey_ex(bp, x, cb, u, NULL, NULL); 313e1051a39Sopenharmony_ci} 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ciPEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) 316e1051a39Sopenharmony_ci{ 317e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(pkey, PrivateKey, propq); 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_pass(); 320e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(pkey, bio); 321e1051a39Sopenharmony_ci 322e1051a39Sopenharmony_ci legacy: 323e1051a39Sopenharmony_ci if (x != NULL && (x->ameth == NULL || x->ameth->priv_encode != NULL)) 324e1051a39Sopenharmony_ci return PEM_write_bio_PKCS8PrivateKey(out, x, enc, 325e1051a39Sopenharmony_ci (const char *)kstr, klen, cb, u); 326e1051a39Sopenharmony_ci return PEM_write_bio_PrivateKey_traditional(out, x, enc, kstr, klen, cb, u); 327e1051a39Sopenharmony_ci} 328e1051a39Sopenharmony_ci 329e1051a39Sopenharmony_ciPEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) 330e1051a39Sopenharmony_ci{ 331e1051a39Sopenharmony_ci return PEM_write_bio_PrivateKey_ex(out, x, enc, kstr, klen, cb, u, 332e1051a39Sopenharmony_ci NULL, NULL); 333e1051a39Sopenharmony_ci} 334e1051a39Sopenharmony_ci 335e1051a39Sopenharmony_ci/* 336e1051a39Sopenharmony_ci * Note: there is no way to tell a provided pkey encoder to use "traditional" 337e1051a39Sopenharmony_ci * encoding. Therefore, if the pkey is provided, we try to take a copy 338e1051a39Sopenharmony_ci */ 339e1051a39Sopenharmony_ciint PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x, 340e1051a39Sopenharmony_ci const EVP_CIPHER *enc, 341e1051a39Sopenharmony_ci const unsigned char *kstr, int klen, 342e1051a39Sopenharmony_ci pem_password_cb *cb, void *u) 343e1051a39Sopenharmony_ci{ 344e1051a39Sopenharmony_ci char pem_str[80]; 345e1051a39Sopenharmony_ci EVP_PKEY *copy = NULL; 346e1051a39Sopenharmony_ci int ret; 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci if (x == NULL) 349e1051a39Sopenharmony_ci return 0; 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci if (evp_pkey_is_assigned(x) 352e1051a39Sopenharmony_ci && evp_pkey_is_provided(x) 353e1051a39Sopenharmony_ci && evp_pkey_copy_downgraded(©, x)) 354e1051a39Sopenharmony_ci x = copy; 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) { 357e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); 358e1051a39Sopenharmony_ci EVP_PKEY_free(copy); 359e1051a39Sopenharmony_ci return 0; 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str); 362e1051a39Sopenharmony_ci ret = PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, 363e1051a39Sopenharmony_ci pem_str, bp, x, enc, kstr, klen, cb, u); 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci EVP_PKEY_free(copy); 366e1051a39Sopenharmony_ci return ret; 367e1051a39Sopenharmony_ci} 368e1051a39Sopenharmony_ci 369e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x, 370e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 371e1051a39Sopenharmony_ci{ 372e1051a39Sopenharmony_ci return pem_read_bio_key(bp, x, NULL, NULL, libctx, propq, 373e1051a39Sopenharmony_ci EVP_PKEY_KEY_PARAMETERS); 374e1051a39Sopenharmony_ci} 375e1051a39Sopenharmony_ci 376e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) 377e1051a39Sopenharmony_ci{ 378e1051a39Sopenharmony_ci return PEM_read_bio_Parameters_ex(bp, x, NULL, NULL); 379e1051a39Sopenharmony_ci} 380e1051a39Sopenharmony_ci 381e1051a39Sopenharmony_ciPEM_write_fnsig(Parameters, EVP_PKEY, BIO, write_bio) 382e1051a39Sopenharmony_ci{ 383e1051a39Sopenharmony_ci char pem_str[80]; 384e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(pkey, Parameters, NULL); 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(pkey, bio); 387e1051a39Sopenharmony_ci 388e1051a39Sopenharmony_ci legacy: 389e1051a39Sopenharmony_ci if (!x->ameth || !x->ameth->param_encode) 390e1051a39Sopenharmony_ci return 0; 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str); 393e1051a39Sopenharmony_ci return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode, 394e1051a39Sopenharmony_ci pem_str, out, x, NULL, NULL, 0, 0, NULL); 395e1051a39Sopenharmony_ci} 396e1051a39Sopenharmony_ci 397e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_STDIO 398e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_PrivateKey_ex(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, 399e1051a39Sopenharmony_ci void *u, OSSL_LIB_CTX *libctx, 400e1051a39Sopenharmony_ci const char *propq) 401e1051a39Sopenharmony_ci{ 402e1051a39Sopenharmony_ci BIO *b; 403e1051a39Sopenharmony_ci EVP_PKEY *ret; 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci if ((b = BIO_new(BIO_s_file())) == NULL) { 406e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 407e1051a39Sopenharmony_ci return 0; 408e1051a39Sopenharmony_ci } 409e1051a39Sopenharmony_ci BIO_set_fp(b, fp, BIO_NOCLOSE); 410e1051a39Sopenharmony_ci ret = PEM_read_bio_PrivateKey_ex(b, x, cb, u, libctx, propq); 411e1051a39Sopenharmony_ci BIO_free(b); 412e1051a39Sopenharmony_ci return ret; 413e1051a39Sopenharmony_ci} 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ciEVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, 416e1051a39Sopenharmony_ci void *u) 417e1051a39Sopenharmony_ci{ 418e1051a39Sopenharmony_ci return PEM_read_PrivateKey_ex(fp, x, cb, u, NULL, NULL); 419e1051a39Sopenharmony_ci} 420e1051a39Sopenharmony_ci 421e1051a39Sopenharmony_ciPEM_write_cb_ex_fnsig(PrivateKey, EVP_PKEY, FILE, write) 422e1051a39Sopenharmony_ci{ 423e1051a39Sopenharmony_ci BIO *b; 424e1051a39Sopenharmony_ci int ret; 425e1051a39Sopenharmony_ci 426e1051a39Sopenharmony_ci if ((b = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { 427e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 428e1051a39Sopenharmony_ci return 0; 429e1051a39Sopenharmony_ci } 430e1051a39Sopenharmony_ci ret = PEM_write_bio_PrivateKey_ex(b, x, enc, kstr, klen, cb, u, 431e1051a39Sopenharmony_ci libctx, propq); 432e1051a39Sopenharmony_ci BIO_free(b); 433e1051a39Sopenharmony_ci return ret; 434e1051a39Sopenharmony_ci} 435e1051a39Sopenharmony_ci 436e1051a39Sopenharmony_ciPEM_write_cb_fnsig(PrivateKey, EVP_PKEY, FILE, write) 437e1051a39Sopenharmony_ci{ 438e1051a39Sopenharmony_ci return PEM_write_PrivateKey_ex(out, x, enc, kstr, klen, cb, u, NULL, NULL); 439e1051a39Sopenharmony_ci} 440e1051a39Sopenharmony_ci#endif 441