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