1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2020-2022 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/* 11e1051a39Sopenharmony_ci * RSA low level APIs are deprecated for public use, but still ok for 12e1051a39Sopenharmony_ci * internal use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <string.h> 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h> 19e1051a39Sopenharmony_ci#include <openssl/core_names.h> 20e1051a39Sopenharmony_ci#include <openssl/core_object.h> 21e1051a39Sopenharmony_ci#include <openssl/crypto.h> 22e1051a39Sopenharmony_ci#include <openssl/err.h> 23e1051a39Sopenharmony_ci#include <openssl/params.h> 24e1051a39Sopenharmony_ci#include <openssl/pem.h> 25e1051a39Sopenharmony_ci#include <openssl/proverr.h> 26e1051a39Sopenharmony_ci#include "internal/nelem.h" 27e1051a39Sopenharmony_ci#include "prov/bio.h" 28e1051a39Sopenharmony_ci#include "prov/implementations.h" 29e1051a39Sopenharmony_ci#include "endecoder_local.h" 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_cistatic int read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin, 32e1051a39Sopenharmony_ci char **pem_name, char **pem_header, 33e1051a39Sopenharmony_ci unsigned char **data, long *len) 34e1051a39Sopenharmony_ci{ 35e1051a39Sopenharmony_ci BIO *in = ossl_bio_new_from_core_bio(provctx, cin); 36e1051a39Sopenharmony_ci int ok; 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_ci if (in == NULL) 39e1051a39Sopenharmony_ci return 0; 40e1051a39Sopenharmony_ci ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0); 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci BIO_free(in); 43e1051a39Sopenharmony_ci return ok; 44e1051a39Sopenharmony_ci} 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_cistatic OSSL_FUNC_decoder_newctx_fn pem2der_newctx; 47e1051a39Sopenharmony_cistatic OSSL_FUNC_decoder_freectx_fn pem2der_freectx; 48e1051a39Sopenharmony_cistatic OSSL_FUNC_decoder_decode_fn pem2der_decode; 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci/* 51e1051a39Sopenharmony_ci * Context used for PEM to DER decoding. 52e1051a39Sopenharmony_ci */ 53e1051a39Sopenharmony_cistruct pem2der_ctx_st { 54e1051a39Sopenharmony_ci PROV_CTX *provctx; 55e1051a39Sopenharmony_ci}; 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_cistatic void *pem2der_newctx(void *provctx) 58e1051a39Sopenharmony_ci{ 59e1051a39Sopenharmony_ci struct pem2der_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci if (ctx != NULL) 62e1051a39Sopenharmony_ci ctx->provctx = provctx; 63e1051a39Sopenharmony_ci return ctx; 64e1051a39Sopenharmony_ci} 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_cistatic void pem2der_freectx(void *vctx) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci struct pem2der_ctx_st *ctx = vctx; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci OPENSSL_free(ctx); 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci/* pem_password_cb compatible function */ 74e1051a39Sopenharmony_cistruct pem2der_pass_data_st { 75e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb; 76e1051a39Sopenharmony_ci void *cbarg; 77e1051a39Sopenharmony_ci}; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_cistatic int pem2der_pass_helper(char *buf, int num, int w, void *data) 80e1051a39Sopenharmony_ci{ 81e1051a39Sopenharmony_ci struct pem2der_pass_data_st *pass_data = data; 82e1051a39Sopenharmony_ci size_t plen; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (pass_data == NULL 85e1051a39Sopenharmony_ci || pass_data->cb == NULL 86e1051a39Sopenharmony_ci || !pass_data->cb(buf, num, &plen, NULL, pass_data->cbarg)) 87e1051a39Sopenharmony_ci return -1; 88e1051a39Sopenharmony_ci return (int)plen; 89e1051a39Sopenharmony_ci} 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci/* 92e1051a39Sopenharmony_ci * The selection parameter in pem2der_decode() is not used by this function 93e1051a39Sopenharmony_ci * because it's not relevant just to decode PEM to DER. 94e1051a39Sopenharmony_ci */ 95e1051a39Sopenharmony_cistatic int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, 96e1051a39Sopenharmony_ci OSSL_CALLBACK *data_cb, void *data_cbarg, 97e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 98e1051a39Sopenharmony_ci{ 99e1051a39Sopenharmony_ci /* 100e1051a39Sopenharmony_ci * PEM names we recognise. Other PEM names should be recognised by 101e1051a39Sopenharmony_ci * other decoder implementations. 102e1051a39Sopenharmony_ci */ 103e1051a39Sopenharmony_ci static struct pem_name_map_st { 104e1051a39Sopenharmony_ci const char *pem_name; 105e1051a39Sopenharmony_ci int object_type; 106e1051a39Sopenharmony_ci const char *data_type; 107e1051a39Sopenharmony_ci const char *data_structure; 108e1051a39Sopenharmony_ci } pem_name_map[] = { 109e1051a39Sopenharmony_ci /* PKCS#8 and SubjectPublicKeyInfo */ 110e1051a39Sopenharmony_ci { PEM_STRING_PKCS8, OSSL_OBJECT_PKEY, NULL, "EncryptedPrivateKeyInfo" }, 111e1051a39Sopenharmony_ci { PEM_STRING_PKCS8INF, OSSL_OBJECT_PKEY, NULL, "PrivateKeyInfo" }, 112e1051a39Sopenharmony_ci { PEM_STRING_PUBLIC, OSSL_OBJECT_PKEY, NULL, "SubjectPublicKeyInfo" }, 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci /* Our set of type specific PEM types */ 115e1051a39Sopenharmony_ci { PEM_STRING_DHPARAMS, OSSL_OBJECT_PKEY, "DH", "type-specific" }, 116e1051a39Sopenharmony_ci { PEM_STRING_DHXPARAMS, OSSL_OBJECT_PKEY, "X9.42 DH", "type-specific" }, 117e1051a39Sopenharmony_ci { PEM_STRING_DSA, OSSL_OBJECT_PKEY, "DSA", "type-specific" }, 118e1051a39Sopenharmony_ci { PEM_STRING_DSA_PUBLIC, OSSL_OBJECT_PKEY, "DSA", "type-specific" }, 119e1051a39Sopenharmony_ci { PEM_STRING_DSAPARAMS, OSSL_OBJECT_PKEY, "DSA", "type-specific" }, 120e1051a39Sopenharmony_ci { PEM_STRING_ECPRIVATEKEY, OSSL_OBJECT_PKEY, "EC", "type-specific" }, 121e1051a39Sopenharmony_ci { PEM_STRING_ECPARAMETERS, OSSL_OBJECT_PKEY, "EC", "type-specific" }, 122e1051a39Sopenharmony_ci { PEM_STRING_RSA, OSSL_OBJECT_PKEY, "RSA", "type-specific" }, 123e1051a39Sopenharmony_ci { PEM_STRING_RSA_PUBLIC, OSSL_OBJECT_PKEY, "RSA", "type-specific" }, 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci /* 126e1051a39Sopenharmony_ci * A few others that there is at least have an object type for, even 127e1051a39Sopenharmony_ci * though there is no provider interface to handle such objects, yet. 128e1051a39Sopenharmony_ci * However, this is beneficial for the OSSL_STORE result handler. 129e1051a39Sopenharmony_ci */ 130e1051a39Sopenharmony_ci { PEM_STRING_X509, OSSL_OBJECT_CERT, NULL, "Certificate" }, 131e1051a39Sopenharmony_ci { PEM_STRING_X509_TRUSTED, OSSL_OBJECT_CERT, NULL, "Certificate" }, 132e1051a39Sopenharmony_ci { PEM_STRING_X509_OLD, OSSL_OBJECT_CERT, NULL, "Certificate" }, 133e1051a39Sopenharmony_ci { PEM_STRING_X509_CRL, OSSL_OBJECT_CRL, NULL, "CertificateList" } 134e1051a39Sopenharmony_ci }; 135e1051a39Sopenharmony_ci struct pem2der_ctx_st *ctx = vctx; 136e1051a39Sopenharmony_ci char *pem_name = NULL, *pem_header = NULL; 137e1051a39Sopenharmony_ci size_t i; 138e1051a39Sopenharmony_ci unsigned char *der = NULL; 139e1051a39Sopenharmony_ci long der_len = 0; 140e1051a39Sopenharmony_ci int ok = 0; 141e1051a39Sopenharmony_ci int objtype = OSSL_OBJECT_UNKNOWN; 142e1051a39Sopenharmony_ci 143e1051a39Sopenharmony_ci ok = read_pem(ctx->provctx, cin, &pem_name, &pem_header, 144e1051a39Sopenharmony_ci &der, &der_len) > 0; 145e1051a39Sopenharmony_ci /* We return "empty handed". This is not an error. */ 146e1051a39Sopenharmony_ci if (!ok) 147e1051a39Sopenharmony_ci return 1; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci /* 150e1051a39Sopenharmony_ci * 10 is the number of characters in "Proc-Type:", which 151e1051a39Sopenharmony_ci * PEM_get_EVP_CIPHER_INFO() requires to be present. 152e1051a39Sopenharmony_ci * If the PEM header has less characters than that, it's 153e1051a39Sopenharmony_ci * not worth spending cycles on it. 154e1051a39Sopenharmony_ci */ 155e1051a39Sopenharmony_ci if (strlen(pem_header) > 10) { 156e1051a39Sopenharmony_ci EVP_CIPHER_INFO cipher; 157e1051a39Sopenharmony_ci struct pem2der_pass_data_st pass_data; 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci ok = 0; /* Assume that we fail */ 160e1051a39Sopenharmony_ci pass_data.cb = pw_cb; 161e1051a39Sopenharmony_ci pass_data.cbarg = pw_cbarg; 162e1051a39Sopenharmony_ci if (!PEM_get_EVP_CIPHER_INFO(pem_header, &cipher) 163e1051a39Sopenharmony_ci || !PEM_do_header(&cipher, der, &der_len, 164e1051a39Sopenharmony_ci pem2der_pass_helper, &pass_data)) 165e1051a39Sopenharmony_ci goto end; 166e1051a39Sopenharmony_ci } 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci /* 169e1051a39Sopenharmony_ci * Indicated that we successfully decoded something, or not at all. 170e1051a39Sopenharmony_ci * Ending up "empty handed" is not an error. 171e1051a39Sopenharmony_ci */ 172e1051a39Sopenharmony_ci ok = 1; 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ci /* Have a look to see if we recognise anything */ 175e1051a39Sopenharmony_ci for (i = 0; i < OSSL_NELEM(pem_name_map); i++) 176e1051a39Sopenharmony_ci if (strcmp(pem_name, pem_name_map[i].pem_name) == 0) 177e1051a39Sopenharmony_ci break; 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci if (i < OSSL_NELEM(pem_name_map)) { 180e1051a39Sopenharmony_ci OSSL_PARAM params[5], *p = params; 181e1051a39Sopenharmony_ci /* We expect these to be read only so casting away the const is ok */ 182e1051a39Sopenharmony_ci char *data_type = (char *)pem_name_map[i].data_type; 183e1051a39Sopenharmony_ci char *data_structure = (char *)pem_name_map[i].data_structure; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci objtype = pem_name_map[i].object_type; 186e1051a39Sopenharmony_ci if (data_type != NULL) 187e1051a39Sopenharmony_ci *p++ = 188e1051a39Sopenharmony_ci OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, 189e1051a39Sopenharmony_ci data_type, 0); 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci /* We expect this to be read only so casting away the const is ok */ 192e1051a39Sopenharmony_ci if (data_structure != NULL) 193e1051a39Sopenharmony_ci *p++ = 194e1051a39Sopenharmony_ci OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, 195e1051a39Sopenharmony_ci data_structure, 0); 196e1051a39Sopenharmony_ci *p++ = 197e1051a39Sopenharmony_ci OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, 198e1051a39Sopenharmony_ci der, der_len); 199e1051a39Sopenharmony_ci *p++ = 200e1051a39Sopenharmony_ci OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci *p = OSSL_PARAM_construct_end(); 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci ok = data_cb(params, data_cbarg); 205e1051a39Sopenharmony_ci } 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci end: 208e1051a39Sopenharmony_ci OPENSSL_free(pem_name); 209e1051a39Sopenharmony_ci OPENSSL_free(pem_header); 210e1051a39Sopenharmony_ci OPENSSL_free(der); 211e1051a39Sopenharmony_ci return ok; 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_pem_to_der_decoder_functions[] = { 215e1051a39Sopenharmony_ci { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))pem2der_newctx }, 216e1051a39Sopenharmony_ci { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))pem2der_freectx }, 217e1051a39Sopenharmony_ci { OSSL_FUNC_DECODER_DECODE, (void (*)(void))pem2der_decode }, 218e1051a39Sopenharmony_ci { 0, NULL } 219e1051a39Sopenharmony_ci}; 220