/src/openssl/providers/implementations/encode_decode/encode_key2blob.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021-2023 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 | 0 | { |
32 | 0 | BIO *out = ossl_bio_new_from_core_bio(provctx, cout); |
33 | 0 | int ret; |
34 | |
|
35 | 0 | if (out == NULL) |
36 | 0 | return 0; |
37 | 0 | ret = BIO_write(out, data, len); |
38 | |
|
39 | 0 | BIO_free(out); |
40 | 0 | return ret; |
41 | 0 | } |
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 | 0 | { |
48 | 0 | return provctx; |
49 | 0 | } |
50 | | |
51 | | static void key2blob_freectx(void *vctx) |
52 | 0 | { |
53 | 0 | } |
54 | | |
55 | | static int key2blob_check_selection(int selection, int selection_mask) |
56 | 0 | { |
57 | | /* |
58 | | * The selections are kinda sorta "levels", i.e. each selection given |
59 | | * here is assumed to include those following. |
60 | | */ |
61 | 0 | int checks[] = { |
62 | 0 | OSSL_KEYMGMT_SELECT_PRIVATE_KEY, |
63 | 0 | OSSL_KEYMGMT_SELECT_PUBLIC_KEY, |
64 | 0 | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS |
65 | 0 | }; |
66 | 0 | size_t i; |
67 | | |
68 | | /* The decoder implementations made here support guessing */ |
69 | 0 | if (selection == 0) |
70 | 0 | return 1; |
71 | | |
72 | 0 | for (i = 0; i < OSSL_NELEM(checks); i++) { |
73 | 0 | int check1 = (selection & checks[i]) != 0; |
74 | 0 | 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 | 0 | if (check1) |
81 | 0 | return check2; |
82 | 0 | } |
83 | | |
84 | | /* This should be dead code, but just to be safe... */ |
85 | 0 | return 0; |
86 | 0 | } |
87 | | |
88 | | static int key2blob_encode(void *vctx, const void *key, int selection, |
89 | | OSSL_CORE_BIO *cout) |
90 | 0 | { |
91 | 0 | int pubkey_len = 0, ok = 0; |
92 | 0 | unsigned char *pubkey = NULL; |
93 | |
|
94 | 0 | pubkey_len = i2o_ECPublicKey(key, &pubkey); |
95 | 0 | if (pubkey_len > 0 && pubkey != NULL) |
96 | 0 | ok = write_blob(vctx, cout, pubkey, pubkey_len); |
97 | 0 | OPENSSL_free(pubkey); |
98 | 0 | return ok; |
99 | 0 | } |
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 | 0 | { \ |
132 | 0 | return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \ |
133 | 0 | ctx, selection, params); \ |
134 | 0 | } \ Unexecuted instantiation: encode_key2blob.c:ec2blob_import_object Unexecuted instantiation: encode_key2blob.c:sm22blob_import_object |
135 | | static void impl##2blob_free_object(void *key) \ |
136 | 0 | { \ |
137 | 0 | ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \ |
138 | 0 | } \ Unexecuted instantiation: encode_key2blob.c:ec2blob_free_object Unexecuted instantiation: encode_key2blob.c:sm22blob_free_object |
139 | | static int impl##2blob_does_selection(void *ctx, int selection) \ |
140 | 0 | { \ |
141 | 0 | return key2blob_check_selection(selection, \ |
142 | 0 | EVP_PKEY_##selection_name); \ |
143 | 0 | } \ Unexecuted instantiation: encode_key2blob.c:ec2blob_does_selection Unexecuted instantiation: encode_key2blob.c:sm22blob_does_selection |
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 | 0 | { \ |
151 | 0 | /* We don't deal with abstract objects */ \ |
152 | 0 | if (key_abstract != NULL) { \ |
153 | 0 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \ |
154 | 0 | return 0; \ |
155 | 0 | } \ |
156 | 0 | return key2blob_encode(vctx, key, selection, cout); \ |
157 | 0 | } \ Unexecuted instantiation: encode_key2blob.c:ec2blob_encode Unexecuted instantiation: encode_key2blob.c:sm22blob_encode |
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 | | OSSL_DISPATCH_END \ |
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 |