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