1 | /*
|
---|
2 | * Copyright 2020-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 | #include <string.h>
|
---|
11 | #include <openssl/core_names.h>
|
---|
12 | #include <openssl/params.h>
|
---|
13 | #include <openssl/ec.h>
|
---|
14 | #include <openssl/rand.h>
|
---|
15 | #include <openssl/err.h>
|
---|
16 | #ifndef FIPS_MODULE
|
---|
17 | # include <openssl/x509.h>
|
---|
18 | #endif
|
---|
19 | #include "crypto/ecx.h"
|
---|
20 | #include "ecx_backend.h"
|
---|
21 |
|
---|
22 | /*
|
---|
23 | * The intention with the "backend" source file is to offer backend support
|
---|
24 | * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
|
---|
25 | * implementations alike.
|
---|
26 | */
|
---|
27 |
|
---|
28 | int ossl_ecx_public_from_private(ECX_KEY *key)
|
---|
29 | {
|
---|
30 | switch (key->type) {
|
---|
31 | case ECX_KEY_TYPE_X25519:
|
---|
32 | ossl_x25519_public_from_private(key->pubkey, key->privkey);
|
---|
33 | break;
|
---|
34 | case ECX_KEY_TYPE_ED25519:
|
---|
35 | if (!ossl_ed25519_public_from_private(key->libctx, key->pubkey,
|
---|
36 | key->privkey, key->propq)) {
|
---|
37 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
|
---|
38 | return 0;
|
---|
39 | }
|
---|
40 | break;
|
---|
41 | case ECX_KEY_TYPE_X448:
|
---|
42 | ossl_x448_public_from_private(key->pubkey, key->privkey);
|
---|
43 | break;
|
---|
44 | case ECX_KEY_TYPE_ED448:
|
---|
45 | if (!ossl_ed448_public_from_private(key->libctx, key->pubkey,
|
---|
46 | key->privkey, key->propq)) {
|
---|
47 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
|
---|
48 | return 0;
|
---|
49 | }
|
---|
50 | break;
|
---|
51 | }
|
---|
52 | return 1;
|
---|
53 | }
|
---|
54 |
|
---|
55 | int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
|
---|
56 | int include_private)
|
---|
57 | {
|
---|
58 | size_t privkeylen = 0, pubkeylen = 0;
|
---|
59 | const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
|
---|
60 | unsigned char *pubkey;
|
---|
61 |
|
---|
62 | if (ecx == NULL)
|
---|
63 | return 0;
|
---|
64 |
|
---|
65 | param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
|
---|
66 | if (include_private)
|
---|
67 | param_priv_key =
|
---|
68 | OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
---|
69 |
|
---|
70 | if (param_pub_key == NULL && param_priv_key == NULL)
|
---|
71 | return 0;
|
---|
72 |
|
---|
73 | if (param_priv_key != NULL) {
|
---|
74 | if (!OSSL_PARAM_get_octet_string(param_priv_key,
|
---|
75 | (void **)&ecx->privkey, ecx->keylen,
|
---|
76 | &privkeylen))
|
---|
77 | return 0;
|
---|
78 | if (privkeylen != ecx->keylen) {
|
---|
79 | /*
|
---|
80 | * Invalid key length. We will clear what we've received now. We
|
---|
81 | * can't leave it to ossl_ecx_key_free() because that will call
|
---|
82 | * OPENSSL_secure_clear_free() and assume the correct key length
|
---|
83 | */
|
---|
84 | OPENSSL_secure_clear_free(ecx->privkey, privkeylen);
|
---|
85 | ecx->privkey = NULL;
|
---|
86 | return 0;
|
---|
87 | }
|
---|
88 | }
|
---|
89 |
|
---|
90 |
|
---|
91 | pubkey = ecx->pubkey;
|
---|
92 | if (param_pub_key != NULL
|
---|
93 | && !OSSL_PARAM_get_octet_string(param_pub_key,
|
---|
94 | (void **)&pubkey,
|
---|
95 | sizeof(ecx->pubkey), &pubkeylen))
|
---|
96 | return 0;
|
---|
97 |
|
---|
98 | if ((param_pub_key != NULL && pubkeylen != ecx->keylen))
|
---|
99 | return 0;
|
---|
100 |
|
---|
101 | if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx))
|
---|
102 | return 0;
|
---|
103 |
|
---|
104 | ecx->haspubkey = 1;
|
---|
105 |
|
---|
106 | return 1;
|
---|
107 | }
|
---|
108 |
|
---|
109 | ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection)
|
---|
110 | {
|
---|
111 | ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
|
---|
112 |
|
---|
113 | if (ret == NULL) {
|
---|
114 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
---|
115 | return NULL;
|
---|
116 | }
|
---|
117 |
|
---|
118 | ret->lock = CRYPTO_THREAD_lock_new();
|
---|
119 | if (ret->lock == NULL) {
|
---|
120 | OPENSSL_free(ret);
|
---|
121 | return NULL;
|
---|
122 | }
|
---|
123 |
|
---|
124 | ret->libctx = key->libctx;
|
---|
125 | ret->haspubkey = key->haspubkey;
|
---|
126 | ret->keylen = key->keylen;
|
---|
127 | ret->type = key->type;
|
---|
128 | ret->references = 1;
|
---|
129 |
|
---|
130 | if (key->propq != NULL) {
|
---|
131 | ret->propq = OPENSSL_strdup(key->propq);
|
---|
132 | if (ret->propq == NULL)
|
---|
133 | goto err;
|
---|
134 | }
|
---|
135 |
|
---|
136 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
---|
137 | memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
|
---|
138 |
|
---|
139 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
|
---|
140 | && key->privkey != NULL) {
|
---|
141 | if (ossl_ecx_key_allocate_privkey(ret) == NULL)
|
---|
142 | goto err;
|
---|
143 | memcpy(ret->privkey, key->privkey, ret->keylen);
|
---|
144 | }
|
---|
145 |
|
---|
146 | return ret;
|
---|
147 |
|
---|
148 | err:
|
---|
149 | ossl_ecx_key_free(ret);
|
---|
150 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
---|
151 | return NULL;
|
---|
152 | }
|
---|
153 |
|
---|
154 | #ifndef FIPS_MODULE
|
---|
155 | ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
|
---|
156 | const unsigned char *p, int plen,
|
---|
157 | int id, ecx_key_op_t op,
|
---|
158 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
159 | {
|
---|
160 | ECX_KEY *key = NULL;
|
---|
161 | unsigned char *privkey, *pubkey;
|
---|
162 |
|
---|
163 | if (op != KEY_OP_KEYGEN) {
|
---|
164 | if (palg != NULL) {
|
---|
165 | int ptype;
|
---|
166 |
|
---|
167 | /* Algorithm parameters must be absent */
|
---|
168 | X509_ALGOR_get0(NULL, &ptype, NULL, palg);
|
---|
169 | if (ptype != V_ASN1_UNDEF) {
|
---|
170 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
|
---|
171 | return 0;
|
---|
172 | }
|
---|
173 | if (id == EVP_PKEY_NONE)
|
---|
174 | id = OBJ_obj2nid(palg->algorithm);
|
---|
175 | else if (id != OBJ_obj2nid(palg->algorithm)) {
|
---|
176 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
|
---|
177 | return 0;
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) {
|
---|
182 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
|
---|
183 | return 0;
|
---|
184 | }
|
---|
185 | }
|
---|
186 |
|
---|
187 | key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq);
|
---|
188 | if (key == NULL) {
|
---|
189 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 | pubkey = key->pubkey;
|
---|
193 |
|
---|
194 | if (op == KEY_OP_PUBLIC) {
|
---|
195 | memcpy(pubkey, p, plen);
|
---|
196 | } else {
|
---|
197 | privkey = ossl_ecx_key_allocate_privkey(key);
|
---|
198 | if (privkey == NULL) {
|
---|
199 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
---|
200 | goto err;
|
---|
201 | }
|
---|
202 | if (op == KEY_OP_KEYGEN) {
|
---|
203 | if (id != EVP_PKEY_NONE) {
|
---|
204 | if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0)
|
---|
205 | goto err;
|
---|
206 | if (id == EVP_PKEY_X25519) {
|
---|
207 | privkey[0] &= 248;
|
---|
208 | privkey[X25519_KEYLEN - 1] &= 127;
|
---|
209 | privkey[X25519_KEYLEN - 1] |= 64;
|
---|
210 | } else if (id == EVP_PKEY_X448) {
|
---|
211 | privkey[0] &= 252;
|
---|
212 | privkey[X448_KEYLEN - 1] |= 128;
|
---|
213 | }
|
---|
214 | }
|
---|
215 | } else {
|
---|
216 | memcpy(privkey, p, KEYLENID(id));
|
---|
217 | }
|
---|
218 | if (!ossl_ecx_public_from_private(key)) {
|
---|
219 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
|
---|
220 | goto err;
|
---|
221 | }
|
---|
222 | }
|
---|
223 |
|
---|
224 | return key;
|
---|
225 | err:
|
---|
226 | ossl_ecx_key_free(key);
|
---|
227 | return NULL;
|
---|
228 | }
|
---|
229 |
|
---|
230 | ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
|
---|
231 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
232 | {
|
---|
233 | ECX_KEY *ecx = NULL;
|
---|
234 | const unsigned char *p;
|
---|
235 | int plen;
|
---|
236 | ASN1_OCTET_STRING *oct = NULL;
|
---|
237 | const X509_ALGOR *palg;
|
---|
238 |
|
---|
239 | if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf))
|
---|
240 | return 0;
|
---|
241 |
|
---|
242 | oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
|
---|
243 | if (oct == NULL) {
|
---|
244 | p = NULL;
|
---|
245 | plen = 0;
|
---|
246 | } else {
|
---|
247 | p = ASN1_STRING_get0_data(oct);
|
---|
248 | plen = ASN1_STRING_length(oct);
|
---|
249 | }
|
---|
250 |
|
---|
251 | /*
|
---|
252 | * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type
|
---|
253 | * on its own.
|
---|
254 | */
|
---|
255 | ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE,
|
---|
256 | libctx, propq);
|
---|
257 | ASN1_OCTET_STRING_free(oct);
|
---|
258 | return ecx;
|
---|
259 | }
|
---|
260 | #endif
|
---|