xref: /freebsd/crypto/openssl/providers/implementations/encode_decode/encode_key2blob.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * Low level APIs are deprecated for public use, but still ok for internal use.
12b077aed3SPierre Pronchery  */
13b077aed3SPierre Pronchery #include "internal/deprecated.h"
14b077aed3SPierre Pronchery 
15b077aed3SPierre Pronchery #include <openssl/core.h>
16b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
17b077aed3SPierre Pronchery #include <openssl/core_names.h>
18b077aed3SPierre Pronchery #include <openssl/params.h>
19b077aed3SPierre Pronchery #include <openssl/err.h>
20b077aed3SPierre Pronchery #include <openssl/evp.h>
21b077aed3SPierre Pronchery #include <openssl/ec.h>
22b077aed3SPierre Pronchery #include "internal/passphrase.h"
23b077aed3SPierre Pronchery #include "internal/nelem.h"
24b077aed3SPierre Pronchery #include "prov/implementations.h"
25b077aed3SPierre Pronchery #include "prov/bio.h"
26b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
27b077aed3SPierre Pronchery #include "endecoder_local.h"
28b077aed3SPierre Pronchery 
write_blob(void * provctx,OSSL_CORE_BIO * cout,void * data,int len)29b077aed3SPierre Pronchery static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
30b077aed3SPierre Pronchery                       void *data, int len)
31b077aed3SPierre Pronchery {
32b077aed3SPierre Pronchery     BIO *out = ossl_bio_new_from_core_bio(provctx, cout);
33b077aed3SPierre Pronchery     int ret;
34b077aed3SPierre Pronchery 
35b077aed3SPierre Pronchery     if (out == NULL)
36b077aed3SPierre Pronchery         return 0;
37b077aed3SPierre Pronchery     ret = BIO_write(out, data, len);
38b077aed3SPierre Pronchery 
39b077aed3SPierre Pronchery     BIO_free(out);
40b077aed3SPierre Pronchery     return ret;
41b077aed3SPierre Pronchery }
42b077aed3SPierre Pronchery 
43b077aed3SPierre Pronchery static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
44b077aed3SPierre Pronchery static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;
45b077aed3SPierre Pronchery 
key2blob_newctx(void * provctx)46b077aed3SPierre Pronchery static void *key2blob_newctx(void *provctx)
47b077aed3SPierre Pronchery {
48b077aed3SPierre Pronchery     return provctx;
49b077aed3SPierre Pronchery }
50b077aed3SPierre Pronchery 
key2blob_freectx(void * vctx)51b077aed3SPierre Pronchery static void key2blob_freectx(void *vctx)
52b077aed3SPierre Pronchery {
53b077aed3SPierre Pronchery }
54b077aed3SPierre Pronchery 
key2blob_check_selection(int selection,int selection_mask)55b077aed3SPierre Pronchery static int key2blob_check_selection(int selection, int selection_mask)
56b077aed3SPierre Pronchery {
57b077aed3SPierre Pronchery     /*
58b077aed3SPierre Pronchery      * The selections are kinda sorta "levels", i.e. each selection given
59b077aed3SPierre Pronchery      * here is assumed to include those following.
60b077aed3SPierre Pronchery      */
61b077aed3SPierre Pronchery     int checks[] = {
62b077aed3SPierre Pronchery         OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
63b077aed3SPierre Pronchery         OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
64b077aed3SPierre Pronchery         OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
65b077aed3SPierre Pronchery     };
66b077aed3SPierre Pronchery     size_t i;
67b077aed3SPierre Pronchery 
68b077aed3SPierre Pronchery     /* The decoder implementations made here support guessing */
69b077aed3SPierre Pronchery     if (selection == 0)
70b077aed3SPierre Pronchery         return 1;
71b077aed3SPierre Pronchery 
72b077aed3SPierre Pronchery     for (i = 0; i < OSSL_NELEM(checks); i++) {
73b077aed3SPierre Pronchery         int check1 = (selection & checks[i]) != 0;
74b077aed3SPierre Pronchery         int check2 = (selection_mask & checks[i]) != 0;
75b077aed3SPierre Pronchery 
76b077aed3SPierre Pronchery         /*
77b077aed3SPierre Pronchery          * If the caller asked for the currently checked bit(s), return
78b077aed3SPierre Pronchery          * whether the decoder description says it's supported.
79b077aed3SPierre Pronchery          */
80b077aed3SPierre Pronchery         if (check1)
81b077aed3SPierre Pronchery             return check2;
82b077aed3SPierre Pronchery     }
83b077aed3SPierre Pronchery 
84b077aed3SPierre Pronchery     /* This should be dead code, but just to be safe... */
85b077aed3SPierre Pronchery     return 0;
86b077aed3SPierre Pronchery }
87b077aed3SPierre Pronchery 
key2blob_encode(void * vctx,const void * key,int selection,OSSL_CORE_BIO * cout)88b077aed3SPierre Pronchery static int key2blob_encode(void *vctx, const void *key, int selection,
89b077aed3SPierre Pronchery                            OSSL_CORE_BIO *cout)
90b077aed3SPierre Pronchery {
91b077aed3SPierre Pronchery     int pubkey_len = 0, ok = 0;
92b077aed3SPierre Pronchery     unsigned char *pubkey = NULL;
93b077aed3SPierre Pronchery 
94b077aed3SPierre Pronchery     pubkey_len = i2o_ECPublicKey(key, &pubkey);
95b077aed3SPierre Pronchery     if (pubkey_len > 0 && pubkey != NULL)
96b077aed3SPierre Pronchery         ok = write_blob(vctx, cout, pubkey, pubkey_len);
97b077aed3SPierre Pronchery     OPENSSL_free(pubkey);
98b077aed3SPierre Pronchery     return ok;
99b077aed3SPierre Pronchery }
100b077aed3SPierre Pronchery 
101b077aed3SPierre Pronchery /*
102b077aed3SPierre Pronchery  * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
103b077aed3SPierre Pronchery  * encoder
104b077aed3SPierre Pronchery  *
105b077aed3SPierre Pronchery  * impl:                The keytype to encode
106b077aed3SPierre Pronchery  * type:                The C structure type holding the key data
107b077aed3SPierre Pronchery  * selection_name:      The acceptable selections.  This translates into
108b077aed3SPierre Pronchery  *                      the macro EVP_PKEY_##selection_name.
109b077aed3SPierre Pronchery  *
110b077aed3SPierre Pronchery  * The selection is understood as a "level" rather than an exact set of
111b077aed3SPierre Pronchery  * requests from the caller.  The encoder has to decide what contents fit
112b077aed3SPierre Pronchery  * the encoded format.  For example, the EC public key blob will only contain
113b077aed3SPierre Pronchery  * the encoded public key itself, no matter if the selection bits include
114b077aed3SPierre Pronchery  * OSSL_KEYMGMT_SELECT_PARAMETERS or not.  However, if the selection includes
115b077aed3SPierre Pronchery  * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
116b077aed3SPierre Pronchery  * cooperate, because it cannot output the private key.
117b077aed3SPierre Pronchery  *
118b077aed3SPierre Pronchery  * EVP_PKEY_##selection_name are convenience macros that combine "typical"
119b077aed3SPierre Pronchery  * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
120b077aed3SPierre Pronchery  */
121b077aed3SPierre Pronchery #define MAKE_BLOB_ENCODER(impl, type, selection_name)                   \
122b077aed3SPierre Pronchery     static OSSL_FUNC_encoder_import_object_fn                           \
123b077aed3SPierre Pronchery     impl##2blob_import_object;                                          \
124b077aed3SPierre Pronchery     static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object;    \
125b077aed3SPierre Pronchery     static OSSL_FUNC_encoder_does_selection_fn                          \
126b077aed3SPierre Pronchery     impl##2blob_does_selection;                                         \
127b077aed3SPierre Pronchery     static OSSL_FUNC_encoder_encode_fn impl##2blob_encode;              \
128b077aed3SPierre Pronchery                                                                         \
129b077aed3SPierre Pronchery     static void *impl##2blob_import_object(void *ctx, int selection,    \
130b077aed3SPierre Pronchery                                            const OSSL_PARAM params[])   \
131b077aed3SPierre Pronchery     {                                                                   \
132b077aed3SPierre Pronchery         return ossl_prov_import_key(ossl_##impl##_keymgmt_functions,    \
133b077aed3SPierre Pronchery                                     ctx, selection, params);            \
134b077aed3SPierre Pronchery     }                                                                   \
135b077aed3SPierre Pronchery     static void impl##2blob_free_object(void *key)                      \
136b077aed3SPierre Pronchery     {                                                                   \
137b077aed3SPierre Pronchery         ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key);       \
138b077aed3SPierre Pronchery     }                                                                   \
139b077aed3SPierre Pronchery     static int impl##2blob_does_selection(void *ctx, int selection)     \
140b077aed3SPierre Pronchery     {                                                                   \
141b077aed3SPierre Pronchery         return key2blob_check_selection(selection,                      \
142b077aed3SPierre Pronchery                                         EVP_PKEY_##selection_name);     \
143b077aed3SPierre Pronchery     }                                                                   \
144b077aed3SPierre Pronchery     static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout,      \
145b077aed3SPierre Pronchery                                   const void *key,                      \
146b077aed3SPierre Pronchery                                   const OSSL_PARAM key_abstract[],      \
147b077aed3SPierre Pronchery                                   int selection,                        \
148b077aed3SPierre Pronchery                                   OSSL_PASSPHRASE_CALLBACK *cb,         \
149b077aed3SPierre Pronchery                                   void *cbarg)                          \
150b077aed3SPierre Pronchery     {                                                                   \
151b077aed3SPierre Pronchery         /* We don't deal with abstract objects */                       \
152b077aed3SPierre Pronchery         if (key_abstract != NULL) {                                     \
153b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);     \
154b077aed3SPierre Pronchery             return 0;                                                   \
155b077aed3SPierre Pronchery         }                                                               \
156b077aed3SPierre Pronchery         return key2blob_encode(vctx, key, selection, cout);             \
157b077aed3SPierre Pronchery     }                                                                   \
158b077aed3SPierre Pronchery     const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = {   \
159b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_NEWCTX,                                     \
160b077aed3SPierre Pronchery           (void (*)(void))key2blob_newctx },                            \
161b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_FREECTX,                                    \
162b077aed3SPierre Pronchery           (void (*)(void))key2blob_freectx },                           \
163b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_DOES_SELECTION,                             \
164b077aed3SPierre Pronchery           (void (*)(void))impl##2blob_does_selection },                 \
165b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_IMPORT_OBJECT,                              \
166b077aed3SPierre Pronchery           (void (*)(void))impl##2blob_import_object },                  \
167b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_FREE_OBJECT,                                \
168b077aed3SPierre Pronchery           (void (*)(void))impl##2blob_free_object },                    \
169b077aed3SPierre Pronchery         { OSSL_FUNC_ENCODER_ENCODE,                                     \
170b077aed3SPierre Pronchery           (void (*)(void))impl##2blob_encode },                         \
171*e7be843bSPierre Pronchery         OSSL_DISPATCH_END                                               \
172b077aed3SPierre Pronchery     }
173b077aed3SPierre Pronchery 
174b077aed3SPierre Pronchery #ifndef OPENSSL_NO_EC
175b077aed3SPierre Pronchery MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
176b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SM2
177b077aed3SPierre Pronchery MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
178b077aed3SPierre Pronchery # endif
179b077aed3SPierre Pronchery #endif
180