2 * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
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
11 * Low level APIs are deprecated for public use, but still ok for internal use.
13 #include "internal/deprecated.h"
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"
26 #include "prov/provider_ctx.h"
27 #include "endecoder_local.h"
29 static int write_blob(void *provctx
, OSSL_CORE_BIO
*cout
,
32 BIO
*out
= ossl_bio_new_from_core_bio(provctx
, cout
);
37 ret
= BIO_write(out
, data
, len
);
43 static OSSL_FUNC_encoder_newctx_fn key2blob_newctx
;
44 static OSSL_FUNC_encoder_freectx_fn key2blob_freectx
;
46 static void *key2blob_newctx(void *provctx
)
51 static void key2blob_freectx(void *vctx
)
55 static int key2blob_check_selection(int selection
, int selection_mask
)
58 * The selections are kinda sorta "levels", i.e. each selection given
59 * here is assumed to include those following.
62 OSSL_KEYMGMT_SELECT_PRIVATE_KEY
,
63 OSSL_KEYMGMT_SELECT_PUBLIC_KEY
,
64 OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
68 /* The decoder implementations made here support guessing */
72 for (i
= 0; i
< OSSL_NELEM(checks
); i
++) {
73 int check1
= (selection
& checks
[i
]) != 0;
74 int check2
= (selection_mask
& checks
[i
]) != 0;
77 * If the caller asked for the currently checked bit(s), return
78 * whether the decoder description says it's supported.
84 /* This should be dead code, but just to be safe... */
88 static int key2blob_encode(void *vctx
, const void *key
, int selection
,
91 int pubkey_len
= 0, ok
= 0;
92 unsigned char *pubkey
= NULL
;
94 pubkey_len
= i2o_ECPublicKey(key
, &pubkey
);
95 if (pubkey_len
> 0 && pubkey
!= NULL
)
96 ok
= write_blob(vctx
, cout
, pubkey
, pubkey_len
);
102 * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
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.
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.
118 * EVP_PKEY_##selection_name are convenience macros that combine "typical"
119 * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
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; \
129 static void *impl##2blob_import_object(void *ctx, int selection, \
130 const OSSL_PARAM params[]) \
132 return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
133 ctx, selection, params); \
135 static void impl##2blob_free_object(void *key) \
137 ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
139 static int impl##2blob_does_selection(void *ctx, int selection) \
141 return key2blob_check_selection(selection, \
142 EVP_PKEY_##selection_name); \
144 static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \
146 const OSSL_PARAM key_abstract[], \
148 OSSL_PASSPHRASE_CALLBACK *cb, \
151 /* We don't deal with abstract objects */ \
152 if (key_abstract != NULL) { \
153 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
156 return key2blob_encode(vctx, key, selection, cout); \
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 }, \
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
);