]>
Commit | Line | Data |
---|---|---|
90d3cb57 MC |
1 | /* |
2 | * Copyright 2020 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 <assert.h> | |
11 | #include <openssl/core_numbers.h> | |
12 | #include <openssl/core_names.h> | |
43cd3701 | 13 | #include <openssl/params.h> |
c1e48c51 | 14 | #include <openssl/err.h> |
43cd3701 P |
15 | #include <openssl/evp.h> |
16 | #include <openssl/rand.h> | |
17 | #include "internal/param_build_set.h" | |
18 | #include "openssl/param_build.h" | |
90d3cb57 MC |
19 | #include "crypto/ecx.h" |
20 | #include "prov/implementations.h" | |
21 | #include "prov/providercommon.h" | |
43cd3701 P |
22 | #include "prov/provider_ctx.h" |
23 | #ifdef S390X_EC_ASM | |
24 | # include "s390x_arch.h" | |
c1e48c51 | 25 | # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */ |
43cd3701 | 26 | #endif |
90d3cb57 MC |
27 | |
28 | static OSSL_OP_keymgmt_new_fn x25519_new_key; | |
29 | static OSSL_OP_keymgmt_new_fn x448_new_key; | |
af6d8dd3 MC |
30 | static OSSL_OP_keymgmt_new_fn ed25519_new_key; |
31 | static OSSL_OP_keymgmt_new_fn ed448_new_key; | |
43cd3701 P |
32 | static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init; |
33 | static OSSL_OP_keymgmt_gen_init_fn x448_gen_init; | |
34 | static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init; | |
35 | static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init; | |
36 | static OSSL_OP_keymgmt_gen_fn x25519_gen; | |
37 | static OSSL_OP_keymgmt_gen_fn x448_gen; | |
38 | static OSSL_OP_keymgmt_gen_fn ed25519_gen; | |
39 | static OSSL_OP_keymgmt_gen_fn ed448_gen; | |
40 | static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup; | |
90d3cb57 MC |
41 | static OSSL_OP_keymgmt_get_params_fn x25519_get_params; |
42 | static OSSL_OP_keymgmt_get_params_fn x448_get_params; | |
af6d8dd3 MC |
43 | static OSSL_OP_keymgmt_get_params_fn ed25519_get_params; |
44 | static OSSL_OP_keymgmt_get_params_fn ed448_get_params; | |
1a7328c8 RL |
45 | static OSSL_OP_keymgmt_gettable_params_fn x25519_gettable_params; |
46 | static OSSL_OP_keymgmt_gettable_params_fn x448_gettable_params; | |
47 | static OSSL_OP_keymgmt_gettable_params_fn ed25519_gettable_params; | |
48 | static OSSL_OP_keymgmt_gettable_params_fn ed448_gettable_params; | |
6a9bd929 MC |
49 | static OSSL_OP_keymgmt_set_params_fn x25519_set_params; |
50 | static OSSL_OP_keymgmt_set_params_fn x448_set_params; | |
51 | static OSSL_OP_keymgmt_set_params_fn ed25519_set_params; | |
52 | static OSSL_OP_keymgmt_set_params_fn ed448_set_params; | |
53 | static OSSL_OP_keymgmt_settable_params_fn x25519_settable_params; | |
54 | static OSSL_OP_keymgmt_settable_params_fn x448_settable_params; | |
55 | static OSSL_OP_keymgmt_settable_params_fn ed25519_settable_params; | |
56 | static OSSL_OP_keymgmt_settable_params_fn ed448_settable_params; | |
90d3cb57 | 57 | static OSSL_OP_keymgmt_has_fn ecx_has; |
262ff123 | 58 | static OSSL_OP_keymgmt_match_fn ecx_match; |
90d3cb57 MC |
59 | static OSSL_OP_keymgmt_import_fn ecx_import; |
60 | static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types; | |
61 | static OSSL_OP_keymgmt_export_fn ecx_export; | |
62 | static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types; | |
63 | ||
f552d900 SL |
64 | #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR) |
65 | ||
43cd3701 P |
66 | struct ecx_gen_ctx { |
67 | OPENSSL_CTX *libctx; | |
68 | ECX_KEY_TYPE type; | |
69 | }; | |
70 | ||
c1e48c51 P |
71 | #ifdef S390X_EC_ASM |
72 | static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx); | |
73 | static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx); | |
74 | static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx); | |
75 | static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx); | |
76 | #endif | |
43cd3701 | 77 | |
90d3cb57 MC |
78 | static void *x25519_new_key(void *provctx) |
79 | { | |
f3336f40 | 80 | return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X25519, 0); |
90d3cb57 MC |
81 | } |
82 | ||
83 | static void *x448_new_key(void *provctx) | |
84 | { | |
f3336f40 | 85 | return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X448, 0); |
90d3cb57 MC |
86 | } |
87 | ||
af6d8dd3 MC |
88 | static void *ed25519_new_key(void *provctx) |
89 | { | |
f3336f40 | 90 | return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED25519, 0); |
af6d8dd3 MC |
91 | } |
92 | ||
93 | static void *ed448_new_key(void *provctx) | |
94 | { | |
f3336f40 | 95 | return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED448, 0); |
af6d8dd3 MC |
96 | } |
97 | ||
90d3cb57 MC |
98 | static int ecx_has(void *keydata, int selection) |
99 | { | |
100 | ECX_KEY *key = keydata; | |
adc9f731 | 101 | int ok = 0; |
90d3cb57 | 102 | |
adc9f731 RL |
103 | if (key != NULL) { |
104 | if ((selection & ECX_POSSIBLE_SELECTIONS) != 0) | |
105 | ok = 1; | |
90d3cb57 | 106 | |
adc9f731 RL |
107 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) |
108 | ok = ok && key->haspubkey; | |
90d3cb57 | 109 | |
adc9f731 RL |
110 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) |
111 | ok = ok && key->privkey != NULL; | |
112 | } | |
90d3cb57 MC |
113 | return ok; |
114 | } | |
115 | ||
262ff123 MC |
116 | static int ecx_match(const void *keydata1, const void *keydata2, int selection) |
117 | { | |
118 | const ECX_KEY *key1 = keydata1; | |
119 | const ECX_KEY *key2 = keydata2; | |
120 | int ok = 1; | |
121 | ||
122 | if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) | |
123 | ok = ok && key1->type == key2->type; | |
124 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { | |
125 | if ((key1->privkey == NULL && key2->privkey != NULL) | |
126 | || (key1->privkey != NULL && key2->privkey == NULL) | |
127 | || key1->type != key2->type) | |
128 | ok = 0; | |
129 | else | |
130 | ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */ | |
131 | || CRYPTO_memcmp(key1->privkey, key2->privkey, | |
132 | key1->keylen) == 0); | |
133 | } | |
134 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { | |
135 | if (key1->haspubkey != key2->haspubkey | |
136 | || key1->type != key2->type) | |
137 | ok = 0; | |
138 | else | |
139 | ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */ | |
140 | || CRYPTO_memcmp(key1->pubkey, key2->pubkey, | |
141 | key1->keylen) == 0); | |
142 | } | |
143 | return ok; | |
144 | } | |
145 | ||
90d3cb57 MC |
146 | static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[]) |
147 | { | |
148 | ECX_KEY *key = keydata; | |
0abae163 RL |
149 | int ok = 1; |
150 | int include_private = 0; | |
90d3cb57 MC |
151 | |
152 | if (key == NULL) | |
153 | return 0; | |
154 | ||
969024b4 | 155 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) |
90d3cb57 MC |
156 | return 0; |
157 | ||
0abae163 | 158 | include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0); |
969024b4 | 159 | ok = ok && ecx_key_fromdata(key, params, include_private); |
90d3cb57 | 160 | |
0abae163 | 161 | return ok; |
90d3cb57 MC |
162 | } |
163 | ||
96ebe52e SL |
164 | static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl, |
165 | OSSL_PARAM params[]) | |
90d3cb57 MC |
166 | { |
167 | if (key == NULL) | |
168 | return 0; | |
169 | ||
96ebe52e SL |
170 | if (!ossl_param_build_set_octet_string(tmpl, params, |
171 | OSSL_PKEY_PARAM_PUB_KEY, | |
172 | key->pubkey, key->keylen)) | |
90d3cb57 MC |
173 | return 0; |
174 | ||
175 | if (key->privkey != NULL | |
96ebe52e SL |
176 | && !ossl_param_build_set_octet_string(tmpl, params, |
177 | OSSL_PKEY_PARAM_PRIV_KEY, | |
178 | key->privkey, key->keylen)) | |
90d3cb57 MC |
179 | return 0; |
180 | ||
181 | return 1; | |
182 | } | |
183 | ||
184 | static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, | |
185 | void *cbarg) | |
186 | { | |
187 | ECX_KEY *key = keydata; | |
6d4e6009 | 188 | OSSL_PARAM_BLD *tmpl; |
90d3cb57 | 189 | OSSL_PARAM *params = NULL; |
96ebe52e | 190 | int ret = 0; |
90d3cb57 MC |
191 | |
192 | if (key == NULL) | |
193 | return 0; | |
194 | ||
6d4e6009 P |
195 | tmpl = OSSL_PARAM_BLD_new(); |
196 | if (tmpl == NULL) | |
90d3cb57 MC |
197 | return 0; |
198 | ||
6d4e6009 | 199 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 |
96ebe52e SL |
200 | && !key_to_params(key, tmpl, NULL)) |
201 | goto err; | |
202 | ||
6d4e6009 | 203 | params = OSSL_PARAM_BLD_to_param(tmpl); |
6d4e6009 | 204 | if (params == NULL) |
96ebe52e | 205 | goto err; |
6d4e6009 | 206 | |
90d3cb57 | 207 | ret = param_cb(params, cbarg); |
6d4e6009 | 208 | OSSL_PARAM_BLD_free_params(params); |
96ebe52e SL |
209 | err: |
210 | OSSL_PARAM_BLD_free(tmpl); | |
90d3cb57 MC |
211 | return ret; |
212 | } | |
213 | ||
96ebe52e SL |
214 | #define ECX_KEY_TYPES() \ |
215 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ | |
216 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0) | |
217 | ||
90d3cb57 | 218 | static const OSSL_PARAM ecx_key_types[] = { |
96ebe52e | 219 | ECX_KEY_TYPES(), |
90d3cb57 MC |
220 | OSSL_PARAM_END |
221 | }; | |
222 | static const OSSL_PARAM *ecx_imexport_types(int selection) | |
223 | { | |
224 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
225 | return ecx_key_types; | |
226 | return NULL; | |
227 | } | |
228 | ||
96ebe52e | 229 | static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits, |
90d3cb57 MC |
230 | int size) |
231 | { | |
96ebe52e | 232 | ECX_KEY *ecx = key; |
90d3cb57 MC |
233 | OSSL_PARAM *p; |
234 | ||
235 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL | |
236 | && !OSSL_PARAM_set_int(p, bits)) | |
237 | return 0; | |
238 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL | |
239 | && !OSSL_PARAM_set_int(p, secbits)) | |
240 | return 0; | |
241 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL | |
242 | && !OSSL_PARAM_set_int(p, size)) | |
243 | return 0; | |
6a9bd929 MC |
244 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT)) != NULL |
245 | && (ecx->type == ECX_KEY_TYPE_X25519 | |
246 | || ecx->type == ECX_KEY_TYPE_X448)) { | |
247 | if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen)) | |
248 | return 0; | |
249 | } | |
250 | ||
96ebe52e | 251 | return key_to_params(ecx, NULL, params); |
90d3cb57 MC |
252 | } |
253 | ||
1a7328c8 RL |
254 | static int ed_get_params(void *key, OSSL_PARAM params[]) |
255 | { | |
256 | OSSL_PARAM *p; | |
257 | ||
258 | if ((p = OSSL_PARAM_locate(params, | |
259 | OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL | |
260 | && !OSSL_PARAM_set_utf8_string(p, "")) | |
261 | return 0; | |
262 | return 1; | |
263 | } | |
264 | ||
90d3cb57 MC |
265 | static int x25519_get_params(void *key, OSSL_PARAM params[]) |
266 | { | |
96ebe52e SL |
267 | return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS, |
268 | X25519_KEYLEN); | |
90d3cb57 MC |
269 | } |
270 | ||
271 | static int x448_get_params(void *key, OSSL_PARAM params[]) | |
272 | { | |
96ebe52e SL |
273 | return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS, |
274 | X448_KEYLEN); | |
90d3cb57 MC |
275 | } |
276 | ||
af6d8dd3 MC |
277 | static int ed25519_get_params(void *key, OSSL_PARAM params[]) |
278 | { | |
96ebe52e | 279 | return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS, |
1a7328c8 RL |
280 | ED25519_KEYLEN) |
281 | && ed_get_params(key, params); | |
af6d8dd3 MC |
282 | } |
283 | ||
284 | static int ed448_get_params(void *key, OSSL_PARAM params[]) | |
285 | { | |
96ebe52e | 286 | return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS, |
1a7328c8 RL |
287 | ED448_KEYLEN) |
288 | && ed_get_params(key, params); | |
af6d8dd3 MC |
289 | } |
290 | ||
6a9bd929 | 291 | static const OSSL_PARAM ecx_gettable_params[] = { |
1a7328c8 RL |
292 | OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), |
293 | OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), | |
294 | OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), | |
295 | OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0), | |
6a9bd929 | 296 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0), |
1a7328c8 RL |
297 | ECX_KEY_TYPES(), |
298 | OSSL_PARAM_END | |
299 | }; | |
300 | ||
6a9bd929 | 301 | static const OSSL_PARAM ed_gettable_params[] = { |
90d3cb57 MC |
302 | OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), |
303 | OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), | |
304 | OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), | |
96ebe52e | 305 | ECX_KEY_TYPES(), |
90d3cb57 MC |
306 | OSSL_PARAM_END |
307 | }; | |
308 | ||
1a7328c8 RL |
309 | static const OSSL_PARAM *x25519_gettable_params(void) |
310 | { | |
6a9bd929 | 311 | return ecx_gettable_params; |
1a7328c8 RL |
312 | } |
313 | ||
314 | static const OSSL_PARAM *x448_gettable_params(void) | |
90d3cb57 | 315 | { |
6a9bd929 | 316 | return ecx_gettable_params; |
90d3cb57 MC |
317 | } |
318 | ||
1a7328c8 RL |
319 | static const OSSL_PARAM *ed25519_gettable_params(void) |
320 | { | |
6a9bd929 | 321 | return ed_gettable_params; |
1a7328c8 RL |
322 | } |
323 | ||
324 | static const OSSL_PARAM *ed448_gettable_params(void) | |
325 | { | |
6a9bd929 MC |
326 | return ed_gettable_params; |
327 | } | |
328 | ||
329 | static int ecx_set_params(void *key, const OSSL_PARAM params[]) | |
330 | { | |
331 | ECX_KEY *ecxkey = key; | |
332 | const OSSL_PARAM *p; | |
333 | ||
334 | p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT); | |
335 | if (p != NULL) { | |
336 | void *buf = ecxkey->pubkey; | |
337 | ||
338 | if (p->data_size != ecxkey->keylen | |
339 | || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey), | |
340 | NULL)) | |
341 | return 0; | |
342 | OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen); | |
343 | ecxkey->privkey = NULL; | |
344 | ecxkey->haspubkey = 1; | |
345 | } | |
346 | ||
347 | return 1; | |
348 | } | |
349 | ||
350 | static int x25519_set_params(void *key, const OSSL_PARAM params[]) | |
351 | { | |
352 | return ecx_set_params(key, params); | |
353 | } | |
354 | ||
355 | static int x448_set_params(void *key, const OSSL_PARAM params[]) | |
356 | { | |
357 | return ecx_set_params(key, params); | |
358 | } | |
359 | ||
360 | static int ed25519_set_params(void *key, const OSSL_PARAM params[]) | |
361 | { | |
362 | return 1; | |
363 | } | |
364 | ||
365 | static int ed448_set_params(void *key, const OSSL_PARAM params[]) | |
366 | { | |
367 | return 1; | |
368 | } | |
369 | ||
370 | static const OSSL_PARAM ecx_settable_params[] = { | |
371 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0), | |
372 | OSSL_PARAM_END | |
373 | }; | |
374 | ||
375 | static const OSSL_PARAM ed_settable_params[] = { | |
376 | OSSL_PARAM_END | |
377 | }; | |
378 | ||
379 | static const OSSL_PARAM *x25519_settable_params(void) | |
380 | { | |
381 | return ecx_settable_params; | |
382 | } | |
383 | ||
384 | static const OSSL_PARAM *x448_settable_params(void) | |
385 | { | |
386 | return ecx_settable_params; | |
387 | } | |
388 | ||
389 | static const OSSL_PARAM *ed25519_settable_params(void) | |
390 | { | |
391 | return ed_settable_params; | |
392 | } | |
393 | ||
394 | static const OSSL_PARAM *ed448_settable_params(void) | |
395 | { | |
396 | return ed_settable_params; | |
1a7328c8 RL |
397 | } |
398 | ||
43cd3701 P |
399 | static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type) |
400 | { | |
401 | OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); | |
402 | struct ecx_gen_ctx *gctx = NULL; | |
403 | ||
404 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) | |
405 | return NULL; | |
406 | ||
407 | if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) { | |
408 | gctx->libctx = libctx; | |
409 | gctx->type = type; | |
410 | } | |
411 | return gctx; | |
412 | } | |
413 | ||
414 | static void *x25519_gen_init(void *provctx, int selection) | |
415 | { | |
416 | return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519); | |
417 | } | |
418 | ||
419 | static void *x448_gen_init(void *provctx, int selection) | |
420 | { | |
421 | return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448); | |
422 | } | |
423 | ||
424 | static void *ed25519_gen_init(void *provctx, int selection) | |
425 | { | |
426 | return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519); | |
427 | } | |
428 | ||
429 | static void *ed448_gen_init(void *provctx, int selection) | |
430 | { | |
431 | return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448); | |
432 | } | |
433 | ||
434 | static void *ecx_gen(struct ecx_gen_ctx *gctx) | |
435 | { | |
436 | ECX_KEY *key; | |
437 | unsigned char *privkey; | |
438 | ||
c1e48c51 P |
439 | if (gctx == NULL) |
440 | return NULL; | |
f3336f40 | 441 | if ((key = ecx_key_new(gctx->libctx, gctx->type, 0)) == NULL) { |
c1e48c51 | 442 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 | 443 | return NULL; |
c1e48c51 P |
444 | } |
445 | if ((privkey = ecx_key_allocate_privkey(key)) == NULL) { | |
446 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
447 | goto err; | |
448 | } | |
449 | if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0) | |
43cd3701 P |
450 | goto err; |
451 | switch (gctx->type) { | |
452 | case ECX_KEY_TYPE_X25519: | |
453 | privkey[0] &= 248; | |
454 | privkey[X25519_KEYLEN - 1] &= 127; | |
455 | privkey[X25519_KEYLEN - 1] |= 64; | |
456 | X25519_public_from_private(key->pubkey, privkey); | |
457 | break; | |
458 | case ECX_KEY_TYPE_X448: | |
459 | privkey[0] &= 252; | |
460 | privkey[X448_KEYLEN - 1] |= 128; | |
461 | X448_public_from_private(key->pubkey, privkey); | |
462 | break; | |
463 | case ECX_KEY_TYPE_ED25519: | |
464 | if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey)) | |
465 | goto err; | |
466 | break; | |
467 | case ECX_KEY_TYPE_ED448: | |
468 | if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey)) | |
469 | goto err; | |
470 | break; | |
471 | } | |
472 | return key; | |
473 | err: | |
474 | ecx_key_free(key); | |
475 | return NULL; | |
476 | } | |
477 | ||
478 | static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) | |
479 | { | |
480 | struct ecx_gen_ctx *gctx = genctx; | |
481 | ||
482 | #ifdef S390X_EC_ASM | |
483 | if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) | |
484 | return s390x_ecx_keygen25519(gctx); | |
485 | #endif | |
486 | return ecx_gen(gctx); | |
487 | } | |
488 | ||
489 | static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) | |
490 | { | |
491 | struct ecx_gen_ctx *gctx = genctx; | |
492 | ||
493 | #ifdef S390X_EC_ASM | |
494 | if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) | |
495 | return s390x_ecx_keygen448(gctx); | |
496 | #endif | |
497 | return ecx_gen(gctx); | |
498 | } | |
499 | ||
500 | static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) | |
501 | { | |
502 | struct ecx_gen_ctx *gctx = genctx; | |
503 | #ifdef S390X_EC_ASM | |
504 | if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519) | |
505 | && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519) | |
506 | && OPENSSL_s390xcap_P.kdsa[0] | |
507 | & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) | |
508 | return s390x_ecd_keygen25519(gctx); | |
509 | #endif | |
510 | return ecx_gen(gctx); | |
511 | } | |
512 | ||
513 | static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) | |
514 | { | |
515 | struct ecx_gen_ctx *gctx = genctx; | |
516 | ||
517 | #ifdef S390X_EC_ASM | |
518 | if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448) | |
519 | && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448) | |
520 | && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) | |
521 | return s390x_ecd_keygen448(gctx); | |
522 | #endif | |
523 | return ecx_gen(gctx); | |
524 | } | |
525 | ||
526 | static void ecx_gen_cleanup(void *genctx) | |
527 | { | |
528 | struct ecx_gen_ctx *gctx = genctx; | |
529 | ||
530 | OPENSSL_free(gctx); | |
531 | } | |
532 | ||
af6d8dd3 MC |
533 | #define MAKE_KEYMGMT_FUNCTIONS(alg) \ |
534 | const OSSL_DISPATCH alg##_keymgmt_functions[] = { \ | |
535 | { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \ | |
536 | { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \ | |
537 | { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \ | |
1a7328c8 | 538 | { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \ |
6a9bd929 MC |
539 | { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \ |
540 | { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \ | |
af6d8dd3 | 541 | { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \ |
262ff123 | 542 | { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \ |
af6d8dd3 MC |
543 | { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \ |
544 | { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ | |
545 | { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \ | |
546 | { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ | |
43cd3701 P |
547 | { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \ |
548 | { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \ | |
549 | { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \ | |
af6d8dd3 MC |
550 | { 0, NULL } \ |
551 | }; | |
552 | ||
553 | MAKE_KEYMGMT_FUNCTIONS(x25519) | |
554 | MAKE_KEYMGMT_FUNCTIONS(x448) | |
555 | MAKE_KEYMGMT_FUNCTIONS(ed25519) | |
556 | MAKE_KEYMGMT_FUNCTIONS(ed448) | |
43cd3701 P |
557 | |
558 | #ifdef S390X_EC_ASM | |
559 | # include "s390x_arch.h" | |
43cd3701 P |
560 | |
561 | static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx) | |
562 | { | |
563 | static const unsigned char generator[] = { | |
564 | 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
565 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
566 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
567 | }; | |
f3336f40 | 568 | ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1); |
43cd3701 P |
569 | unsigned char *privkey = NULL, *pubkey; |
570 | ||
571 | if (key == NULL) { | |
c1e48c51 | 572 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
573 | goto err; |
574 | } | |
575 | ||
576 | pubkey = key->pubkey; | |
577 | ||
578 | privkey = ecx_key_allocate_privkey(key); | |
579 | if (privkey == NULL) { | |
c1e48c51 | 580 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
581 | goto err; |
582 | } | |
583 | ||
c1e48c51 | 584 | if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0) |
43cd3701 P |
585 | goto err; |
586 | ||
587 | privkey[0] &= 248; | |
588 | privkey[31] &= 127; | |
589 | privkey[31] |= 64; | |
590 | ||
591 | if (s390x_x25519_mul(pubkey, generator, privkey) != 1) | |
592 | goto err; | |
43cd3701 P |
593 | return key; |
594 | err: | |
595 | ecx_key_free(key); | |
596 | return NULL; | |
597 | } | |
598 | ||
599 | static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx) | |
600 | { | |
601 | static const unsigned char generator[] = { | |
602 | 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
604 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
605 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
607 | }; | |
f3336f40 | 608 | ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1); |
43cd3701 P |
609 | unsigned char *privkey = NULL, *pubkey; |
610 | ||
611 | if (key == NULL) { | |
c1e48c51 | 612 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
613 | goto err; |
614 | } | |
615 | ||
616 | pubkey = key->pubkey; | |
617 | ||
618 | privkey = ecx_key_allocate_privkey(key); | |
619 | if (privkey == NULL) { | |
c1e48c51 | 620 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
621 | goto err; |
622 | } | |
623 | ||
c1e48c51 | 624 | if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0) |
43cd3701 P |
625 | goto err; |
626 | ||
627 | privkey[0] &= 252; | |
628 | privkey[55] |= 128; | |
629 | ||
630 | if (s390x_x448_mul(pubkey, generator, privkey) != 1) | |
631 | goto err; | |
43cd3701 P |
632 | return key; |
633 | err: | |
634 | ecx_key_free(key); | |
635 | return NULL; | |
636 | } | |
637 | ||
638 | static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx) | |
639 | { | |
640 | static const unsigned char generator_x[] = { | |
641 | 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, | |
642 | 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, | |
643 | 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 | |
644 | }; | |
645 | static const unsigned char generator_y[] = { | |
646 | 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | |
647 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | |
648 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | |
649 | }; | |
650 | unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH]; | |
f3336f40 | 651 | ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1); |
43cd3701 P |
652 | unsigned char *privkey = NULL, *pubkey; |
653 | unsigned int sz; | |
c1e48c51 P |
654 | EVP_MD *sha = NULL; |
655 | int j; | |
43cd3701 P |
656 | |
657 | if (key == NULL) { | |
c1e48c51 | 658 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
659 | goto err; |
660 | } | |
661 | ||
662 | pubkey = key->pubkey; | |
663 | ||
664 | privkey = ecx_key_allocate_privkey(key); | |
665 | if (privkey == NULL) { | |
c1e48c51 | 666 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
667 | goto err; |
668 | } | |
669 | ||
c1e48c51 | 670 | if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0) |
43cd3701 P |
671 | goto err; |
672 | ||
c1e48c51 P |
673 | sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL); |
674 | if (sha == NULL) | |
675 | goto err; | |
676 | j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL); | |
677 | EVP_MD_free(sha); | |
678 | if (!j) | |
43cd3701 P |
679 | goto err; |
680 | ||
681 | buff[0] &= 248; | |
682 | buff[31] &= 63; | |
683 | buff[31] |= 64; | |
684 | ||
685 | if (s390x_ed25519_mul(x_dst, pubkey, | |
686 | generator_x, generator_y, buff) != 1) | |
687 | goto err; | |
688 | ||
689 | pubkey[31] |= ((x_dst[0] & 0x01) << 7); | |
690 | return key; | |
691 | err: | |
692 | ecx_key_free(key); | |
693 | return NULL; | |
694 | } | |
695 | ||
696 | static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx) | |
697 | { | |
698 | static const unsigned char generator_x[] = { | |
699 | 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b, | |
700 | 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, | |
701 | 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47, | |
702 | 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, | |
703 | 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00 | |
704 | }; | |
705 | static const unsigned char generator_y[] = { | |
706 | 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e, | |
707 | 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, | |
708 | 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c, | |
709 | 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, | |
710 | 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00 | |
711 | }; | |
712 | unsigned char x_dst[57], buff[114]; | |
f3336f40 | 713 | ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1); |
43cd3701 P |
714 | unsigned char *privkey = NULL, *pubkey; |
715 | EVP_MD_CTX *hashctx = NULL; | |
c1e48c51 | 716 | EVP_MD *shake = NULL; |
43cd3701 P |
717 | |
718 | if (key == NULL) { | |
c1e48c51 | 719 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
720 | goto err; |
721 | } | |
722 | ||
723 | pubkey = key->pubkey; | |
724 | ||
725 | privkey = ecx_key_allocate_privkey(key); | |
726 | if (privkey == NULL) { | |
c1e48c51 | 727 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
43cd3701 P |
728 | goto err; |
729 | } | |
730 | ||
c1e48c51 P |
731 | shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL); |
732 | if (shake == NULL) | |
733 | goto err; | |
734 | if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0) | |
43cd3701 P |
735 | goto err; |
736 | ||
737 | hashctx = EVP_MD_CTX_new(); | |
738 | if (hashctx == NULL) | |
739 | goto err; | |
c1e48c51 | 740 | if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1) |
43cd3701 P |
741 | goto err; |
742 | if (EVP_DigestUpdate(hashctx, privkey, 57) != 1) | |
743 | goto err; | |
744 | if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1) | |
745 | goto err; | |
746 | ||
747 | buff[0] &= -4; | |
748 | buff[55] |= 0x80; | |
749 | buff[56] = 0; | |
750 | ||
751 | if (s390x_ed448_mul(x_dst, pubkey, | |
752 | generator_x, generator_y, buff) != 1) | |
753 | goto err; | |
754 | ||
755 | pubkey[56] |= ((x_dst[0] & 0x01) << 7); | |
43cd3701 | 756 | EVP_MD_CTX_free(hashctx); |
c1e48c51 | 757 | EVP_MD_free(shake); |
43cd3701 P |
758 | return key; |
759 | err: | |
760 | ecx_key_free(key); | |
761 | EVP_MD_CTX_free(hashctx); | |
c1e48c51 | 762 | EVP_MD_free(shake); |
43cd3701 P |
763 | return NULL; |
764 | } | |
765 | #endif |