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