]>
Commit | Line | Data |
---|---|---|
0abae163 | 1 | /* |
da1c088f | 2 | * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. |
0abae163 RL |
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 | ||
cf333799 | 10 | #include <string.h> |
0abae163 RL |
11 | #include <openssl/core_names.h> |
12 | #include <openssl/params.h> | |
969024b4 | 13 | #include <openssl/ec.h> |
cf333799 | 14 | #include <openssl/rand.h> |
969024b4 | 15 | #include <openssl/err.h> |
3f773c91 TM |
16 | #ifndef FIPS_MODULE |
17 | # include <openssl/x509.h> | |
18 | #endif | |
0abae163 RL |
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 | ||
32ab57cb | 28 | int ossl_ecx_public_from_private(ECX_KEY *key) |
969024b4 MC |
29 | { |
30 | switch (key->type) { | |
31 | case ECX_KEY_TYPE_X25519: | |
054d43ff | 32 | ossl_x25519_public_from_private(key->pubkey, key->privkey); |
969024b4 MC |
33 | break; |
34 | case ECX_KEY_TYPE_ED25519: | |
054d43ff SL |
35 | if (!ossl_ed25519_public_from_private(key->libctx, key->pubkey, |
36 | key->privkey, key->propq)) { | |
9311d0c4 | 37 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); |
969024b4 MC |
38 | return 0; |
39 | } | |
40 | break; | |
41 | case ECX_KEY_TYPE_X448: | |
054d43ff | 42 | ossl_x448_public_from_private(key->pubkey, key->privkey); |
969024b4 MC |
43 | break; |
44 | case ECX_KEY_TYPE_ED448: | |
054d43ff SL |
45 | if (!ossl_ed448_public_from_private(key->libctx, key->pubkey, |
46 | key->privkey, key->propq)) { | |
9311d0c4 | 47 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); |
969024b4 MC |
48 | return 0; |
49 | } | |
50 | break; | |
51 | } | |
52 | return 1; | |
53 | } | |
54 | ||
32ab57cb SL |
55 | int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[], |
56 | int include_private) | |
0abae163 | 57 | { |
969024b4 | 58 | size_t privkeylen = 0, pubkeylen = 0; |
0abae163 RL |
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); | |
969024b4 MC |
69 | |
70 | if (param_pub_key == NULL && param_priv_key == NULL) | |
0abae163 RL |
71 | return 0; |
72 | ||
50938aec MC |
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 | ||
0abae163 RL |
90 | |
91 | pubkey = ecx->pubkey; | |
969024b4 MC |
92 | if (param_pub_key != NULL |
93 | && !OSSL_PARAM_get_octet_string(param_pub_key, | |
94 | (void **)&pubkey, | |
95 | sizeof(ecx->pubkey), &pubkeylen)) | |
0abae163 RL |
96 | return 0; |
97 | ||
50938aec | 98 | if ((param_pub_key != NULL && pubkeylen != ecx->keylen)) |
0abae163 RL |
99 | return 0; |
100 | ||
32ab57cb | 101 | if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx)) |
969024b4 MC |
102 | return 0; |
103 | ||
0abae163 RL |
104 | ecx->haspubkey = 1; |
105 | ||
106 | return 1; | |
107 | } | |
108 | ||
b4f447c0 | 109 | ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) |
4a9fe33c TM |
110 | { |
111 | ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); | |
112 | ||
e077455e | 113 | if (ret == NULL) |
4a9fe33c | 114 | return NULL; |
4a9fe33c | 115 | |
4a9fe33c TM |
116 | ret->libctx = key->libctx; |
117 | ret->haspubkey = key->haspubkey; | |
118 | ret->keylen = key->keylen; | |
119 | ret->type = key->type; | |
99b7beaf P |
120 | |
121 | if (!CRYPTO_NEW_REF(&ret->references, 1)) | |
122 | goto err; | |
4a9fe33c TM |
123 | |
124 | if (key->propq != NULL) { | |
125 | ret->propq = OPENSSL_strdup(key->propq); | |
126 | if (ret->propq == NULL) | |
127 | goto err; | |
128 | } | |
129 | ||
b4f447c0 TM |
130 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) |
131 | memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); | |
4a9fe33c | 132 | |
b4f447c0 TM |
133 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 |
134 | && key->privkey != NULL) { | |
e077455e RL |
135 | if (ossl_ecx_key_allocate_privkey(ret) == NULL) { |
136 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | |
4a9fe33c | 137 | goto err; |
e077455e | 138 | } |
4a9fe33c TM |
139 | memcpy(ret->privkey, key->privkey, ret->keylen); |
140 | } | |
141 | ||
142 | return ret; | |
143 | ||
144 | err: | |
99b7beaf | 145 | CRYPTO_FREE_REF(&ret->references); |
4a9fe33c | 146 | ossl_ecx_key_free(ret); |
4a9fe33c TM |
147 | return NULL; |
148 | } | |
149 | ||
cf333799 RL |
150 | #ifndef FIPS_MODULE |
151 | ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, | |
152 | const unsigned char *p, int plen, | |
153 | int id, ecx_key_op_t op, | |
154 | OSSL_LIB_CTX *libctx, const char *propq) | |
155 | { | |
156 | ECX_KEY *key = NULL; | |
157 | unsigned char *privkey, *pubkey; | |
158 | ||
159 | if (op != KEY_OP_KEYGEN) { | |
160 | if (palg != NULL) { | |
161 | int ptype; | |
162 | ||
163 | /* Algorithm parameters must be absent */ | |
164 | X509_ALGOR_get0(NULL, &ptype, NULL, palg); | |
165 | if (ptype != V_ASN1_UNDEF) { | |
166 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); | |
167 | return 0; | |
168 | } | |
169 | if (id == EVP_PKEY_NONE) | |
170 | id = OBJ_obj2nid(palg->algorithm); | |
171 | else if (id != OBJ_obj2nid(palg->algorithm)) { | |
172 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); | |
173 | return 0; | |
174 | } | |
175 | } | |
176 | ||
177 | if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) { | |
178 | ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); | |
179 | return 0; | |
180 | } | |
181 | } | |
182 | ||
183 | key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); | |
184 | if (key == NULL) { | |
e077455e | 185 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
cf333799 RL |
186 | return 0; |
187 | } | |
188 | pubkey = key->pubkey; | |
189 | ||
190 | if (op == KEY_OP_PUBLIC) { | |
191 | memcpy(pubkey, p, plen); | |
192 | } else { | |
193 | privkey = ossl_ecx_key_allocate_privkey(key); | |
194 | if (privkey == NULL) { | |
e077455e | 195 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
cf333799 RL |
196 | goto err; |
197 | } | |
198 | if (op == KEY_OP_KEYGEN) { | |
199 | if (id != EVP_PKEY_NONE) { | |
5cbd2ea3 | 200 | if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0) |
cf333799 RL |
201 | goto err; |
202 | if (id == EVP_PKEY_X25519) { | |
203 | privkey[0] &= 248; | |
204 | privkey[X25519_KEYLEN - 1] &= 127; | |
205 | privkey[X25519_KEYLEN - 1] |= 64; | |
206 | } else if (id == EVP_PKEY_X448) { | |
207 | privkey[0] &= 252; | |
208 | privkey[X448_KEYLEN - 1] |= 128; | |
209 | } | |
210 | } | |
211 | } else { | |
212 | memcpy(privkey, p, KEYLENID(id)); | |
213 | } | |
214 | if (!ossl_ecx_public_from_private(key)) { | |
215 | ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); | |
216 | goto err; | |
217 | } | |
218 | } | |
219 | ||
220 | return key; | |
221 | err: | |
222 | ossl_ecx_key_free(key); | |
223 | return NULL; | |
224 | } | |
225 | ||
226 | ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, | |
227 | OSSL_LIB_CTX *libctx, const char *propq) | |
228 | { | |
229 | ECX_KEY *ecx = NULL; | |
230 | const unsigned char *p; | |
231 | int plen; | |
232 | ASN1_OCTET_STRING *oct = NULL; | |
233 | const X509_ALGOR *palg; | |
234 | ||
235 | if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) | |
236 | return 0; | |
237 | ||
238 | oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); | |
239 | if (oct == NULL) { | |
240 | p = NULL; | |
241 | plen = 0; | |
242 | } else { | |
243 | p = ASN1_STRING_get0_data(oct); | |
244 | plen = ASN1_STRING_length(oct); | |
245 | } | |
246 | ||
247 | /* | |
248 | * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type | |
249 | * on its own. | |
250 | */ | |
251 | ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, | |
252 | libctx, propq); | |
253 | ASN1_OCTET_STRING_free(oct); | |
254 | return ecx; | |
255 | } | |
256 | #endif |