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 * Low level APIs are deprecated for public use, but still ok for internal use. 12e1051a39Sopenharmony_ci */ 13e1051a39Sopenharmony_ci#include "internal/deprecated.h" 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci#include <string.h> 16e1051a39Sopenharmony_ci#include <openssl/core.h> 17e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h> 18e1051a39Sopenharmony_ci#include <openssl/core_names.h> 19e1051a39Sopenharmony_ci#include <openssl/params.h> 20e1051a39Sopenharmony_ci#include <openssl/err.h> 21e1051a39Sopenharmony_ci#include <openssl/pem.h> /* Functions for writing MSBLOB and PVK */ 22e1051a39Sopenharmony_ci#include <openssl/dsa.h> 23e1051a39Sopenharmony_ci#include "internal/passphrase.h" 24e1051a39Sopenharmony_ci#include "crypto/rsa.h" 25e1051a39Sopenharmony_ci#include "prov/implementations.h" 26e1051a39Sopenharmony_ci#include "prov/bio.h" 27e1051a39Sopenharmony_ci#include "prov/provider_ctx.h" 28e1051a39Sopenharmony_ci#include "endecoder_local.h" 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_cistruct key2ms_ctx_st { 31e1051a39Sopenharmony_ci PROV_CTX *provctx; 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_ci int pvk_encr_level; 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci struct ossl_passphrase_data_st pwdata; 36e1051a39Sopenharmony_ci}; 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_cistatic int write_msblob(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout, 39e1051a39Sopenharmony_ci EVP_PKEY *pkey, int ispub) 40e1051a39Sopenharmony_ci{ 41e1051a39Sopenharmony_ci BIO *out = ossl_bio_new_from_core_bio(ctx->provctx, cout); 42e1051a39Sopenharmony_ci int ret; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci if (out == NULL) 45e1051a39Sopenharmony_ci return 0; 46e1051a39Sopenharmony_ci ret = ispub ? i2b_PublicKey_bio(out, pkey) : i2b_PrivateKey_bio(out, pkey); 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci BIO_free(out); 49e1051a39Sopenharmony_ci return ret; 50e1051a39Sopenharmony_ci} 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_cistatic int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout, 53e1051a39Sopenharmony_ci EVP_PKEY *pkey) 54e1051a39Sopenharmony_ci{ 55e1051a39Sopenharmony_ci BIO *out = NULL; 56e1051a39Sopenharmony_ci int ret; 57e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci out = ossl_bio_new_from_core_bio(ctx->provctx, cout); 60e1051a39Sopenharmony_ci if (out == NULL) 61e1051a39Sopenharmony_ci return 0; 62e1051a39Sopenharmony_ci ret = i2b_PVK_bio_ex(out, pkey, ctx->pvk_encr_level, 63e1051a39Sopenharmony_ci ossl_pw_pvk_password, &ctx->pwdata, libctx, NULL); 64e1051a39Sopenharmony_ci BIO_free(out); 65e1051a39Sopenharmony_ci return ret; 66e1051a39Sopenharmony_ci} 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_cistatic OSSL_FUNC_encoder_freectx_fn key2ms_freectx; 69e1051a39Sopenharmony_cistatic OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_cistatic struct key2ms_ctx_st *key2ms_newctx(void *provctx) 72e1051a39Sopenharmony_ci{ 73e1051a39Sopenharmony_ci struct key2ms_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci if (ctx != NULL) { 76e1051a39Sopenharmony_ci ctx->provctx = provctx; 77e1051a39Sopenharmony_ci /* This is the strongest encryption level */ 78e1051a39Sopenharmony_ci ctx->pvk_encr_level = 2; 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci return ctx; 81e1051a39Sopenharmony_ci} 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_cistatic void key2ms_freectx(void *vctx) 84e1051a39Sopenharmony_ci{ 85e1051a39Sopenharmony_ci struct key2ms_ctx_st *ctx = vctx; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci ossl_pw_clear_passphrase_data(&ctx->pwdata); 88e1051a39Sopenharmony_ci OPENSSL_free(ctx); 89e1051a39Sopenharmony_ci} 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_cistatic const OSSL_PARAM *key2pvk_settable_ctx_params(ossl_unused void *provctx) 92e1051a39Sopenharmony_ci{ 93e1051a39Sopenharmony_ci static const OSSL_PARAM settables[] = { 94e1051a39Sopenharmony_ci OSSL_PARAM_int(OSSL_ENCODER_PARAM_ENCRYPT_LEVEL, NULL), 95e1051a39Sopenharmony_ci OSSL_PARAM_END, 96e1051a39Sopenharmony_ci }; 97e1051a39Sopenharmony_ci 98e1051a39Sopenharmony_ci return settables; 99e1051a39Sopenharmony_ci} 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_cistatic int key2pvk_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 102e1051a39Sopenharmony_ci{ 103e1051a39Sopenharmony_ci struct key2ms_ctx_st *ctx = vctx; 104e1051a39Sopenharmony_ci const OSSL_PARAM *p; 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_ENCRYPT_LEVEL); 107e1051a39Sopenharmony_ci if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->pvk_encr_level)) 108e1051a39Sopenharmony_ci return 0; 109e1051a39Sopenharmony_ci return 1; 110e1051a39Sopenharmony_ci} 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_cistatic int key2ms_does_selection(void *vctx, int selection) 113e1051a39Sopenharmony_ci{ 114e1051a39Sopenharmony_ci return (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0; 115e1051a39Sopenharmony_ci} 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci/* 118e1051a39Sopenharmony_ci * The real EVP_PKEY_set1_TYPE() functions take a non-const key, while the key 119e1051a39Sopenharmony_ci * pointer in the encode function is a const pointer. We violate the constness 120e1051a39Sopenharmony_ci * knowingly, since we know that the key comes from the same provider, is never 121e1051a39Sopenharmony_ci * actually const, and the implied reference count change is safe. 122e1051a39Sopenharmony_ci * 123e1051a39Sopenharmony_ci * EVP_PKEY_assign() can't be used, because there's no way to clear the internal 124e1051a39Sopenharmony_ci * key using that function without freeing the existing internal key. 125e1051a39Sopenharmony_ci */ 126e1051a39Sopenharmony_citypedef int evp_pkey_set1_fn(EVP_PKEY *, const void *key); 127e1051a39Sopenharmony_ci 128e1051a39Sopenharmony_cistatic int key2msblob_encode(void *vctx, const void *key, int selection, 129e1051a39Sopenharmony_ci OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key, 130e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 131e1051a39Sopenharmony_ci{ 132e1051a39Sopenharmony_ci struct key2ms_ctx_st *ctx = vctx; 133e1051a39Sopenharmony_ci int ispub = -1; 134e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 135e1051a39Sopenharmony_ci int ok = 0; 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 138e1051a39Sopenharmony_ci ispub = 0; 139e1051a39Sopenharmony_ci else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 140e1051a39Sopenharmony_ci ispub = 1; 141e1051a39Sopenharmony_ci else 142e1051a39Sopenharmony_ci return 0; /* Error */ 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key)) 145e1051a39Sopenharmony_ci ok = write_msblob(ctx, cout, pkey, ispub); 146e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 147e1051a39Sopenharmony_ci return ok; 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_cistatic int key2pvk_encode(void *vctx, const void *key, int selection, 151e1051a39Sopenharmony_ci OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key, 152e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci struct key2ms_ctx_st *ctx = vctx; 155e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 156e1051a39Sopenharmony_ci int ok = 0; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0) 159e1051a39Sopenharmony_ci return 0; /* Error */ 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ci if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key) 162e1051a39Sopenharmony_ci && (pw_cb == NULL 163e1051a39Sopenharmony_ci || ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, pw_cb, pw_cbarg))) 164e1051a39Sopenharmony_ci ok = write_pvk(ctx, cout, pkey); 165e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 166e1051a39Sopenharmony_ci return ok; 167e1051a39Sopenharmony_ci} 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ci#define dsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_DSA 170e1051a39Sopenharmony_ci#define rsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_RSA 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci#define msblob_set_params 173e1051a39Sopenharmony_ci#define pvk_set_params \ 174e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \ 175e1051a39Sopenharmony_ci (void (*)(void))key2pvk_settable_ctx_params }, \ 176e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \ 177e1051a39Sopenharmony_ci (void (*)(void))key2pvk_set_ctx_params }, 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci#define MAKE_MS_ENCODER(impl, output, type) \ 180e1051a39Sopenharmony_ci static OSSL_FUNC_encoder_import_object_fn \ 181e1051a39Sopenharmony_ci impl##2##output##_import_object; \ 182e1051a39Sopenharmony_ci static OSSL_FUNC_encoder_free_object_fn impl##2##output##_free_object; \ 183e1051a39Sopenharmony_ci static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \ 184e1051a39Sopenharmony_ci \ 185e1051a39Sopenharmony_ci static void * \ 186e1051a39Sopenharmony_ci impl##2##output##_import_object(void *ctx, int selection, \ 187e1051a39Sopenharmony_ci const OSSL_PARAM params[]) \ 188e1051a39Sopenharmony_ci { \ 189e1051a39Sopenharmony_ci return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \ 190e1051a39Sopenharmony_ci ctx, selection, params); \ 191e1051a39Sopenharmony_ci } \ 192e1051a39Sopenharmony_ci static void impl##2##output##_free_object(void *key) \ 193e1051a39Sopenharmony_ci { \ 194e1051a39Sopenharmony_ci ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \ 195e1051a39Sopenharmony_ci } \ 196e1051a39Sopenharmony_ci static int impl##2##output##_encode(void *vctx, OSSL_CORE_BIO *cout, \ 197e1051a39Sopenharmony_ci const void *key, \ 198e1051a39Sopenharmony_ci const OSSL_PARAM key_abstract[], \ 199e1051a39Sopenharmony_ci int selection, \ 200e1051a39Sopenharmony_ci OSSL_PASSPHRASE_CALLBACK *cb, \ 201e1051a39Sopenharmony_ci void *cbarg) \ 202e1051a39Sopenharmony_ci { \ 203e1051a39Sopenharmony_ci /* We don't deal with abstract objects */ \ 204e1051a39Sopenharmony_ci if (key_abstract != NULL) { \ 205e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \ 206e1051a39Sopenharmony_ci return 0; \ 207e1051a39Sopenharmony_ci } \ 208e1051a39Sopenharmony_ci return key2##output##_encode(vctx, key, selection, cout, type##_set1, \ 209e1051a39Sopenharmony_ci cb, cbarg); \ 210e1051a39Sopenharmony_ci } \ 211e1051a39Sopenharmony_ci const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \ 212e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_NEWCTX, \ 213e1051a39Sopenharmony_ci (void (*)(void))key2ms_newctx }, \ 214e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_FREECTX, \ 215e1051a39Sopenharmony_ci (void (*)(void))key2ms_freectx }, \ 216e1051a39Sopenharmony_ci output##_set_params \ 217e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_DOES_SELECTION, \ 218e1051a39Sopenharmony_ci (void (*)(void))key2ms_does_selection }, \ 219e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \ 220e1051a39Sopenharmony_ci (void (*)(void))impl##2##output##_import_object }, \ 221e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_FREE_OBJECT, \ 222e1051a39Sopenharmony_ci (void (*)(void))impl##2##output##_free_object }, \ 223e1051a39Sopenharmony_ci { OSSL_FUNC_ENCODER_ENCODE, \ 224e1051a39Sopenharmony_ci (void (*)(void))impl##2##output##_encode }, \ 225e1051a39Sopenharmony_ci { 0, NULL } \ 226e1051a39Sopenharmony_ci } 227e1051a39Sopenharmony_ci 228e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 229e1051a39Sopenharmony_ciMAKE_MS_ENCODER(dsa, pvk, dsa); 230e1051a39Sopenharmony_ciMAKE_MS_ENCODER(dsa, msblob, dsa); 231e1051a39Sopenharmony_ci#endif 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ciMAKE_MS_ENCODER(rsa, pvk, rsa); 234e1051a39Sopenharmony_ciMAKE_MS_ENCODER(rsa, msblob, rsa); 235