1 /* 2 * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* 11 * Low level APIs are deprecated for public use, but still ok for internal use. 12 */ 13 #include "internal/deprecated.h" 14 15 #include <openssl/core.h> 16 #include <openssl/core_dispatch.h> 17 #include <openssl/core_names.h> 18 #include <openssl/params.h> 19 #include <openssl/err.h> 20 #include <openssl/evp.h> 21 #include <openssl/ec.h> 22 #include "internal/passphrase.h" 23 #include "internal/nelem.h" 24 #include "prov/implementations.h" 25 #include "prov/bio.h" 26 #include "prov/provider_ctx.h" 27 #include "endecoder_local.h" 28 29 static int write_blob(void *provctx, OSSL_CORE_BIO *cout, 30 void *data, int len) 31 { 32 BIO *out = ossl_bio_new_from_core_bio(provctx, cout); 33 int ret; 34 35 if (out == NULL) 36 return 0; 37 ret = BIO_write(out, data, len); 38 39 BIO_free(out); 40 return ret; 41 } 42 43 static OSSL_FUNC_encoder_newctx_fn key2blob_newctx; 44 static OSSL_FUNC_encoder_freectx_fn key2blob_freectx; 45 46 static void *key2blob_newctx(void *provctx) 47 { 48 return provctx; 49 } 50 51 static void key2blob_freectx(void *vctx) 52 { 53 } 54 55 static int key2blob_check_selection(int selection, int selection_mask) 56 { 57 /* 58 * The selections are kinda sorta "levels", i.e. each selection given 59 * here is assumed to include those following. 60 */ 61 int checks[] = { 62 OSSL_KEYMGMT_SELECT_PRIVATE_KEY, 63 OSSL_KEYMGMT_SELECT_PUBLIC_KEY, 64 OSSL_KEYMGMT_SELECT_ALL_PARAMETERS 65 }; 66 size_t i; 67 68 /* The decoder implementations made here support guessing */ 69 if (selection == 0) 70 return 1; 71 72 for (i = 0; i < OSSL_NELEM(checks); i++) { 73 int check1 = (selection & checks[i]) != 0; 74 int check2 = (selection_mask & checks[i]) != 0; 75 76 /* 77 * If the caller asked for the currently checked bit(s), return 78 * whether the decoder description says it's supported. 79 */ 80 if (check1) 81 return check2; 82 } 83 84 /* This should be dead code, but just to be safe... */ 85 return 0; 86 } 87 88 static int key2blob_encode(void *vctx, const void *key, int selection, 89 OSSL_CORE_BIO *cout) 90 { 91 int pubkey_len = 0, ok = 0; 92 unsigned char *pubkey = NULL; 93 94 pubkey_len = i2o_ECPublicKey(key, &pubkey); 95 if (pubkey_len > 0 && pubkey != NULL) 96 ok = write_blob(vctx, cout, pubkey, pubkey_len); 97 OPENSSL_free(pubkey); 98 return ok; 99 } 100 101 /* 102 * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob 103 * encoder 104 * 105 * impl: The keytype to encode 106 * type: The C structure type holding the key data 107 * selection_name: The acceptable selections. This translates into 108 * the macro EVP_PKEY_##selection_name. 109 * 110 * The selection is understood as a "level" rather than an exact set of 111 * requests from the caller. The encoder has to decide what contents fit 112 * the encoded format. For example, the EC public key blob will only contain 113 * the encoded public key itself, no matter if the selection bits include 114 * OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes 115 * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to 116 * cooperate, because it cannot output the private key. 117 * 118 * EVP_PKEY_##selection_name are convenience macros that combine "typical" 119 * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content. 120 */ 121 #define MAKE_BLOB_ENCODER(impl, type, selection_name) \ 122 static OSSL_FUNC_encoder_import_object_fn \ 123 impl##2blob_import_object; \ 124 static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \ 125 static OSSL_FUNC_encoder_does_selection_fn \ 126 impl##2blob_does_selection; \ 127 static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \ 128 \ 129 static void *impl##2blob_import_object(void *ctx, int selection, \ 130 const OSSL_PARAM params[]) \ 131 { \ 132 return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \ 133 ctx, selection, params); \ 134 } \ 135 static void impl##2blob_free_object(void *key) \ 136 { \ 137 ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \ 138 } \ 139 static int impl##2blob_does_selection(void *ctx, int selection) \ 140 { \ 141 return key2blob_check_selection(selection, \ 142 EVP_PKEY_##selection_name); \ 143 } \ 144 static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \ 145 const void *key, \ 146 const OSSL_PARAM key_abstract[], \ 147 int selection, \ 148 OSSL_PASSPHRASE_CALLBACK *cb, \ 149 void *cbarg) \ 150 { \ 151 /* We don't deal with abstract objects */ \ 152 if (key_abstract != NULL) { \ 153 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \ 154 return 0; \ 155 } \ 156 return key2blob_encode(vctx, key, selection, cout); \ 157 } \ 158 const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \ 159 { OSSL_FUNC_ENCODER_NEWCTX, \ 160 (void (*)(void))key2blob_newctx }, \ 161 { OSSL_FUNC_ENCODER_FREECTX, \ 162 (void (*)(void))key2blob_freectx }, \ 163 { OSSL_FUNC_ENCODER_DOES_SELECTION, \ 164 (void (*)(void))impl##2blob_does_selection }, \ 165 { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \ 166 (void (*)(void))impl##2blob_import_object }, \ 167 { OSSL_FUNC_ENCODER_FREE_OBJECT, \ 168 (void (*)(void))impl##2blob_free_object }, \ 169 { OSSL_FUNC_ENCODER_ENCODE, \ 170 (void (*)(void))impl##2blob_encode }, \ 171 { 0, NULL } \ 172 } 173 174 #ifndef OPENSSL_NO_EC 175 MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY); 176 # ifndef OPENSSL_NO_SM2 177 MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY); 178 # endif 179 #endif 180