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
|
---|