2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/crypto.h>
11 #include <openssl/core_dispatch.h>
12 #include <openssl/core_names.h>
13 #include <openssl/err.h>
14 #include <openssl/params.h>
15 #include <openssl/evp.h>
16 #include <openssl/err.h>
17 #include <openssl/proverr.h>
18 #include "internal/nelem.h"
19 #include "internal/sizes.h"
20 #include "prov/providercommon.h"
21 #include "prov/implementations.h"
22 #include "prov/provider_ctx.h"
23 #include "prov/der_ecx.h"
24 #include "crypto/ecx.h"
27 # include "s390x_arch.h"
29 # define S390X_CAN_SIGN(edtype) \
30 ((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype)) \
31 && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype)) \
32 && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
34 static int s390x_ed25519_digestsign(const ECX_KEY
*edkey
, unsigned char *sig
,
35 const unsigned char *tbs
, size_t tbslen
);
36 static int s390x_ed448_digestsign(const ECX_KEY
*edkey
, unsigned char *sig
,
37 const unsigned char *tbs
, size_t tbslen
);
38 static int s390x_ed25519_digestverify(const ECX_KEY
*edkey
,
39 const unsigned char *sig
,
40 const unsigned char *tbs
, size_t tbslen
);
41 static int s390x_ed448_digestverify(const ECX_KEY
*edkey
,
42 const unsigned char *sig
,
43 const unsigned char *tbs
, size_t tbslen
);
45 #endif /* S390X_EC_ASM */
47 static OSSL_FUNC_signature_newctx_fn eddsa_newctx
;
48 static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init
;
49 static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign
;
50 static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign
;
51 static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify
;
52 static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify
;
53 static OSSL_FUNC_signature_freectx_fn eddsa_freectx
;
54 static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx
;
55 static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params
;
56 static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params
;
62 /* The Algorithm Identifier of the signature algorithm */
63 unsigned char aid_buf
[OSSL_MAX_ALGORITHM_ID_SIZE
];
68 static void *eddsa_newctx(void *provctx
, const char *propq_unused
)
70 PROV_EDDSA_CTX
*peddsactx
;
72 if (!ossl_prov_is_running())
75 peddsactx
= OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX
));
76 if (peddsactx
== NULL
) {
77 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
81 peddsactx
->libctx
= PROV_LIBCTX_OF(provctx
);
86 static int eddsa_digest_signverify_init(void *vpeddsactx
, const char *mdname
,
89 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
90 ECX_KEY
*edkey
= (ECX_KEY
*)vedkey
;
94 if (!ossl_prov_is_running())
97 if (mdname
!= NULL
&& mdname
[0] != '\0') {
98 ERR_raise(ERR_LIB_PROV
, PROV_R_INVALID_DIGEST
);
102 if (!ossl_ecx_key_up_ref(edkey
)) {
103 ERR_raise(ERR_LIB_PROV
, ERR_R_INTERNAL_ERROR
);
108 * TODO(3.0) Should we care about DER writing errors?
109 * All it really means is that for some reason, there's no
110 * AlgorithmIdentifier to be had, but the operation itself is
111 * still valid, just as long as it's not used to construct
112 * anything that needs an AlgorithmIdentifier.
114 peddsactx
->aid_len
= 0;
115 ret
= WPACKET_init_der(&pkt
, peddsactx
->aid_buf
, sizeof(peddsactx
->aid_buf
));
116 switch (edkey
->type
) {
117 case ECX_KEY_TYPE_ED25519
:
118 ret
= ret
&& ossl_DER_w_algorithmIdentifier_ED25519(&pkt
, -1, edkey
);
120 case ECX_KEY_TYPE_ED448
:
121 ret
= ret
&& ossl_DER_w_algorithmIdentifier_ED448(&pkt
, -1, edkey
);
124 /* Should never happen */
125 ERR_raise(ERR_LIB_PROV
, ERR_R_INTERNAL_ERROR
);
128 if (ret
&& WPACKET_finish(&pkt
)) {
129 WPACKET_get_total_written(&pkt
, &peddsactx
->aid_len
);
130 peddsactx
->aid
= WPACKET_get_curr(&pkt
);
132 WPACKET_cleanup(&pkt
);
134 peddsactx
->key
= edkey
;
139 int ed25519_digest_sign(void *vpeddsactx
, unsigned char *sigret
,
140 size_t *siglen
, size_t sigsize
,
141 const unsigned char *tbs
, size_t tbslen
)
143 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
144 const ECX_KEY
*edkey
= peddsactx
->key
;
146 if (!ossl_prov_is_running())
149 if (sigret
== NULL
) {
150 *siglen
= ED25519_SIGSIZE
;
153 if (sigsize
< ED25519_SIGSIZE
) {
154 ERR_raise(ERR_LIB_PROV
, PROV_R_OUTPUT_BUFFER_TOO_SMALL
);
158 if (S390X_CAN_SIGN(ED25519
))
159 return s390x_ed25519_digestsign(edkey
, sigret
, tbs
, tbslen
);
160 #endif /* S390X_EC_ASM */
161 if (ED25519_sign(sigret
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
,
162 peddsactx
->libctx
, NULL
) == 0) {
163 ERR_raise(ERR_LIB_PROV
, PROV_R_FAILED_TO_SIGN
);
166 *siglen
= ED25519_SIGSIZE
;
170 int ed448_digest_sign(void *vpeddsactx
, unsigned char *sigret
,
171 size_t *siglen
, size_t sigsize
,
172 const unsigned char *tbs
, size_t tbslen
)
174 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
175 const ECX_KEY
*edkey
= peddsactx
->key
;
177 if (!ossl_prov_is_running())
180 if (sigret
== NULL
) {
181 *siglen
= ED448_SIGSIZE
;
184 if (sigsize
< ED448_SIGSIZE
) {
185 ERR_raise(ERR_LIB_PROV
, PROV_R_OUTPUT_BUFFER_TOO_SMALL
);
189 if (S390X_CAN_SIGN(ED448
))
190 return s390x_ed448_digestsign(edkey
, sigret
, tbs
, tbslen
);
191 #endif /* S390X_EC_ASM */
192 if (ED448_sign(peddsactx
->libctx
, sigret
, tbs
, tbslen
, edkey
->pubkey
,
193 edkey
->privkey
, NULL
, 0, edkey
->propq
) == 0) {
194 ERR_raise(ERR_LIB_PROV
, PROV_R_FAILED_TO_SIGN
);
197 *siglen
= ED448_SIGSIZE
;
201 int ed25519_digest_verify(void *vpeddsactx
, const unsigned char *sig
,
202 size_t siglen
, const unsigned char *tbs
,
205 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
206 const ECX_KEY
*edkey
= peddsactx
->key
;
208 if (!ossl_prov_is_running() || siglen
!= ED25519_SIGSIZE
)
212 if (S390X_CAN_SIGN(ED25519
))
213 return s390x_ed25519_digestverify(edkey
, sig
, tbs
, tbslen
);
214 #endif /* S390X_EC_ASM */
216 return ED25519_verify(tbs
, tbslen
, sig
, edkey
->pubkey
, peddsactx
->libctx
,
220 int ed448_digest_verify(void *vpeddsactx
, const unsigned char *sig
,
221 size_t siglen
, const unsigned char *tbs
,
224 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
225 const ECX_KEY
*edkey
= peddsactx
->key
;
227 if (!ossl_prov_is_running() || siglen
!= ED448_SIGSIZE
)
231 if (S390X_CAN_SIGN(ED448
))
232 return s390x_ed448_digestverify(edkey
, sig
, tbs
, tbslen
);
233 #endif /* S390X_EC_ASM */
235 return ED448_verify(peddsactx
->libctx
, tbs
, tbslen
, sig
, edkey
->pubkey
,
236 NULL
, 0, edkey
->propq
);
239 static void eddsa_freectx(void *vpeddsactx
)
241 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
243 ossl_ecx_key_free(peddsactx
->key
);
245 OPENSSL_free(peddsactx
);
248 static void *eddsa_dupctx(void *vpeddsactx
)
250 PROV_EDDSA_CTX
*srcctx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
251 PROV_EDDSA_CTX
*dstctx
;
253 if (!ossl_prov_is_running())
256 dstctx
= OPENSSL_zalloc(sizeof(*srcctx
));
263 if (srcctx
->key
!= NULL
&& !ossl_ecx_key_up_ref(srcctx
->key
)) {
264 ERR_raise(ERR_LIB_PROV
, ERR_R_INTERNAL_ERROR
);
267 dstctx
->key
= srcctx
->key
;
271 eddsa_freectx(dstctx
);
275 static int eddsa_get_ctx_params(void *vpeddsactx
, OSSL_PARAM
*params
)
277 PROV_EDDSA_CTX
*peddsactx
= (PROV_EDDSA_CTX
*)vpeddsactx
;
280 if (peddsactx
== NULL
|| params
== NULL
)
283 p
= OSSL_PARAM_locate(params
, OSSL_SIGNATURE_PARAM_ALGORITHM_ID
);
284 if (p
!= NULL
&& !OSSL_PARAM_set_octet_string(p
, peddsactx
->aid
,
291 static const OSSL_PARAM known_gettable_ctx_params
[] = {
292 OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID
, NULL
, 0),
296 static const OSSL_PARAM
*eddsa_gettable_ctx_params(ossl_unused
void *provctx
)
298 return known_gettable_ctx_params
;
301 const OSSL_DISPATCH ossl_ed25519_signature_functions
[] = {
302 { OSSL_FUNC_SIGNATURE_NEWCTX
, (void (*)(void))eddsa_newctx
},
303 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT
,
304 (void (*)(void))eddsa_digest_signverify_init
},
305 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN
,
306 (void (*)(void))ed25519_digest_sign
},
307 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT
,
308 (void (*)(void))eddsa_digest_signverify_init
},
309 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
,
310 (void (*)(void))ed25519_digest_verify
},
311 { OSSL_FUNC_SIGNATURE_FREECTX
, (void (*)(void))eddsa_freectx
},
312 { OSSL_FUNC_SIGNATURE_DUPCTX
, (void (*)(void))eddsa_dupctx
},
313 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS
, (void (*)(void))eddsa_get_ctx_params
},
314 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS
,
315 (void (*)(void))eddsa_gettable_ctx_params
},
319 const OSSL_DISPATCH ossl_ed448_signature_functions
[] = {
320 { OSSL_FUNC_SIGNATURE_NEWCTX
, (void (*)(void))eddsa_newctx
},
321 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT
,
322 (void (*)(void))eddsa_digest_signverify_init
},
323 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN
,
324 (void (*)(void))ed448_digest_sign
},
325 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT
,
326 (void (*)(void))eddsa_digest_signverify_init
},
327 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
,
328 (void (*)(void))ed448_digest_verify
},
329 { OSSL_FUNC_SIGNATURE_FREECTX
, (void (*)(void))eddsa_freectx
},
330 { OSSL_FUNC_SIGNATURE_DUPCTX
, (void (*)(void))eddsa_dupctx
},
331 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS
, (void (*)(void))eddsa_get_ctx_params
},
332 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS
,
333 (void (*)(void))eddsa_gettable_ctx_params
},
339 static int s390x_ed25519_digestsign(const ECX_KEY
*edkey
, unsigned char *sig
,
340 const unsigned char *tbs
, size_t tbslen
)
345 unsigned char sig
[64];
346 unsigned char priv
[32];
348 unsigned long long buff
[512];
351 memset(¶m
, 0, sizeof(param
));
352 memcpy(param
.ed25519
.priv
, edkey
->privkey
, sizeof(param
.ed25519
.priv
));
354 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED25519
, ¶m
.ed25519
, tbs
, tbslen
);
355 OPENSSL_cleanse(param
.ed25519
.priv
, sizeof(param
.ed25519
.priv
));
359 s390x_flip_endian32(sig
, param
.ed25519
.sig
);
360 s390x_flip_endian32(sig
+ 32, param
.ed25519
.sig
+ 32);
364 static int s390x_ed448_digestsign(const ECX_KEY
*edkey
, unsigned char *sig
,
365 const unsigned char *tbs
, size_t tbslen
)
370 unsigned char sig
[128];
371 unsigned char priv
[64];
373 unsigned long long buff
[512];
376 memset(¶m
, 0, sizeof(param
));
377 memcpy(param
.ed448
.priv
+ 64 - 57, edkey
->privkey
, 57);
379 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED448
, ¶m
.ed448
, tbs
, tbslen
);
380 OPENSSL_cleanse(param
.ed448
.priv
, sizeof(param
.ed448
.priv
));
384 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
385 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
386 memcpy(sig
, param
.ed448
.sig
, 57);
387 memcpy(sig
+ 57, param
.ed448
.sig
+ 64, 57);
391 static int s390x_ed25519_digestverify(const ECX_KEY
*edkey
,
392 const unsigned char *sig
,
393 const unsigned char *tbs
, size_t tbslen
)
397 unsigned char sig
[64];
398 unsigned char pub
[32];
400 unsigned long long buff
[512];
403 memset(¶m
, 0, sizeof(param
));
404 s390x_flip_endian32(param
.ed25519
.sig
, sig
);
405 s390x_flip_endian32(param
.ed25519
.sig
+ 32, sig
+ 32);
406 s390x_flip_endian32(param
.ed25519
.pub
, edkey
->pubkey
);
408 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519
,
409 ¶m
.ed25519
, tbs
, tbslen
) == 0 ? 1 : 0;
412 static int s390x_ed448_digestverify(const ECX_KEY
*edkey
,
413 const unsigned char *sig
,
414 const unsigned char *tbs
,
419 unsigned char sig
[128];
420 unsigned char pub
[64];
422 unsigned long long buff
[512];
425 memset(¶m
, 0, sizeof(param
));
426 memcpy(param
.ed448
.sig
, sig
, 57);
427 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
428 memcpy(param
.ed448
.sig
+ 64, sig
+ 57, 57);
429 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
430 memcpy(param
.ed448
.pub
, edkey
->pubkey
, 57);
431 s390x_flip_endian64(param
.ed448
.pub
, param
.ed448
.pub
);
433 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448
,
434 ¶m
.ed448
, tbs
, tbslen
) == 0 ? 1 : 0;
437 #endif /* S390X_EC_ASM */