]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ecx_meth.c
Add X25519/X448 Key Exchange to the default provider
[thirdparty/openssl.git] / crypto / ec / ecx_meth.c
CommitLineData
756b198d 1/*
b0edda11 2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
756b198d 3 *
a7f182b7 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
756b198d
DSH
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
579422c8
P
10/*
11 * ECDSA low level APIs are deprecated for public use, but still ok for
12 * internal use.
13 */
14#include "internal/deprecated.h"
15
756b198d
DSH
16#include <stdio.h>
17#include "internal/cryptlib.h"
18#include <openssl/x509.h>
19#include <openssl/ec.h>
20#include <openssl/rand.h>
6f7d2135
MC
21#include <openssl/core_names.h>
22#include "internal/param_build.h"
25f2138b
DMSP
23#include "crypto/asn1.h"
24#include "crypto/evp.h"
4de88fe6 25#include "crypto/ecx.h"
706457b7
DMSP
26#include "ec_local.h"
27#include "curve448/curve448_local.h"
756b198d 28
13735cfe
MC
29#define ISX448(id) ((id) == EVP_PKEY_X448)
30#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
31#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
32 : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
33 : ED448_KEYLEN))
34#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
35
756b198d
DSH
36
37typedef enum {
13735cfe
MC
38 KEY_OP_PUBLIC,
39 KEY_OP_PRIVATE,
40 KEY_OP_KEYGEN
756b198d
DSH
41} ecx_key_op_t;
42
43/* Setup EVP_PKEY using public, private or generation */
42a3008a 44static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
756b198d
DSH
45 const unsigned char *p, int plen, ecx_key_op_t op)
46{
13735cfe
MC
47 ECX_KEY *key = NULL;
48 unsigned char *privkey, *pubkey;
756b198d 49
13735cfe 50 if (op != KEY_OP_KEYGEN) {
5d6aaf8a
DSH
51 if (palg != NULL) {
52 int ptype;
53
54 /* Algorithm parameters must be absent */
55 X509_ALGOR_get0(NULL, &ptype, NULL, palg);
56 if (ptype != V_ASN1_UNDEF) {
57 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
58 return 0;
59 }
756b198d
DSH
60 }
61
13735cfe 62 if (p == NULL || plen != KEYLENID(id)) {
756b198d
DSH
63 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
64 return 0;
65 }
66 }
67
4de88fe6 68 key = ecx_key_new(KEYLENID(id), 1);
13735cfe 69 if (key == NULL) {
756b198d
DSH
70 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
71 return 0;
72 }
13735cfe 73 pubkey = key->pubkey;
756b198d 74
13735cfe
MC
75 if (op == KEY_OP_PUBLIC) {
76 memcpy(pubkey, p, plen);
756b198d 77 } else {
4de88fe6 78 privkey = ecx_key_allocate_privkey(key);
13735cfe 79 if (privkey == NULL) {
756b198d 80 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
13735cfe 81 goto err;
756b198d 82 }
13735cfe 83 if (op == KEY_OP_KEYGEN) {
4de88fe6 84 if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0)
13735cfe 85 goto err;
d2916a5b 86 if (id == EVP_PKEY_X25519) {
13735cfe
MC
87 privkey[0] &= 248;
88 privkey[X25519_KEYLEN - 1] &= 127;
89 privkey[X25519_KEYLEN - 1] |= 64;
90 } else if (id == EVP_PKEY_X448) {
91 privkey[0] &= 252;
92 privkey[X448_KEYLEN - 1] |= 128;
8ecade8b 93 }
756b198d 94 } else {
13735cfe
MC
95 memcpy(privkey, p, KEYLENID(id));
96 }
97 switch (id) {
98 case EVP_PKEY_X25519:
99 X25519_public_from_private(pubkey, privkey);
100 break;
101 case EVP_PKEY_ED25519:
102 ED25519_public_from_private(pubkey, privkey);
103 break;
104 case EVP_PKEY_X448:
105 X448_public_from_private(pubkey, privkey);
106 break;
107 case EVP_PKEY_ED448:
a9612d6c
MC
108 /*
109 * TODO(3.0): We set the library context to NULL for now. This will
110 * need to change.
111 */
112 ED448_public_from_private(NULL, pubkey, privkey);
13735cfe 113 break;
756b198d 114 }
756b198d
DSH
115 }
116
13735cfe 117 EVP_PKEY_assign(pkey, id, key);
756b198d 118 return 1;
13735cfe 119 err:
4de88fe6 120 ecx_key_free(key);
13735cfe 121 return 0;
756b198d
DSH
122}
123
124static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
125{
13735cfe 126 const ECX_KEY *ecxkey = pkey->pkey.ecx;
756b198d
DSH
127 unsigned char *penc;
128
13735cfe 129 if (ecxkey == NULL) {
756b198d
DSH
130 ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
131 return 0;
132 }
133
13735cfe 134 penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
756b198d
DSH
135 if (penc == NULL) {
136 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
137 return 0;
138 }
139
8ecade8b 140 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
13735cfe 141 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
756b198d
DSH
142 OPENSSL_free(penc);
143 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
144 return 0;
145 }
146 return 1;
147}
148
149static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
150{
151 const unsigned char *p;
152 int pklen;
153 X509_ALGOR *palg;
154
155 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
156 return 0;
42a3008a 157 return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
13735cfe 158 KEY_OP_PUBLIC);
756b198d
DSH
159}
160
161static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
162{
13735cfe
MC
163 const ECX_KEY *akey = a->pkey.ecx;
164 const ECX_KEY *bkey = b->pkey.ecx;
756b198d
DSH
165
166 if (akey == NULL || bkey == NULL)
167 return -2;
13735cfe
MC
168
169 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
756b198d
DSH
170}
171
245c6bc3 172static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
756b198d
DSH
173{
174 const unsigned char *p;
175 int plen;
176 ASN1_OCTET_STRING *oct = NULL;
245c6bc3 177 const X509_ALGOR *palg;
756b198d
DSH
178 int rv;
179
180 if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
181 return 0;
182
183 oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
184 if (oct == NULL) {
185 p = NULL;
186 plen = 0;
187 } else {
17ebf85a 188 p = ASN1_STRING_get0_data(oct);
756b198d
DSH
189 plen = ASN1_STRING_length(oct);
190 }
191
13735cfe 192 rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE);
6ef03ea9 193 ASN1_STRING_clear_free(oct);
756b198d
DSH
194 return rv;
195}
196
197static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
198{
13735cfe 199 const ECX_KEY *ecxkey = pkey->pkey.ecx;
756b198d
DSH
200 ASN1_OCTET_STRING oct;
201 unsigned char *penc = NULL;
202 int penclen;
203
13735cfe 204 if (ecxkey == NULL || ecxkey->privkey == NULL) {
756b198d
DSH
205 ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
206 return 0;
207 }
208
13735cfe
MC
209 oct.data = ecxkey->privkey;
210 oct.length = KEYLEN(pkey);
756b198d
DSH
211 oct.flags = 0;
212
213 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
214 if (penclen < 0) {
215 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
216 return 0;
217 }
218
8ecade8b 219 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
756b198d
DSH
220 V_ASN1_UNDEF, NULL, penc, penclen)) {
221 OPENSSL_clear_free(penc, penclen);
222 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
223 return 0;
224 }
225
226 return 1;
227}
228
229static int ecx_size(const EVP_PKEY *pkey)
230{
13735cfe 231 return KEYLEN(pkey);
756b198d
DSH
232}
233
234static int ecx_bits(const EVP_PKEY *pkey)
235{
13735cfe
MC
236 if (IS25519(pkey->ameth->pkey_id)) {
237 return X25519_BITS;
238 } else if(ISX448(pkey->ameth->pkey_id)) {
239 return X448_BITS;
240 } else {
241 return ED448_BITS;
242 }
756b198d
DSH
243}
244
245static int ecx_security_bits(const EVP_PKEY *pkey)
246{
13735cfe
MC
247 if (IS25519(pkey->ameth->pkey_id)) {
248 return X25519_SECURITY_BITS;
249 } else {
250 return X448_SECURITY_BITS;
251 }
756b198d
DSH
252}
253
254static void ecx_free(EVP_PKEY *pkey)
255{
4de88fe6 256 ecx_key_free(pkey->pkey.ecx);
756b198d
DSH
257}
258
259/* "parameters" are always equal */
260static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
261{
262 return 1;
263}
264
265static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
266 ASN1_PCTX *ctx, ecx_key_op_t op)
267{
13735cfe 268 const ECX_KEY *ecxkey = pkey->pkey.ecx;
8ecade8b
DSH
269 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
270
13735cfe
MC
271 if (op == KEY_OP_PRIVATE) {
272 if (ecxkey == NULL || ecxkey->privkey == NULL) {
756b198d
DSH
273 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
274 return 0;
275 return 1;
276 }
8ecade8b 277 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
756b198d
DSH
278 return 0;
279 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
280 return 0;
13735cfe
MC
281 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
282 indent + 4) == 0)
756b198d
DSH
283 return 0;
284 } else {
13735cfe 285 if (ecxkey == NULL) {
756b198d
DSH
286 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
287 return 0;
288 return 1;
289 }
8ecade8b 290 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
756b198d
DSH
291 return 0;
292 }
293 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
294 return 0;
13735cfe
MC
295
296 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
297 indent + 4) == 0)
756b198d
DSH
298 return 0;
299 return 1;
300}
301
302static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
303 ASN1_PCTX *ctx)
304{
13735cfe 305 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
756b198d
DSH
306}
307
308static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
309 ASN1_PCTX *ctx)
310{
13735cfe 311 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
756b198d
DSH
312}
313
314static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
315{
5d6aaf8a
DSH
316 switch (op) {
317
318 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
13735cfe
MC
319 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
320 KEY_OP_PUBLIC);
5d6aaf8a
DSH
321
322 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
13735cfe 323 if (pkey->pkey.ecx != NULL) {
5d6aaf8a 324 unsigned char **ppt = arg2;
13735cfe
MC
325
326 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
5d6aaf8a 327 if (*ppt != NULL)
13735cfe 328 return KEYLEN(pkey);
5d6aaf8a
DSH
329 }
330 return 0;
331
aabbc24e
MC
332 default:
333 return -2;
334
335 }
336}
337
338static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
339{
340 switch (op) {
5d6aaf8a 341 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
aabbc24e
MC
342 /* We currently only support Pure EdDSA which takes no digest */
343 *(int *)arg2 = NID_undef;
5d6aaf8a
DSH
344 return 2;
345
346 default:
347 return -2;
348
349 }
756b198d
DSH
350}
351
cc8b15c7
MC
352static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
353 size_t len)
354{
355 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
356 KEY_OP_PRIVATE);
357}
358
359static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
360{
361 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
362 KEY_OP_PUBLIC);
363}
364
0d124b0a
MC
365static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
366 size_t *len)
367{
368 const ECX_KEY *key = pkey->pkey.ecx;
369
370 if (priv == NULL) {
371 *len = KEYLENID(pkey->ameth->pkey_id);
372 return 1;
373 }
374
375 if (key == NULL
376 || key->privkey == NULL
377 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
378 return 0;
379
380 *len = KEYLENID(pkey->ameth->pkey_id);
381 memcpy(priv, key->privkey, *len);
382
383 return 1;
384}
385
386static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
387 size_t *len)
388{
389 const ECX_KEY *key = pkey->pkey.ecx;
390
391 if (pub == NULL) {
392 *len = KEYLENID(pkey->ameth->pkey_id);
393 return 1;
394 }
395
396 if (key == NULL
397 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
398 return 0;
399
400 *len = KEYLENID(pkey->ameth->pkey_id);
401 memcpy(pub, key->pubkey, *len);
402
403 return 1;
404}
405
6f7d2135
MC
406static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
407{
408 /*
409 * We provide no mechanism to "update" an ECX key once it has been set,
410 * therefore we do not have to maintain a dirty count.
411 */
412 return 1;
413}
414
415static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
416 EVP_KEYMGMT *to_keymgmt)
417{
418 const ECX_KEY *key = from->pkey.ecx;
419 OSSL_PARAM_BLD tmpl;
420 OSSL_PARAM *params = NULL;
421 int rv = 0;
422
423 ossl_param_bld_init(&tmpl);
424
425 /* A key must at least have a public part */
426 if (!ossl_param_bld_push_octet_string(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
427 key->pubkey, key->keylen))
428 goto err;
429
430 if (key->privkey != NULL) {
431 if (!ossl_param_bld_push_octet_string(&tmpl,
432 OSSL_PKEY_PARAM_PRIV_KEY,
433 key->privkey, key->keylen))
434 goto err;
435 }
436
437 params = ossl_param_bld_to_param(&tmpl);
438
439 /* We export, the provider imports */
440 rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
441 params);
442
443 err:
444 ossl_param_bld_free(params);
445 return rv;
446}
447
756b198d 448const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
d2916a5b
DSH
449 EVP_PKEY_X25519,
450 EVP_PKEY_X25519,
756b198d
DSH
451 0,
452 "X25519",
453 "OpenSSL X25519 algorithm",
454
455 ecx_pub_decode,
456 ecx_pub_encode,
457 ecx_pub_cmp,
458 ecx_pub_print,
459
460 ecx_priv_decode,
461 ecx_priv_encode,
462 ecx_priv_print,
463
464 ecx_size,
465 ecx_bits,
466 ecx_security_bits,
467
468 0, 0, 0, 0,
469 ecx_cmp_parameters,
470 0, 0,
471
472 ecx_free,
473 ecx_ctrl,
474 NULL,
cc8b15c7
MC
475 NULL,
476
477 NULL,
478 NULL,
479 NULL,
480
481 NULL,
482 NULL,
483 NULL,
484
485 ecx_set_priv_key,
486 ecx_set_pub_key,
0d124b0a
MC
487 ecx_get_priv_key,
488 ecx_get_pub_key,
6f7d2135
MC
489 ecx_pkey_dirty_cnt,
490 ecx_pkey_export_to
756b198d
DSH
491};
492
13735cfe
MC
493const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
494 EVP_PKEY_X448,
495 EVP_PKEY_X448,
496 0,
497 "X448",
498 "OpenSSL X448 algorithm",
499
500 ecx_pub_decode,
501 ecx_pub_encode,
502 ecx_pub_cmp,
503 ecx_pub_print,
504
505 ecx_priv_decode,
506 ecx_priv_encode,
507 ecx_priv_print,
508
509 ecx_size,
510 ecx_bits,
511 ecx_security_bits,
512
513 0, 0, 0, 0,
514 ecx_cmp_parameters,
515 0, 0,
516
517 ecx_free,
518 ecx_ctrl,
519 NULL,
cc8b15c7
MC
520 NULL,
521
522 NULL,
523 NULL,
524 NULL,
525
526 NULL,
527 NULL,
528 NULL,
529
530 ecx_set_priv_key,
531 ecx_set_pub_key,
0d124b0a
MC
532 ecx_get_priv_key,
533 ecx_get_pub_key,
6f7d2135
MC
534 ecx_pkey_dirty_cnt,
535 ecx_pkey_export_to
13735cfe
MC
536};
537
538static int ecd_size25519(const EVP_PKEY *pkey)
8ecade8b
DSH
539{
540 return ED25519_SIGSIZE;
541}
542
13735cfe
MC
543static int ecd_size448(const EVP_PKEY *pkey)
544{
545 return ED448_SIGSIZE;
546}
547
9f98fbad
DSH
548static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
549 X509_ALGOR *sigalg, ASN1_BIT_STRING *str,
550 EVP_PKEY *pkey)
551{
552 const ASN1_OBJECT *obj;
553 int ptype;
13735cfe 554 int nid;
9f98fbad 555
13735cfe 556 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
9f98fbad 557 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
13735cfe
MC
558 nid = OBJ_obj2nid(obj);
559 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
9f98fbad
DSH
560 ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING);
561 return 0;
562 }
563
564 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
565 return 0;
566
567 return 2;
568}
569
13735cfe
MC
570static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
571 X509_ALGOR *alg1, X509_ALGOR *alg2,
572 ASN1_BIT_STRING *str)
9f98fbad
DSH
573{
574 /* Set algorithms identifiers */
575 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
576 if (alg2)
577 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
c2969ff6 578 /* Algorithm identifiers set: carry on as normal */
9f98fbad
DSH
579 return 3;
580}
581
13735cfe
MC
582static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
583 const ASN1_STRING *sig)
684c41c8
DSH
584{
585 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
586 X509_SIG_INFO_TLS);
587 return 1;
588}
589
13735cfe
MC
590static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
591 X509_ALGOR *alg1, X509_ALGOR *alg2,
592 ASN1_BIT_STRING *str)
593{
594 /* Set algorithm identifier */
595 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
596 if (alg2 != NULL)
597 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
598 /* Algorithm identifier set: carry on as normal */
599 return 3;
600}
601
602static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
603 const ASN1_STRING *sig)
604{
605 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
606 X509_SIG_INFO_TLS);
607 return 1;
608}
609
610
8ecade8b 611const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
d2916a5b
DSH
612 EVP_PKEY_ED25519,
613 EVP_PKEY_ED25519,
8ecade8b
DSH
614 0,
615 "ED25519",
616 "OpenSSL ED25519 algorithm",
617
618 ecx_pub_decode,
619 ecx_pub_encode,
620 ecx_pub_cmp,
621 ecx_pub_print,
622
623 ecx_priv_decode,
624 ecx_priv_encode,
625 ecx_priv_print,
626
13735cfe
MC
627 ecd_size25519,
628 ecx_bits,
629 ecx_security_bits,
630
631 0, 0, 0, 0,
632 ecx_cmp_parameters,
633 0, 0,
634
635 ecx_free,
aabbc24e 636 ecd_ctrl,
13735cfe
MC
637 NULL,
638 NULL,
639 ecd_item_verify,
640 ecd_item_sign25519,
cc8b15c7
MC
641 ecd_sig_info_set25519,
642
643 NULL,
644 NULL,
645 NULL,
646
647 ecx_set_priv_key,
648 ecx_set_pub_key,
0d124b0a
MC
649 ecx_get_priv_key,
650 ecx_get_pub_key,
13735cfe
MC
651};
652
653const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
654 EVP_PKEY_ED448,
655 EVP_PKEY_ED448,
656 0,
657 "ED448",
658 "OpenSSL ED448 algorithm",
659
660 ecx_pub_decode,
661 ecx_pub_encode,
662 ecx_pub_cmp,
663 ecx_pub_print,
664
665 ecx_priv_decode,
666 ecx_priv_encode,
667 ecx_priv_print,
668
669 ecd_size448,
8ecade8b
DSH
670 ecx_bits,
671 ecx_security_bits,
672
673 0, 0, 0, 0,
674 ecx_cmp_parameters,
675 0, 0,
676
677 ecx_free,
aabbc24e 678 ecd_ctrl,
8ecade8b 679 NULL,
9f98fbad
DSH
680 NULL,
681 ecd_item_verify,
13735cfe 682 ecd_item_sign448,
cc8b15c7
MC
683 ecd_sig_info_set448,
684
685 NULL,
686 NULL,
687 NULL,
688
689 ecx_set_priv_key,
690 ecx_set_pub_key,
0d124b0a
MC
691 ecx_get_priv_key,
692 ecx_get_pub_key,
8ecade8b
DSH
693};
694
756b198d
DSH
695static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
696{
13735cfe 697 return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN);
756b198d
DSH
698}
699
13735cfe
MC
700static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
701 size_t *keylen,
702 const unsigned char **privkey,
703 const unsigned char **pubkey)
756b198d 704{
13735cfe 705 const ECX_KEY *ecxkey, *peerkey;
756b198d
DSH
706
707 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
13735cfe 708 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET);
756b198d
DSH
709 return 0;
710 }
13735cfe
MC
711 ecxkey = ctx->pkey->pkey.ecx;
712 peerkey = ctx->peerkey->pkey.ecx;
713 if (ecxkey == NULL || ecxkey->privkey == NULL) {
714 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
756b198d
DSH
715 return 0;
716 }
717 if (peerkey == NULL) {
13735cfe 718 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
756b198d
DSH
719 return 0;
720 }
13735cfe
MC
721 *privkey = ecxkey->privkey;
722 *pubkey = peerkey->pubkey;
723
724 return 1;
725}
726
727static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
728 size_t *keylen)
729{
730 const unsigned char *privkey, *pubkey;
731
732 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
733 || (key != NULL
734 && X25519(key, privkey, pubkey) == 0))
735 return 0;
756b198d 736 *keylen = X25519_KEYLEN;
13735cfe
MC
737 return 1;
738}
739
740static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
741 size_t *keylen)
742{
743 const unsigned char *privkey, *pubkey;
744
745 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
746 || (key != NULL
747 && X448(key, privkey, pubkey) == 0))
756b198d 748 return 0;
13735cfe 749 *keylen = X448_KEYLEN;
756b198d
DSH
750 return 1;
751}
752
753static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
754{
755 /* Only need to handle peer key for derivation */
756 if (type == EVP_PKEY_CTRL_PEER_KEY)
757 return 1;
758 return -2;
759}
760
19bd1fa1 761static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
d2916a5b 762 EVP_PKEY_X25519,
756b198d
DSH
763 0, 0, 0, 0, 0, 0, 0,
764 pkey_ecx_keygen,
765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe 766 pkey_ecx_derive25519,
756b198d
DSH
767 pkey_ecx_ctrl,
768 0
769};
42a3008a 770
19bd1fa1 771static const EVP_PKEY_METHOD ecx448_pkey_meth = {
13735cfe
MC
772 EVP_PKEY_X448,
773 0, 0, 0, 0, 0, 0, 0,
774 pkey_ecx_keygen,
775 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
776 pkey_ecx_derive448,
777 pkey_ecx_ctrl,
778 0
779};
780
07824f30
MC
781static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
782 size_t *siglen, const unsigned char *tbs,
783 size_t tbslen)
42a3008a 784{
07824f30 785 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
42a3008a
DSH
786
787 if (sig == NULL) {
788 *siglen = ED25519_SIGSIZE;
789 return 1;
790 }
791 if (*siglen < ED25519_SIGSIZE) {
07824f30 792 ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
42a3008a
DSH
793 return 0;
794 }
795
796 if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0)
797 return 0;
798 *siglen = ED25519_SIGSIZE;
799 return 1;
800}
801
07824f30
MC
802static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
803 size_t *siglen, const unsigned char *tbs,
804 size_t tbslen)
13735cfe 805{
07824f30 806 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
13735cfe
MC
807
808 if (sig == NULL) {
809 *siglen = ED448_SIGSIZE;
810 return 1;
811 }
812 if (*siglen < ED448_SIGSIZE) {
07824f30 813 ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
13735cfe
MC
814 return 0;
815 }
816
a9612d6c
MC
817 /*
818 * TODO(3.0): We use NULL for the library context for now. Will need to
819 * change later.
820 */
821 if (ED448_sign(NULL, sig, tbs, tbslen, edkey->pubkey, edkey->privkey,
822 NULL, 0) == 0)
13735cfe
MC
823 return 0;
824 *siglen = ED448_SIGSIZE;
825 return 1;
826}
827
07824f30
MC
828static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
829 size_t siglen, const unsigned char *tbs,
830 size_t tbslen)
42a3008a 831{
07824f30 832 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
42a3008a
DSH
833
834 if (siglen != ED25519_SIGSIZE)
835 return 0;
836
837 return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
838}
839
07824f30
MC
840static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
841 size_t siglen, const unsigned char *tbs,
842 size_t tbslen)
13735cfe 843{
07824f30 844 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
13735cfe
MC
845
846 if (siglen != ED448_SIGSIZE)
847 return 0;
848
a9612d6c
MC
849 /*
850 * TODO(3.0): We send NULL for the OPENSSL_CTX for now. This will need to
851 * change.
852 */
853 return ED448_verify(NULL, tbs, tbslen, sig, edkey->pubkey, NULL, 0);
13735cfe
MC
854}
855
42a3008a
DSH
856static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
857{
858 switch (type) {
859 case EVP_PKEY_CTRL_MD:
860 /* Only NULL allowed as digest */
f3021aca 861 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
42a3008a
DSH
862 return 1;
863 ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
864 return 0;
865
866 case EVP_PKEY_CTRL_DIGESTINIT:
867 return 1;
868 }
869 return -2;
870}
871
19bd1fa1 872static const EVP_PKEY_METHOD ed25519_pkey_meth = {
d2916a5b 873 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
42a3008a
DSH
874 0, 0, 0, 0, 0, 0,
875 pkey_ecx_keygen,
07824f30 876 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42a3008a
DSH
877 pkey_ecd_ctrl,
878 0,
13735cfe
MC
879 pkey_ecd_digestsign25519,
880 pkey_ecd_digestverify25519
881};
882
19bd1fa1 883static const EVP_PKEY_METHOD ed448_pkey_meth = {
13735cfe
MC
884 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
885 0, 0, 0, 0, 0, 0,
886 pkey_ecx_keygen,
07824f30 887 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe
MC
888 pkey_ecd_ctrl,
889 0,
890 pkey_ecd_digestsign448,
891 pkey_ecd_digestverify448
42a3008a 892};
19bd1fa1
PS
893
894#ifdef S390X_EC_ASM
895# include "s390x_arch.h"
677c4a01 896# include "internal/constant_time.h"
19bd1fa1
PS
897
898static void s390x_x25519_mod_p(unsigned char u[32])
899{
900 unsigned char u_red[32];
901 unsigned int c = 0;
902 int i;
903
904 memcpy(u_red, u, sizeof(u_red));
905
906 c += (unsigned int)u_red[31] + 19;
907 u_red[31] = (unsigned char)c;
908 c >>= 8;
909
677c4a01 910 for (i = 30; i >= 0; i--) {
19bd1fa1
PS
911 c += (unsigned int)u_red[i];
912 u_red[i] = (unsigned char)c;
913 c >>= 8;
914 }
915
677c4a01
PS
916 c = (u_red[0] & 0x80) >> 7;
917 u_red[0] &= 0x7f;
918 constant_time_cond_swap_buff(0 - (unsigned char)c,
919 u, u_red, sizeof(u_red));
19bd1fa1
PS
920}
921
922static void s390x_x448_mod_p(unsigned char u[56])
923{
924 unsigned char u_red[56];
925 unsigned int c = 0;
926 int i;
927
928 memcpy(u_red, u, sizeof(u_red));
929
930 c += (unsigned int)u_red[55] + 1;
931 u_red[55] = (unsigned char)c;
932 c >>= 8;
933
934 for (i = 54; i >= 28; i--) {
935 c += (unsigned int)u_red[i];
936 u_red[i] = (unsigned char)c;
937 c >>= 8;
938 }
939
940 c += (unsigned int)u_red[27] + 1;
941 u_red[27] = (unsigned char)c;
942 c >>= 8;
943
677c4a01 944 for (i = 26; i >= 0; i--) {
19bd1fa1
PS
945 c += (unsigned int)u_red[i];
946 u_red[i] = (unsigned char)c;
947 c >>= 8;
948 }
949
677c4a01
PS
950 constant_time_cond_swap_buff(0 - (unsigned char)c,
951 u, u_red, sizeof(u_red));
19bd1fa1
PS
952}
953
954static int s390x_x25519_mul(unsigned char u_dst[32],
955 const unsigned char u_src[32],
956 const unsigned char d_src[32])
957{
958 union {
959 struct {
960 unsigned char u_dst[32];
961 unsigned char u_src[32];
962 unsigned char d_src[32];
963 } x25519;
964 unsigned long long buff[512];
965 } param;
966 int rc;
967
968 memset(&param, 0, sizeof(param));
969
970 s390x_flip_endian32(param.x25519.u_src, u_src);
971 param.x25519.u_src[0] &= 0x7f;
972 s390x_x25519_mod_p(param.x25519.u_src);
973
974 s390x_flip_endian32(param.x25519.d_src, d_src);
975 param.x25519.d_src[31] &= 248;
976 param.x25519.d_src[0] &= 127;
977 param.x25519.d_src[0] |= 64;
978
979 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, &param.x25519) ? 0 : 1;
980 if (rc == 1)
981 s390x_flip_endian32(u_dst, param.x25519.u_dst);
982
983 OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
984 return rc;
985}
986
987static int s390x_x448_mul(unsigned char u_dst[56],
988 const unsigned char u_src[56],
989 const unsigned char d_src[56])
990{
991 union {
992 struct {
993 unsigned char u_dst[64];
994 unsigned char u_src[64];
995 unsigned char d_src[64];
996 } x448;
997 unsigned long long buff[512];
998 } param;
999 int rc;
1000
1001 memset(&param, 0, sizeof(param));
1002
1003 memcpy(param.x448.u_src, u_src, 56);
1004 memcpy(param.x448.d_src, d_src, 56);
1005
1006 s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
58738b1c 1007 s390x_x448_mod_p(param.x448.u_src + 8);
19bd1fa1
PS
1008
1009 s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
1010 param.x448.d_src[63] &= 252;
1011 param.x448.d_src[8] |= 128;
1012
1013 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, &param.x448) ? 0 : 1;
1014 if (rc == 1) {
1015 s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
1016 memcpy(u_dst, param.x448.u_dst, 56);
1017 }
1018
1019 OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
1020 return rc;
1021}
1022
1023static int s390x_ed25519_mul(unsigned char x_dst[32],
1024 unsigned char y_dst[32],
1025 const unsigned char x_src[32],
1026 const unsigned char y_src[32],
1027 const unsigned char d_src[32])
1028{
1029 union {
1030 struct {
1031 unsigned char x_dst[32];
1032 unsigned char y_dst[32];
1033 unsigned char x_src[32];
1034 unsigned char y_src[32];
1035 unsigned char d_src[32];
1036 } ed25519;
1037 unsigned long long buff[512];
1038 } param;
1039 int rc;
1040
1041 memset(&param, 0, sizeof(param));
1042
1043 s390x_flip_endian32(param.ed25519.x_src, x_src);
1044 s390x_flip_endian32(param.ed25519.y_src, y_src);
1045 s390x_flip_endian32(param.ed25519.d_src, d_src);
1046
1047 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, &param.ed25519) ? 0 : 1;
1048 if (rc == 1) {
1049 s390x_flip_endian32(x_dst, param.ed25519.x_dst);
1050 s390x_flip_endian32(y_dst, param.ed25519.y_dst);
1051 }
1052
1053 OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
1054 return rc;
1055}
1056
1057static int s390x_ed448_mul(unsigned char x_dst[57],
1058 unsigned char y_dst[57],
1059 const unsigned char x_src[57],
1060 const unsigned char y_src[57],
1061 const unsigned char d_src[57])
1062{
1063 union {
1064 struct {
1065 unsigned char x_dst[64];
1066 unsigned char y_dst[64];
1067 unsigned char x_src[64];
1068 unsigned char y_src[64];
1069 unsigned char d_src[64];
1070 } ed448;
1071 unsigned long long buff[512];
1072 } param;
1073 int rc;
1074
1075 memset(&param, 0, sizeof(param));
1076
1077 memcpy(param.ed448.x_src, x_src, 57);
1078 memcpy(param.ed448.y_src, y_src, 57);
1079 memcpy(param.ed448.d_src, d_src, 57);
1080 s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
1081 s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
1082 s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
1083
1084 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, &param.ed448) ? 0 : 1;
1085 if (rc == 1) {
1086 s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
1087 s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
1088 memcpy(x_dst, param.ed448.x_dst, 57);
1089 memcpy(y_dst, param.ed448.y_dst, 57);
1090 }
1091
1092 OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
1093 return rc;
1094}
1095
1096static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1097{
1098 static const unsigned char generator[] = {
1099 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1102 };
4de88fe6 1103 ECX_KEY *key = ecx_key_new(X25519_KEYLEN, 1);
19bd1fa1
PS
1104 unsigned char *privkey = NULL, *pubkey;
1105
19bd1fa1
PS
1106 if (key == NULL) {
1107 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1108 goto err;
1109 }
1110
1111 pubkey = key->pubkey;
1112
4de88fe6 1113 privkey = ecx_key_allocate_privkey(key);
19bd1fa1
PS
1114 if (privkey == NULL) {
1115 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1116 goto err;
1117 }
1118
1119 if (RAND_priv_bytes(privkey, X25519_KEYLEN) <= 0)
1120 goto err;
1121
1122 privkey[0] &= 248;
1123 privkey[31] &= 127;
1124 privkey[31] |= 64;
1125
1126 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1127 goto err;
1128
1129 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1130 return 1;
1131 err:
4de88fe6 1132 ecx_key_free(key);
19bd1fa1
PS
1133 return 0;
1134}
1135
1136static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1137{
1138 static const unsigned char generator[] = {
1139 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1144 };
4de88fe6 1145 ECX_KEY *key = ecx_key_new(X448_KEYLEN, 1);
19bd1fa1
PS
1146 unsigned char *privkey = NULL, *pubkey;
1147
19bd1fa1
PS
1148 if (key == NULL) {
1149 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1150 goto err;
1151 }
1152
1153 pubkey = key->pubkey;
1154
4de88fe6 1155 privkey = ecx_key_allocate_privkey(key);
19bd1fa1
PS
1156 if (privkey == NULL) {
1157 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1158 goto err;
1159 }
1160
1161 if (RAND_priv_bytes(privkey, X448_KEYLEN) <= 0)
1162 goto err;
1163
1164 privkey[0] &= 252;
1165 privkey[55] |= 128;
1166
1167 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1168 goto err;
1169
1170 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1171 return 1;
1172 err:
4de88fe6 1173 ecx_key_free(key);
19bd1fa1
PS
1174 return 0;
1175}
1176
1177static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1178{
1179 static const unsigned char generator_x[] = {
1180 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1181 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1182 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1183 };
1184 static const unsigned char generator_y[] = {
1185 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1186 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1187 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1188 };
1189 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
4de88fe6 1190 ECX_KEY *key = ecx_key_new(ED25519_KEYLEN, 1);
19bd1fa1 1191 unsigned char *privkey = NULL, *pubkey;
85d843c8 1192 unsigned int sz;
19bd1fa1 1193
19bd1fa1
PS
1194 if (key == NULL) {
1195 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1196 goto err;
1197 }
1198
1199 pubkey = key->pubkey;
1200
4de88fe6 1201 privkey = ecx_key_allocate_privkey(key);
19bd1fa1
PS
1202 if (privkey == NULL) {
1203 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1204 goto err;
1205 }
1206
1207 if (RAND_priv_bytes(privkey, ED25519_KEYLEN) <= 0)
1208 goto err;
1209
85d843c8
P
1210 if (!EVP_Digest(privkey, 32, buff, &sz, EVP_sha512(), NULL))
1211 goto err;
1212
19bd1fa1
PS
1213 buff[0] &= 248;
1214 buff[31] &= 63;
1215 buff[31] |= 64;
1216
1217 if (s390x_ed25519_mul(x_dst, pubkey,
1218 generator_x, generator_y, buff) != 1)
1219 goto err;
1220
1221 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1222
1223 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1224 return 1;
1225 err:
4de88fe6 1226 ecx_key_free(key);
19bd1fa1
PS
1227 return 0;
1228}
1229
1230static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1231{
1232 static const unsigned char generator_x[] = {
1233 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1234 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1235 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1236 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1237 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1238 };
1239 static const unsigned char generator_y[] = {
1240 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1241 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1242 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1243 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1244 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1245 };
1246 unsigned char x_dst[57], buff[114];
4de88fe6 1247 ECX_KEY *key = ecx_key_new(ED448_KEYLEN, 1);
19bd1fa1
PS
1248 unsigned char *privkey = NULL, *pubkey;
1249 EVP_MD_CTX *hashctx = NULL;
1250
19bd1fa1
PS
1251 if (key == NULL) {
1252 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1253 goto err;
1254 }
1255
1256 pubkey = key->pubkey;
1257
4de88fe6 1258 privkey = ecx_key_allocate_privkey(key);
19bd1fa1
PS
1259 if (privkey == NULL) {
1260 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1261 goto err;
1262 }
1263
1264 if (RAND_priv_bytes(privkey, ED448_KEYLEN) <= 0)
1265 goto err;
1266
1267 hashctx = EVP_MD_CTX_new();
1268 if (hashctx == NULL)
1269 goto err;
1270 if (EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) != 1)
1271 goto err;
1272 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1273 goto err;
1274 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1275 goto err;
1276
1277 buff[0] &= -4;
1278 buff[55] |= 0x80;
1279 buff[56] = 0;
1280
1281 if (s390x_ed448_mul(x_dst, pubkey,
1282 generator_x, generator_y, buff) != 1)
1283 goto err;
1284
1285 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1286
1287 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1288 EVP_MD_CTX_free(hashctx);
1289 return 1;
1290 err:
4de88fe6 1291 ecx_key_free(key);
19bd1fa1
PS
1292 EVP_MD_CTX_free(hashctx);
1293 return 0;
1294}
1295
1296static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1297 size_t *keylen)
1298{
1299 const unsigned char *privkey, *pubkey;
1300
1301 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1302 return 0;
1303
1304 if (key != NULL)
1305 return s390x_x25519_mul(key, pubkey, privkey);
1306
1307 *keylen = X25519_KEYLEN;
1308 return 1;
1309}
1310
1311static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1312 size_t *keylen)
1313{
1314 const unsigned char *privkey, *pubkey;
1315
1316 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1317 return 0;
1318
1319 if (key != NULL)
1320 return s390x_x448_mul(key, pubkey, privkey);
1321
1322 *keylen = X448_KEYLEN;
1323 return 1;
1324}
1325
1326static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1327 unsigned char *sig, size_t *siglen,
1328 const unsigned char *tbs,
1329 size_t tbslen)
1330{
1331 union {
1332 struct {
1333 unsigned char sig[64];
1334 unsigned char priv[32];
1335 } ed25519;
1336 unsigned long long buff[512];
1337 } param;
1338 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1339 int rc;
1340
1341 if (sig == NULL) {
1342 *siglen = ED25519_SIGSIZE;
1343 return 1;
1344 }
1345
1346 if (*siglen < ED25519_SIGSIZE) {
1347 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
1348 return 0;
1349 }
1350
1351 memset(&param, 0, sizeof(param));
1352 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1353
1354 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1355 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1356 if (rc != 0)
1357 return 0;
1358
1359 s390x_flip_endian32(sig, param.ed25519.sig);
1360 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1361
1362 *siglen = ED25519_SIGSIZE;
1363 return 1;
1364}
1365
1366static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1367 unsigned char *sig, size_t *siglen,
1368 const unsigned char *tbs,
1369 size_t tbslen)
1370{
1371 union {
1372 struct {
1373 unsigned char sig[128];
1374 unsigned char priv[64];
1375 } ed448;
1376 unsigned long long buff[512];
1377 } param;
1378 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1379 int rc;
1380
1381 if (sig == NULL) {
1382 *siglen = ED448_SIGSIZE;
1383 return 1;
1384 }
1385
1386 if (*siglen < ED448_SIGSIZE) {
1387 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
1388 return 0;
1389 }
1390
1391 memset(&param, 0, sizeof(param));
1392 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1393
1394 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1395 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1396 if (rc != 0)
1397 return 0;
1398
1399 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1400 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1401 memcpy(sig, param.ed448.sig, 57);
1402 memcpy(sig + 57, param.ed448.sig + 64, 57);
1403
1404 *siglen = ED448_SIGSIZE;
1405 return 1;
1406}
1407
1408static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1409 const unsigned char *sig,
1410 size_t siglen,
1411 const unsigned char *tbs,
1412 size_t tbslen)
1413{
1414 union {
1415 struct {
1416 unsigned char sig[64];
1417 unsigned char pub[32];
1418 } ed25519;
1419 unsigned long long buff[512];
1420 } param;
1421 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1422
1423 if (siglen != ED25519_SIGSIZE)
1424 return 0;
1425
1426 memset(&param, 0, sizeof(param));
1427 s390x_flip_endian32(param.ed25519.sig, sig);
1428 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1429 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1430
1431 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1432 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1433}
1434
1435static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1436 const unsigned char *sig,
1437 size_t siglen,
1438 const unsigned char *tbs,
1439 size_t tbslen)
1440{
1441 union {
1442 struct {
1443 unsigned char sig[128];
1444 unsigned char pub[64];
1445 } ed448;
1446 unsigned long long buff[512];
1447 } param;
1448 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1449
1450 if (siglen != ED448_SIGSIZE)
1451 return 0;
1452
1453 memset(&param, 0, sizeof(param));
1454 memcpy(param.ed448.sig, sig, 57);
1455 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1456 memcpy(param.ed448.sig + 64, sig + 57, 57);
1457 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1458 memcpy(param.ed448.pub, edkey->pubkey, 57);
1459 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1460
1461 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1462 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1463}
1464
1465static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1466 EVP_PKEY_X25519,
1467 0, 0, 0, 0, 0, 0, 0,
1468 s390x_pkey_ecx_keygen25519,
1469 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1470 s390x_pkey_ecx_derive25519,
1471 pkey_ecx_ctrl,
1472 0
1473};
1474
1475static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1476 EVP_PKEY_X448,
1477 0, 0, 0, 0, 0, 0, 0,
1478 s390x_pkey_ecx_keygen448,
1479 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1480 s390x_pkey_ecx_derive448,
1481 pkey_ecx_ctrl,
1482 0
1483};
1484static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1485 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1486 0, 0, 0, 0, 0, 0,
1487 s390x_pkey_ecd_keygen25519,
1488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1489 pkey_ecd_ctrl,
1490 0,
1491 s390x_pkey_ecd_digestsign25519,
1492 s390x_pkey_ecd_digestverify25519
1493};
1494
1495static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1496 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1497 0, 0, 0, 0, 0, 0,
1498 s390x_pkey_ecd_keygen448,
1499 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1500 pkey_ecd_ctrl,
1501 0,
1502 s390x_pkey_ecd_digestsign448,
1503 s390x_pkey_ecd_digestverify448
1504};
1505#endif
1506
1507const EVP_PKEY_METHOD *ecx25519_pkey_method(void)
1508{
1509#ifdef S390X_EC_ASM
1510 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1511 return &ecx25519_s390x_pkey_meth;
1512#endif
1513 return &ecx25519_pkey_meth;
1514}
1515
1516const EVP_PKEY_METHOD *ecx448_pkey_method(void)
1517{
1518#ifdef S390X_EC_ASM
1519 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1520 return &ecx448_s390x_pkey_meth;
1521#endif
1522 return &ecx448_pkey_meth;
1523}
1524
1525const EVP_PKEY_METHOD *ed25519_pkey_method(void)
1526{
1527#ifdef S390X_EC_ASM
1528 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1529 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1530 && OPENSSL_s390xcap_P.kdsa[0]
1531 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1532 return &ed25519_s390x_pkey_meth;
1533#endif
1534 return &ed25519_pkey_meth;
1535}
1536
1537const EVP_PKEY_METHOD *ed448_pkey_method(void)
1538{
1539#ifdef S390X_EC_ASM
1540 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1541 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1542 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1543 return &ed448_s390x_pkey_meth;
1544#endif
1545 return &ed448_pkey_meth;
1546}