|  | /* | 
|  | * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. | 
|  | * | 
|  | * Licensed under the Apache License 2.0 (the "License").  You may not use | 
|  | * this file except in compliance with the License.  You can obtain a copy | 
|  | * in the file LICENSE in the source distribution or at | 
|  | * https://www.openssl.org/source/license.html | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * RSA low level APIs are deprecated for public use, but still ok for | 
|  | * internal use. | 
|  | */ | 
|  | #include "internal/deprecated.h" | 
|  |  | 
|  | #include <openssl/core_dispatch.h> | 
|  | #include <openssl/core_names.h> | 
|  | #include <openssl/crypto.h> | 
|  | #include <openssl/params.h> | 
|  | #include <openssl/x509.h> | 
|  | #include "prov/bio.h" | 
|  | #include "prov/implementations.h" | 
|  | #include "serializer_local.h" | 
|  |  | 
|  | static OSSL_FUNC_deserializer_newctx_fn der2rsa_newctx; | 
|  | static OSSL_FUNC_deserializer_freectx_fn der2rsa_freectx; | 
|  | static OSSL_FUNC_deserializer_gettable_params_fn der2rsa_gettable_params; | 
|  | static OSSL_FUNC_deserializer_get_params_fn der2rsa_get_params; | 
|  | static OSSL_FUNC_deserializer_deserialize_fn der2rsa_deserialize; | 
|  | static OSSL_FUNC_deserializer_export_object_fn der2rsa_export_object; | 
|  |  | 
|  | /* | 
|  | * Context used for DER to RSA key deserialization. | 
|  | */ | 
|  | struct der2rsa_ctx_st { | 
|  | PROV_CTX *provctx; | 
|  |  | 
|  | #if 0 | 
|  | struct pkcs8_encrypt_ctx_st sc; | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | static void *der2rsa_newctx(void *provctx) | 
|  | { | 
|  | struct der2rsa_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); | 
|  |  | 
|  | if (ctx != NULL) { | 
|  | ctx->provctx = provctx; | 
|  | } | 
|  | return ctx; | 
|  | } | 
|  |  | 
|  | static void der2rsa_freectx(void *vctx) | 
|  | { | 
|  | struct der2rsa_ctx_st *ctx = vctx; | 
|  |  | 
|  | OPENSSL_free(ctx); | 
|  | } | 
|  |  | 
|  | static const OSSL_PARAM *der2rsa_gettable_params(void) | 
|  | { | 
|  | static const OSSL_PARAM gettables[] = { | 
|  | { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 }, | 
|  | OSSL_PARAM_END, | 
|  | }; | 
|  |  | 
|  | return gettables; | 
|  | } | 
|  |  | 
|  | static int der2rsa_get_params(OSSL_PARAM params[]) | 
|  | { | 
|  | OSSL_PARAM *p; | 
|  |  | 
|  | p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE); | 
|  | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "DER")) | 
|  | return 0; | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static int der2rsa_deserialize(void *vctx, OSSL_CORE_BIO *cin, | 
|  | OSSL_CALLBACK *data_cb, void *data_cbarg, | 
|  | OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) | 
|  | { | 
|  | struct der2rsa_ctx_st *ctx = vctx; | 
|  | void *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); | 
|  | RSA *rsa = NULL; | 
|  | unsigned char *der = NULL; | 
|  | const unsigned char *derp; | 
|  | long der_len = 0; | 
|  | EVP_PKEY *pkey = NULL; | 
|  | int ok = 0; | 
|  |  | 
|  | if (!ossl_prov_read_der(ctx->provctx, cin, &der, &der_len)) | 
|  | return 0; | 
|  |  | 
|  | derp = der; | 
|  | #if 0                            /* PKCS#8 decryption coming soon */ | 
|  | X509_SIG *p8 = NULL; | 
|  | if ((p8 = d2i_X509_SIG(NULL, &derp, der_len)) != NULL) { | 
|  | const X509_ALGOR *dalg = NULL; | 
|  | const ASN1_OCTET_STRING *doct = NULL; | 
|  | unsigned char *new_data = NULL; | 
|  | int new_data_len; | 
|  |  | 
|  | /* passphrase fetching code TBA */ | 
|  | X509_SIG_get0(p8, &dalg, &doct); | 
|  | if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), | 
|  | doct->data, doct->length, | 
|  | &new_data, &new_data_len, 0)) | 
|  | goto nop8; | 
|  | OPENSSL_free(der); | 
|  | der = new_data; | 
|  | der_len = new_data_len; | 
|  | } | 
|  | X509_SIG_free(p8); | 
|  | nop8: | 
|  | #endif | 
|  |  | 
|  | derp = der; | 
|  | if ((pkey = d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &derp, der_len, | 
|  | libctx, NULL)) != NULL) { | 
|  | /* Tear out the RSA pointer from the pkey */ | 
|  | rsa = EVP_PKEY_get1_RSA(pkey); | 
|  | EVP_PKEY_free(pkey); | 
|  | } | 
|  |  | 
|  | OPENSSL_free(der); | 
|  |  | 
|  | if (rsa != NULL) { | 
|  | OSSL_PARAM params[3]; | 
|  |  | 
|  | params[0] = | 
|  | OSSL_PARAM_construct_utf8_string(OSSL_DESERIALIZER_PARAM_DATA_TYPE, | 
|  | "RSA", 0); | 
|  | /* The address of the key becomes the octet string */ | 
|  | params[1] = | 
|  | OSSL_PARAM_construct_octet_string(OSSL_DESERIALIZER_PARAM_REFERENCE, | 
|  | &rsa, sizeof(rsa)); | 
|  | params[2] = OSSL_PARAM_construct_end(); | 
|  |  | 
|  | ok = data_cb(params, data_cbarg); | 
|  | } | 
|  | RSA_free(rsa); | 
|  |  | 
|  | return ok; | 
|  | } | 
|  |  | 
|  | static int der2rsa_export_object(void *vctx, | 
|  | const void *reference, size_t reference_sz, | 
|  | OSSL_CALLBACK *export_cb, void *export_cbarg) | 
|  | { | 
|  | OSSL_FUNC_keymgmt_export_fn *rsa_export = | 
|  | ossl_prov_get_keymgmt_rsa_export(); | 
|  | void *keydata; | 
|  |  | 
|  | if (reference_sz == sizeof(keydata) && rsa_export != NULL) { | 
|  | /* The contents of the reference is the address to our object */ | 
|  | keydata = *(RSA **)reference; | 
|  |  | 
|  | return rsa_export(keydata, OSSL_KEYMGMT_SELECT_ALL, | 
|  | export_cb, export_cbarg); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | const OSSL_DISPATCH der_to_rsa_deserializer_functions[] = { | 
|  | { OSSL_FUNC_DESERIALIZER_NEWCTX, (void (*)(void))der2rsa_newctx }, | 
|  | { OSSL_FUNC_DESERIALIZER_FREECTX, (void (*)(void))der2rsa_freectx }, | 
|  | { OSSL_FUNC_DESERIALIZER_GETTABLE_PARAMS, | 
|  | (void (*)(void))der2rsa_gettable_params }, | 
|  | { OSSL_FUNC_DESERIALIZER_GET_PARAMS, | 
|  | (void (*)(void))der2rsa_get_params }, | 
|  | { OSSL_FUNC_DESERIALIZER_DESERIALIZE, | 
|  | (void (*)(void))der2rsa_deserialize }, | 
|  | { OSSL_FUNC_DESERIALIZER_EXPORT_OBJECT, | 
|  | (void (*)(void))der2rsa_export_object }, | 
|  | { 0, NULL } | 
|  | }; |