Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/providers/implementations/encode_decode/encode_key2blob.c
48383 views
1
/*
2
* Copyright 2021-2023 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
OSSL_DISPATCH_END \
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
180
181