]>
Commit | Line | Data |
---|---|---|
c8182743 | 1 | /* |
fecb3aae | 2 | * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. |
c8182743 RL |
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 | { | |
9500c823 | 32 | BIO *out = ossl_bio_new_from_core_bio(provctx, cout); |
352a0bca | 33 | int ret; |
34 | ||
35 | if (out == NULL) | |
36 | return 0; | |
37 | ret = BIO_write(out, data, len); | |
c8182743 RL |
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; | |
c8182743 RL |
45 | |
46 | static void *key2blob_newctx(void *provctx) | |
47 | { | |
48 | return provctx; | |
49 | } | |
50 | ||
51 | static void key2blob_freectx(void *vctx) | |
52 | { | |
53 | } | |
54 | ||
c8182743 RL |
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 }, \ | |
c8182743 RL |
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 |