1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <openssl/crypto.h>
11e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h>
12e1051a39Sopenharmony_ci#include <openssl/core_names.h>
13e1051a39Sopenharmony_ci#include <openssl/err.h>
14e1051a39Sopenharmony_ci#include <openssl/params.h>
15e1051a39Sopenharmony_ci#include <openssl/evp.h>
16e1051a39Sopenharmony_ci#include <openssl/err.h>
17e1051a39Sopenharmony_ci#include <openssl/proverr.h>
18e1051a39Sopenharmony_ci#include "internal/nelem.h"
19e1051a39Sopenharmony_ci#include "internal/sizes.h"
20e1051a39Sopenharmony_ci#include "prov/providercommon.h"
21e1051a39Sopenharmony_ci#include "prov/implementations.h"
22e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
23e1051a39Sopenharmony_ci#include "prov/der_ecx.h"
24e1051a39Sopenharmony_ci#include "crypto/ecx.h"
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
27e1051a39Sopenharmony_ci# include "s390x_arch.h"
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_ci# define S390X_CAN_SIGN(edtype)                                                \
30e1051a39Sopenharmony_ci((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype))    \
31e1051a39Sopenharmony_ci&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype))      \
32e1051a39Sopenharmony_ci&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_cistatic int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
35e1051a39Sopenharmony_ci                                    const unsigned char *tbs, size_t tbslen);
36e1051a39Sopenharmony_cistatic int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
37e1051a39Sopenharmony_ci                                  const unsigned char *tbs, size_t tbslen);
38e1051a39Sopenharmony_cistatic int s390x_ed25519_digestverify(const ECX_KEY *edkey,
39e1051a39Sopenharmony_ci                                      const unsigned char *sig,
40e1051a39Sopenharmony_ci                                      const unsigned char *tbs, size_t tbslen);
41e1051a39Sopenharmony_cistatic int s390x_ed448_digestverify(const ECX_KEY *edkey,
42e1051a39Sopenharmony_ci                                    const unsigned char *sig,
43e1051a39Sopenharmony_ci                                    const unsigned char *tbs, size_t tbslen);
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_newctx_fn eddsa_newctx;
48e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
49e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
50e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
51e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
52e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
53e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_freectx_fn eddsa_freectx;
54e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
55e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
56e1051a39Sopenharmony_cistatic OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_citypedef struct {
59e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx;
60e1051a39Sopenharmony_ci    ECX_KEY *key;
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_ci    /* The Algorithm Identifier of the signature algorithm */
63e1051a39Sopenharmony_ci    unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
64e1051a39Sopenharmony_ci    unsigned char *aid;
65e1051a39Sopenharmony_ci    size_t  aid_len;
66e1051a39Sopenharmony_ci} PROV_EDDSA_CTX;
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_cistatic void *eddsa_newctx(void *provctx, const char *propq_unused)
69e1051a39Sopenharmony_ci{
70e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx;
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
73e1051a39Sopenharmony_ci        return NULL;
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ci    peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
76e1051a39Sopenharmony_ci    if (peddsactx == NULL) {
77e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
78e1051a39Sopenharmony_ci        return NULL;
79e1051a39Sopenharmony_ci    }
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci    peddsactx->libctx = PROV_LIBCTX_OF(provctx);
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci    return peddsactx;
84e1051a39Sopenharmony_ci}
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_cistatic int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
87e1051a39Sopenharmony_ci                                        void *vedkey,
88e1051a39Sopenharmony_ci                                        ossl_unused const OSSL_PARAM params[])
89e1051a39Sopenharmony_ci{
90e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
91e1051a39Sopenharmony_ci    ECX_KEY *edkey = (ECX_KEY *)vedkey;
92e1051a39Sopenharmony_ci    WPACKET pkt;
93e1051a39Sopenharmony_ci    int ret;
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
96e1051a39Sopenharmony_ci        return 0;
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ci    if (mdname != NULL && mdname[0] != '\0') {
99e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
100e1051a39Sopenharmony_ci        return 0;
101e1051a39Sopenharmony_ci    }
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci    if (edkey == NULL) {
104e1051a39Sopenharmony_ci        if (peddsactx->key != NULL)
105e1051a39Sopenharmony_ci            /* there is nothing to do on reinit */
106e1051a39Sopenharmony_ci            return 1;
107e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
108e1051a39Sopenharmony_ci        return 0;
109e1051a39Sopenharmony_ci    }
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci    if (!ossl_ecx_key_up_ref(edkey)) {
112e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
113e1051a39Sopenharmony_ci        return 0;
114e1051a39Sopenharmony_ci    }
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    /*
117e1051a39Sopenharmony_ci     * We do not care about DER writing errors.
118e1051a39Sopenharmony_ci     * All it really means is that for some reason, there's no
119e1051a39Sopenharmony_ci     * AlgorithmIdentifier to be had, but the operation itself is
120e1051a39Sopenharmony_ci     * still valid, just as long as it's not used to construct
121e1051a39Sopenharmony_ci     * anything that needs an AlgorithmIdentifier.
122e1051a39Sopenharmony_ci     */
123e1051a39Sopenharmony_ci    peddsactx->aid_len = 0;
124e1051a39Sopenharmony_ci    ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
125e1051a39Sopenharmony_ci    switch (edkey->type) {
126e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED25519:
127e1051a39Sopenharmony_ci        ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
128e1051a39Sopenharmony_ci        break;
129e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED448:
130e1051a39Sopenharmony_ci        ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
131e1051a39Sopenharmony_ci        break;
132e1051a39Sopenharmony_ci    default:
133e1051a39Sopenharmony_ci        /* Should never happen */
134e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
135e1051a39Sopenharmony_ci        ossl_ecx_key_free(edkey);
136e1051a39Sopenharmony_ci        return 0;
137e1051a39Sopenharmony_ci    }
138e1051a39Sopenharmony_ci    if (ret && WPACKET_finish(&pkt)) {
139e1051a39Sopenharmony_ci        WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
140e1051a39Sopenharmony_ci        peddsactx->aid = WPACKET_get_curr(&pkt);
141e1051a39Sopenharmony_ci    }
142e1051a39Sopenharmony_ci    WPACKET_cleanup(&pkt);
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci    peddsactx->key = edkey;
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci    return 1;
147e1051a39Sopenharmony_ci}
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ciint ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
150e1051a39Sopenharmony_ci                        size_t *siglen, size_t sigsize,
151e1051a39Sopenharmony_ci                        const unsigned char *tbs, size_t tbslen)
152e1051a39Sopenharmony_ci{
153e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
154e1051a39Sopenharmony_ci    const ECX_KEY *edkey = peddsactx->key;
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
157e1051a39Sopenharmony_ci        return 0;
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci    if (sigret == NULL) {
160e1051a39Sopenharmony_ci        *siglen = ED25519_SIGSIZE;
161e1051a39Sopenharmony_ci        return 1;
162e1051a39Sopenharmony_ci    }
163e1051a39Sopenharmony_ci    if (sigsize < ED25519_SIGSIZE) {
164e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
165e1051a39Sopenharmony_ci        return 0;
166e1051a39Sopenharmony_ci    }
167e1051a39Sopenharmony_ci    if (edkey->privkey == NULL) {
168e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
169e1051a39Sopenharmony_ci        return 0;
170e1051a39Sopenharmony_ci    }
171e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
172e1051a39Sopenharmony_ci    if (S390X_CAN_SIGN(ED25519)) {
173e1051a39Sopenharmony_ci	    if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
174e1051a39Sopenharmony_ci		    ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
175e1051a39Sopenharmony_ci		    return 0;
176e1051a39Sopenharmony_ci	    }
177e1051a39Sopenharmony_ci	    *siglen = ED25519_SIGSIZE;
178e1051a39Sopenharmony_ci	    return 1;
179e1051a39Sopenharmony_ci    }
180e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
181e1051a39Sopenharmony_ci    if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
182e1051a39Sopenharmony_ci                          peddsactx->libctx, NULL) == 0) {
183e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
184e1051a39Sopenharmony_ci        return 0;
185e1051a39Sopenharmony_ci    }
186e1051a39Sopenharmony_ci    *siglen = ED25519_SIGSIZE;
187e1051a39Sopenharmony_ci    return 1;
188e1051a39Sopenharmony_ci}
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ciint ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
191e1051a39Sopenharmony_ci                      size_t *siglen, size_t sigsize,
192e1051a39Sopenharmony_ci                      const unsigned char *tbs, size_t tbslen)
193e1051a39Sopenharmony_ci{
194e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
195e1051a39Sopenharmony_ci    const ECX_KEY *edkey = peddsactx->key;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
198e1051a39Sopenharmony_ci        return 0;
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci    if (sigret == NULL) {
201e1051a39Sopenharmony_ci        *siglen = ED448_SIGSIZE;
202e1051a39Sopenharmony_ci        return 1;
203e1051a39Sopenharmony_ci    }
204e1051a39Sopenharmony_ci    if (sigsize < ED448_SIGSIZE) {
205e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
206e1051a39Sopenharmony_ci        return 0;
207e1051a39Sopenharmony_ci    }
208e1051a39Sopenharmony_ci    if (edkey->privkey == NULL) {
209e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
210e1051a39Sopenharmony_ci        return 0;
211e1051a39Sopenharmony_ci    }
212e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
213e1051a39Sopenharmony_ci    if (S390X_CAN_SIGN(ED448)) {
214e1051a39Sopenharmony_ci        if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
215e1051a39Sopenharmony_ci		ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
216e1051a39Sopenharmony_ci		return 0;
217e1051a39Sopenharmony_ci	}
218e1051a39Sopenharmony_ci	*siglen = ED448_SIGSIZE;
219e1051a39Sopenharmony_ci	return 1;
220e1051a39Sopenharmony_ci    }
221e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
222e1051a39Sopenharmony_ci    if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
223e1051a39Sopenharmony_ci                        edkey->privkey, NULL, 0, edkey->propq) == 0) {
224e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
225e1051a39Sopenharmony_ci        return 0;
226e1051a39Sopenharmony_ci    }
227e1051a39Sopenharmony_ci    *siglen = ED448_SIGSIZE;
228e1051a39Sopenharmony_ci    return 1;
229e1051a39Sopenharmony_ci}
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_ciint ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
232e1051a39Sopenharmony_ci                          size_t siglen, const unsigned char *tbs,
233e1051a39Sopenharmony_ci                          size_t tbslen)
234e1051a39Sopenharmony_ci{
235e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
236e1051a39Sopenharmony_ci    const ECX_KEY *edkey = peddsactx->key;
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
239e1051a39Sopenharmony_ci        return 0;
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
242e1051a39Sopenharmony_ci    if (S390X_CAN_SIGN(ED25519))
243e1051a39Sopenharmony_ci        return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
244e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
247e1051a39Sopenharmony_ci                               peddsactx->libctx, edkey->propq);
248e1051a39Sopenharmony_ci}
249e1051a39Sopenharmony_ci
250e1051a39Sopenharmony_ciint ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
251e1051a39Sopenharmony_ci                        size_t siglen, const unsigned char *tbs,
252e1051a39Sopenharmony_ci                        size_t tbslen)
253e1051a39Sopenharmony_ci{
254e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
255e1051a39Sopenharmony_ci    const ECX_KEY *edkey = peddsactx->key;
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
258e1051a39Sopenharmony_ci        return 0;
259e1051a39Sopenharmony_ci
260e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
261e1051a39Sopenharmony_ci    if (S390X_CAN_SIGN(ED448))
262e1051a39Sopenharmony_ci        return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
263e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
266e1051a39Sopenharmony_ci                             NULL, 0, edkey->propq);
267e1051a39Sopenharmony_ci}
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_cistatic void eddsa_freectx(void *vpeddsactx)
270e1051a39Sopenharmony_ci{
271e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
272e1051a39Sopenharmony_ci
273e1051a39Sopenharmony_ci    ossl_ecx_key_free(peddsactx->key);
274e1051a39Sopenharmony_ci
275e1051a39Sopenharmony_ci    OPENSSL_free(peddsactx);
276e1051a39Sopenharmony_ci}
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_cistatic void *eddsa_dupctx(void *vpeddsactx)
279e1051a39Sopenharmony_ci{
280e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
281e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *dstctx;
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
284e1051a39Sopenharmony_ci        return NULL;
285e1051a39Sopenharmony_ci
286e1051a39Sopenharmony_ci    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
287e1051a39Sopenharmony_ci    if (dstctx == NULL)
288e1051a39Sopenharmony_ci        return NULL;
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci    *dstctx = *srcctx;
291e1051a39Sopenharmony_ci    dstctx->key = NULL;
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ci    if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
294e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
295e1051a39Sopenharmony_ci        goto err;
296e1051a39Sopenharmony_ci    }
297e1051a39Sopenharmony_ci    dstctx->key = srcctx->key;
298e1051a39Sopenharmony_ci
299e1051a39Sopenharmony_ci    return dstctx;
300e1051a39Sopenharmony_ci err:
301e1051a39Sopenharmony_ci    eddsa_freectx(dstctx);
302e1051a39Sopenharmony_ci    return NULL;
303e1051a39Sopenharmony_ci}
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_cistatic int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
306e1051a39Sopenharmony_ci{
307e1051a39Sopenharmony_ci    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
308e1051a39Sopenharmony_ci    OSSL_PARAM *p;
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_ci    if (peddsactx == NULL)
311e1051a39Sopenharmony_ci        return 0;
312e1051a39Sopenharmony_ci
313e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
314e1051a39Sopenharmony_ci    if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
315e1051a39Sopenharmony_ci                                                  peddsactx->aid_len))
316e1051a39Sopenharmony_ci        return 0;
317e1051a39Sopenharmony_ci
318e1051a39Sopenharmony_ci    return 1;
319e1051a39Sopenharmony_ci}
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_cistatic const OSSL_PARAM known_gettable_ctx_params[] = {
322e1051a39Sopenharmony_ci    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
323e1051a39Sopenharmony_ci    OSSL_PARAM_END
324e1051a39Sopenharmony_ci};
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_cistatic const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
327e1051a39Sopenharmony_ci                                                   ossl_unused void *provctx)
328e1051a39Sopenharmony_ci{
329e1051a39Sopenharmony_ci    return known_gettable_ctx_params;
330e1051a39Sopenharmony_ci}
331e1051a39Sopenharmony_ci
332e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
333e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
334e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
335e1051a39Sopenharmony_ci      (void (*)(void))eddsa_digest_signverify_init },
336e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
337e1051a39Sopenharmony_ci      (void (*)(void))ed25519_digest_sign },
338e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
339e1051a39Sopenharmony_ci      (void (*)(void))eddsa_digest_signverify_init },
340e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
341e1051a39Sopenharmony_ci      (void (*)(void))ed25519_digest_verify },
342e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
343e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
344e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
345e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
346e1051a39Sopenharmony_ci      (void (*)(void))eddsa_gettable_ctx_params },
347e1051a39Sopenharmony_ci    { 0, NULL }
348e1051a39Sopenharmony_ci};
349e1051a39Sopenharmony_ci
350e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_ed448_signature_functions[] = {
351e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
352e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
353e1051a39Sopenharmony_ci      (void (*)(void))eddsa_digest_signverify_init },
354e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
355e1051a39Sopenharmony_ci      (void (*)(void))ed448_digest_sign },
356e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
357e1051a39Sopenharmony_ci      (void (*)(void))eddsa_digest_signverify_init },
358e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
359e1051a39Sopenharmony_ci      (void (*)(void))ed448_digest_verify },
360e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
361e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
362e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
363e1051a39Sopenharmony_ci    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
364e1051a39Sopenharmony_ci      (void (*)(void))eddsa_gettable_ctx_params },
365e1051a39Sopenharmony_ci    { 0, NULL }
366e1051a39Sopenharmony_ci};
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_cistatic int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
371e1051a39Sopenharmony_ci                                    const unsigned char *tbs, size_t tbslen)
372e1051a39Sopenharmony_ci{
373e1051a39Sopenharmony_ci    int rc;
374e1051a39Sopenharmony_ci    union {
375e1051a39Sopenharmony_ci        struct {
376e1051a39Sopenharmony_ci            unsigned char sig[64];
377e1051a39Sopenharmony_ci            unsigned char priv[32];
378e1051a39Sopenharmony_ci        } ed25519;
379e1051a39Sopenharmony_ci        unsigned long long buff[512];
380e1051a39Sopenharmony_ci    } param;
381e1051a39Sopenharmony_ci
382e1051a39Sopenharmony_ci    memset(&param, 0, sizeof(param));
383e1051a39Sopenharmony_ci    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
384e1051a39Sopenharmony_ci
385e1051a39Sopenharmony_ci    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
386e1051a39Sopenharmony_ci    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
387e1051a39Sopenharmony_ci    if (rc != 0)
388e1051a39Sopenharmony_ci        return 0;
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci    s390x_flip_endian32(sig, param.ed25519.sig);
391e1051a39Sopenharmony_ci    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
392e1051a39Sopenharmony_ci    return 1;
393e1051a39Sopenharmony_ci}
394e1051a39Sopenharmony_ci
395e1051a39Sopenharmony_cistatic int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
396e1051a39Sopenharmony_ci                                  const unsigned char *tbs, size_t tbslen)
397e1051a39Sopenharmony_ci{
398e1051a39Sopenharmony_ci    int rc;
399e1051a39Sopenharmony_ci    union {
400e1051a39Sopenharmony_ci        struct {
401e1051a39Sopenharmony_ci            unsigned char sig[128];
402e1051a39Sopenharmony_ci            unsigned char priv[64];
403e1051a39Sopenharmony_ci        } ed448;
404e1051a39Sopenharmony_ci        unsigned long long buff[512];
405e1051a39Sopenharmony_ci    } param;
406e1051a39Sopenharmony_ci
407e1051a39Sopenharmony_ci    memset(&param, 0, sizeof(param));
408e1051a39Sopenharmony_ci    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ci    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
411e1051a39Sopenharmony_ci    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
412e1051a39Sopenharmony_ci    if (rc != 0)
413e1051a39Sopenharmony_ci        return 0;
414e1051a39Sopenharmony_ci
415e1051a39Sopenharmony_ci    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
416e1051a39Sopenharmony_ci    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
417e1051a39Sopenharmony_ci    memcpy(sig, param.ed448.sig, 57);
418e1051a39Sopenharmony_ci    memcpy(sig + 57, param.ed448.sig + 64, 57);
419e1051a39Sopenharmony_ci    return 1;
420e1051a39Sopenharmony_ci}
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_cistatic int s390x_ed25519_digestverify(const ECX_KEY *edkey,
423e1051a39Sopenharmony_ci                                      const unsigned char *sig,
424e1051a39Sopenharmony_ci                                      const unsigned char *tbs, size_t tbslen)
425e1051a39Sopenharmony_ci{
426e1051a39Sopenharmony_ci    union {
427e1051a39Sopenharmony_ci        struct {
428e1051a39Sopenharmony_ci            unsigned char sig[64];
429e1051a39Sopenharmony_ci            unsigned char pub[32];
430e1051a39Sopenharmony_ci        } ed25519;
431e1051a39Sopenharmony_ci        unsigned long long buff[512];
432e1051a39Sopenharmony_ci    } param;
433e1051a39Sopenharmony_ci
434e1051a39Sopenharmony_ci    memset(&param, 0, sizeof(param));
435e1051a39Sopenharmony_ci    s390x_flip_endian32(param.ed25519.sig, sig);
436e1051a39Sopenharmony_ci    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
437e1051a39Sopenharmony_ci    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
438e1051a39Sopenharmony_ci
439e1051a39Sopenharmony_ci    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
440e1051a39Sopenharmony_ci                      &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
441e1051a39Sopenharmony_ci}
442e1051a39Sopenharmony_ci
443e1051a39Sopenharmony_cistatic int s390x_ed448_digestverify(const ECX_KEY *edkey,
444e1051a39Sopenharmony_ci                                    const unsigned char *sig,
445e1051a39Sopenharmony_ci                                    const unsigned char *tbs,
446e1051a39Sopenharmony_ci                                    size_t tbslen)
447e1051a39Sopenharmony_ci{
448e1051a39Sopenharmony_ci    union {
449e1051a39Sopenharmony_ci        struct {
450e1051a39Sopenharmony_ci            unsigned char sig[128];
451e1051a39Sopenharmony_ci            unsigned char pub[64];
452e1051a39Sopenharmony_ci        } ed448;
453e1051a39Sopenharmony_ci        unsigned long long buff[512];
454e1051a39Sopenharmony_ci    } param;
455e1051a39Sopenharmony_ci
456e1051a39Sopenharmony_ci    memset(&param, 0, sizeof(param));
457e1051a39Sopenharmony_ci    memcpy(param.ed448.sig, sig, 57);
458e1051a39Sopenharmony_ci    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
459e1051a39Sopenharmony_ci    memcpy(param.ed448.sig + 64, sig + 57, 57);
460e1051a39Sopenharmony_ci    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
461e1051a39Sopenharmony_ci    memcpy(param.ed448.pub, edkey->pubkey, 57);
462e1051a39Sopenharmony_ci    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
463e1051a39Sopenharmony_ci
464e1051a39Sopenharmony_ci    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
465e1051a39Sopenharmony_ci                      &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
466e1051a39Sopenharmony_ci}
467e1051a39Sopenharmony_ci
468e1051a39Sopenharmony_ci#endif /* S390X_EC_ASM */
469