1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-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#include <openssl/core_dispatch.h> 11e1051a39Sopenharmony_ci#include <openssl/pem.h> 12e1051a39Sopenharmony_ci#include <openssl/encoder.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci/* 15e1051a39Sopenharmony_ci * Selectors, named according to the ASN.1 names used throughout libcrypto. 16e1051a39Sopenharmony_ci * 17e1051a39Sopenharmony_ci * Note that these are not absolutely mandatory, they are rather a wishlist 18e1051a39Sopenharmony_ci * of sorts. The provider implementations are free to make choices that 19e1051a39Sopenharmony_ci * make sense for them, based on these selectors. 20e1051a39Sopenharmony_ci * For example, the EC backend is likely to really just output the private 21e1051a39Sopenharmony_ci * key to a PKCS#8 structure, even thought PEM_SELECTION_PrivateKey specifies 22e1051a39Sopenharmony_ci * the public key as well. This is fine, as long as the corresponding 23e1051a39Sopenharmony_ci * decoding operation can return an object that contains what libcrypto 24e1051a39Sopenharmony_ci * expects. 25e1051a39Sopenharmony_ci */ 26e1051a39Sopenharmony_ci# define PEM_SELECTION_PUBKEY EVP_PKEY_PUBLIC_KEY 27e1051a39Sopenharmony_ci# define PEM_SELECTION_PrivateKey EVP_PKEY_KEYPAIR 28e1051a39Sopenharmony_ci# define PEM_SELECTION_Parameters EVP_PKEY_KEY_PARAMETERS 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/* 31e1051a39Sopenharmony_ci * Properties, named according to the ASN.1 names used throughout libcrypto. 32e1051a39Sopenharmony_ci */ 33e1051a39Sopenharmony_ci# define PEM_STRUCTURE_PUBKEY "SubjectPublicKeyInfo" 34e1051a39Sopenharmony_ci# define PEM_STRUCTURE_PrivateKey "PrivateKeyInfo" 35e1051a39Sopenharmony_ci# define PEM_STRUCTURE_Parameters "type-specific" 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci# define PEM_STRUCTURE_RSAPrivateKey "type-specific" 38e1051a39Sopenharmony_ci# define PEM_STRUCTURE_RSAPublicKey "type-specific" 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci/* Alternative IMPLEMENT macros for provided encoders */ 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_body_vars(type, asn1, pq) \ 43e1051a39Sopenharmony_ci int ret = 0; \ 44e1051a39Sopenharmony_ci OSSL_ENCODER_CTX *ctx = \ 45e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_new_for_##type(x, PEM_SELECTION_##asn1, \ 46e1051a39Sopenharmony_ci "PEM", PEM_STRUCTURE_##asn1, \ 47e1051a39Sopenharmony_ci (pq)); \ 48e1051a39Sopenharmony_ci \ 49e1051a39Sopenharmony_ci if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) { \ 50e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_free(ctx); \ 51e1051a39Sopenharmony_ci goto legacy; \ 52e1051a39Sopenharmony_ci } 53e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_body_pass() \ 54e1051a39Sopenharmony_ci ret = 1; \ 55e1051a39Sopenharmony_ci if (kstr == NULL && cb == NULL) { \ 56e1051a39Sopenharmony_ci if (u != NULL) { \ 57e1051a39Sopenharmony_ci kstr = u; \ 58e1051a39Sopenharmony_ci klen = strlen(u); \ 59e1051a39Sopenharmony_ci } else { \ 60e1051a39Sopenharmony_ci cb = PEM_def_callback; \ 61e1051a39Sopenharmony_ci } \ 62e1051a39Sopenharmony_ci } \ 63e1051a39Sopenharmony_ci if (enc != NULL) { \ 64e1051a39Sopenharmony_ci ret = 0; \ 65e1051a39Sopenharmony_ci if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc), \ 66e1051a39Sopenharmony_ci NULL)) { \ 67e1051a39Sopenharmony_ci ret = 1; \ 68e1051a39Sopenharmony_ci if (kstr != NULL \ 69e1051a39Sopenharmony_ci && !OSSL_ENCODER_CTX_set_passphrase(ctx, kstr, klen)) \ 70e1051a39Sopenharmony_ci ret = 0; \ 71e1051a39Sopenharmony_ci else if (cb != NULL \ 72e1051a39Sopenharmony_ci && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, \ 73e1051a39Sopenharmony_ci cb, u)) \ 74e1051a39Sopenharmony_ci ret = 0; \ 75e1051a39Sopenharmony_ci } \ 76e1051a39Sopenharmony_ci } \ 77e1051a39Sopenharmony_ci if (!ret) { \ 78e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_free(ctx); \ 79e1051a39Sopenharmony_ci return 0; \ 80e1051a39Sopenharmony_ci } 81e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \ 82e1051a39Sopenharmony_ci ret = OSSL_ENCODER_to_##outtype(ctx, out); \ 83e1051a39Sopenharmony_ci OSSL_ENCODER_CTX_free(ctx); \ 84e1051a39Sopenharmony_ci return ret 85e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ 86e1051a39Sopenharmony_ci writename) \ 87e1051a39Sopenharmony_ci legacy: \ 88e1051a39Sopenharmony_ci return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \ 89e1051a39Sopenharmony_ci x, NULL, NULL, 0, NULL, NULL) 90e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \ 91e1051a39Sopenharmony_ci writename) \ 92e1051a39Sopenharmony_ci legacy: \ 93e1051a39Sopenharmony_ci return PEM_ASN1_##writename##((i2d_of_void *)i2d_##asn1, str, out, \ 94e1051a39Sopenharmony_ci x, enc, kstr, klen, cb, u) 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, \ 97e1051a39Sopenharmony_ci OUTTYPE, outtype, writename) \ 98e1051a39Sopenharmony_ci PEM_write_fnsig(name, TYPE, OUTTYPE, writename) \ 99e1051a39Sopenharmony_ci { \ 100e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \ 101e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ 102e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ 103e1051a39Sopenharmony_ci writename); \ 104e1051a39Sopenharmony_ci } \ 105e1051a39Sopenharmony_ci PEM_write_ex_fnsig(name, TYPE, OUTTYPE, writename) \ 106e1051a39Sopenharmony_ci { \ 107e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \ 108e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ 109e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ 110e1051a39Sopenharmony_ci writename); \ 111e1051a39Sopenharmony_ci } 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, \ 115e1051a39Sopenharmony_ci OUTTYPE, outtype, writename) \ 116e1051a39Sopenharmony_ci PEM_write_cb_fnsig(name, TYPE, OUTTYPE, writename) \ 117e1051a39Sopenharmony_ci { \ 118e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \ 119e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_pass(); \ 120e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ 121e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \ 122e1051a39Sopenharmony_ci writename); \ 123e1051a39Sopenharmony_ci } \ 124e1051a39Sopenharmony_ci PEM_write_ex_cb_fnsig(name, TYPE, OUTTYPE, writename) \ 125e1051a39Sopenharmony_ci { \ 126e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \ 127e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_pass(); \ 128e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_main(type, outtype); \ 129e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \ 130e1051a39Sopenharmony_ci writename); \ 131e1051a39Sopenharmony_ci } 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ci# ifdef OPENSSL_NO_STDIO 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) 136e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci# else 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) \ 141e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, FILE, fp, write) 142e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) \ 143e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, FILE, fp, write) 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci# endif 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \ 148e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, BIO, bio, write_bio) 149e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \ 150e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, BIO, bio, write_bio) 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1) \ 153e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \ 154e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1) \ 157e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \ 158e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_rw(name, TYPE, type, str, asn1) \ 161e1051a39Sopenharmony_ci IMPLEMENT_PEM_read(name, TYPE, str, asn1) \ 162e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1) 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci# define IMPLEMENT_PEM_provided_rw_cb(name, TYPE, type, str, asn1) \ 165e1051a39Sopenharmony_ci IMPLEMENT_PEM_read(name, TYPE, str, asn1) \ 166e1051a39Sopenharmony_ci IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1) 167e1051a39Sopenharmony_ci 168