]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/encode_decode/encode_key2blob.c
PROV: drop get_params() and gettable_params() from all encoder implementatio
[thirdparty/openssl.git] / providers / implementations / encode_decode / encode_key2blob.c
1 /*
2 * Copyright 2021 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 = BIO_write(out, data, len);
34
35 BIO_free(out);
36 return ret;
37 }
38
39 static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
40 static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
41
42 static void *key2blob_newctx(void *provctx)
43 {
44 return provctx;
45 }
46
47 static void key2blob_freectx(void *vctx)
48 {
49 }
50
51 static int key2blob_check_selection(int selection, int selection_mask)
52 {
53 /*
54 * The selections are kinda sorta "levels", i.e. each selection given
55 * here is assumed to include those following.
56 */
57 int checks[] = {
58 OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
59 OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
60 OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
61 };
62 size_t i;
63
64 /* The decoder implementations made here support guessing */
65 if (selection == 0)
66 return 1;
67
68 for (i = 0; i < OSSL_NELEM(checks); i++) {
69 int check1 = (selection & checks[i]) != 0;
70 int check2 = (selection_mask & checks[i]) != 0;
71
72 /*
73 * If the caller asked for the currently checked bit(s), return
74 * whether the decoder description says it's supported.
75 */
76 if (check1)
77 return check2;
78 }
79
80 /* This should be dead code, but just to be safe... */
81 return 0;
82 }
83
84 static int key2blob_encode(void *vctx, const void *key, int selection,
85 OSSL_CORE_BIO *cout)
86 {
87 int pubkey_len = 0, ok = 0;
88 unsigned char *pubkey = NULL;
89
90 pubkey_len = i2o_ECPublicKey(key, &pubkey);
91 if (pubkey_len > 0 && pubkey != NULL)
92 ok = write_blob(vctx, cout, pubkey, pubkey_len);
93 OPENSSL_free(pubkey);
94 return ok;
95 }
96
97 /*
98 * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
99 * encoder
100 *
101 * impl: The keytype to encode
102 * type: The C structure type holding the key data
103 * selection_name: The acceptable selections. This translates into
104 * the macro EVP_PKEY_##selection_name.
105 *
106 * The selection is understood as a "level" rather than an exact set of
107 * requests from the caller. The encoder has to decide what contents fit
108 * the encoded format. For example, the EC public key blob will only contain
109 * the encoded public key itself, no matter if the selection bits include
110 * OSSL_KEYMGMT_SELECT_PARAMETERS or not. However, if the selection includes
111 * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
112 * cooperate, because it cannot output the private key.
113 *
114 * EVP_PKEY_##selection_name are convenience macros that combine "typical"
115 * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
116 */
117 #define MAKE_BLOB_ENCODER(impl, type, selection_name) \
118 static OSSL_FUNC_encoder_import_object_fn \
119 impl##2blob_import_object; \
120 static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object; \
121 static OSSL_FUNC_encoder_does_selection_fn \
122 impl##2blob_does_selection; \
123 static OSSL_FUNC_encoder_encode_fn impl##2blob_encode; \
124 \
125 static void *impl##2blob_import_object(void *ctx, int selection, \
126 const OSSL_PARAM params[]) \
127 { \
128 return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
129 ctx, selection, params); \
130 } \
131 static void impl##2blob_free_object(void *key) \
132 { \
133 ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
134 } \
135 static int impl##2blob_does_selection(void *ctx, int selection) \
136 { \
137 return key2blob_check_selection(selection, \
138 EVP_PKEY_##selection_name); \
139 } \
140 static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout, \
141 const void *key, \
142 const OSSL_PARAM key_abstract[], \
143 int selection, \
144 OSSL_PASSPHRASE_CALLBACK *cb, \
145 void *cbarg) \
146 { \
147 /* We don't deal with abstract objects */ \
148 if (key_abstract != NULL) { \
149 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
150 return 0; \
151 } \
152 return key2blob_encode(vctx, key, selection, cout); \
153 } \
154 const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = { \
155 { OSSL_FUNC_ENCODER_NEWCTX, \
156 (void (*)(void))key2blob_newctx }, \
157 { OSSL_FUNC_ENCODER_FREECTX, \
158 (void (*)(void))key2blob_freectx }, \
159 { OSSL_FUNC_ENCODER_DOES_SELECTION, \
160 (void (*)(void))impl##2blob_does_selection }, \
161 { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
162 (void (*)(void))impl##2blob_import_object }, \
163 { OSSL_FUNC_ENCODER_FREE_OBJECT, \
164 (void (*)(void))impl##2blob_free_object }, \
165 { OSSL_FUNC_ENCODER_ENCODE, \
166 (void (*)(void))impl##2blob_encode }, \
167 { 0, NULL } \
168 }
169
170 #ifndef OPENSSL_NO_EC
171 MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
172 # ifndef OPENSSL_NO_SM2
173 MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
174 # endif
175 #endif