1 /* 2 * Copyright 2020-2022 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 return 0; 137 } 138 if (ret && WPACKET_finish(&pkt)) { 139 WPACKET_get_total_written(&pkt, &peddsactx->aid_len); 140 peddsactx->aid = WPACKET_get_curr(&pkt); 141 } 142 WPACKET_cleanup(&pkt); 143 144 peddsactx->key = edkey; 145 146 return 1; 147 } 148 149 int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret, 150 size_t *siglen, size_t sigsize, 151 const unsigned char *tbs, size_t tbslen) 152 { 153 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 154 const ECX_KEY *edkey = peddsactx->key; 155 156 if (!ossl_prov_is_running()) 157 return 0; 158 159 if (sigret == NULL) { 160 *siglen = ED25519_SIGSIZE; 161 return 1; 162 } 163 if (sigsize < ED25519_SIGSIZE) { 164 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 165 return 0; 166 } 167 if (edkey->privkey == NULL) { 168 ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); 169 return 0; 170 } 171 #ifdef S390X_EC_ASM 172 if (S390X_CAN_SIGN(ED25519)) { 173 if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) { 174 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN); 175 return 0; 176 } 177 *siglen = ED25519_SIGSIZE; 178 return 1; 179 } 180 #endif /* S390X_EC_ASM */ 181 if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey, 182 peddsactx->libctx, NULL) == 0) { 183 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN); 184 return 0; 185 } 186 *siglen = ED25519_SIGSIZE; 187 return 1; 188 } 189 190 int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret, 191 size_t *siglen, size_t sigsize, 192 const unsigned char *tbs, size_t tbslen) 193 { 194 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 195 const ECX_KEY *edkey = peddsactx->key; 196 197 if (!ossl_prov_is_running()) 198 return 0; 199 200 if (sigret == NULL) { 201 *siglen = ED448_SIGSIZE; 202 return 1; 203 } 204 if (sigsize < ED448_SIGSIZE) { 205 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 206 return 0; 207 } 208 if (edkey->privkey == NULL) { 209 ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); 210 return 0; 211 } 212 #ifdef S390X_EC_ASM 213 if (S390X_CAN_SIGN(ED448)) { 214 if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) { 215 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN); 216 return 0; 217 } 218 *siglen = ED448_SIGSIZE; 219 return 1; 220 } 221 #endif /* S390X_EC_ASM */ 222 if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey, 223 edkey->privkey, NULL, 0, edkey->propq) == 0) { 224 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN); 225 return 0; 226 } 227 *siglen = ED448_SIGSIZE; 228 return 1; 229 } 230 231 int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig, 232 size_t siglen, const unsigned char *tbs, 233 size_t tbslen) 234 { 235 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 236 const ECX_KEY *edkey = peddsactx->key; 237 238 if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE) 239 return 0; 240 241 #ifdef S390X_EC_ASM 242 if (S390X_CAN_SIGN(ED25519)) 243 return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen); 244 #endif /* S390X_EC_ASM */ 245 246 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey, 247 peddsactx->libctx, edkey->propq); 248 } 249 250 int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig, 251 size_t siglen, const unsigned char *tbs, 252 size_t tbslen) 253 { 254 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 255 const ECX_KEY *edkey = peddsactx->key; 256 257 if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE) 258 return 0; 259 260 #ifdef S390X_EC_ASM 261 if (S390X_CAN_SIGN(ED448)) 262 return s390x_ed448_digestverify(edkey, sig, tbs, tbslen); 263 #endif /* S390X_EC_ASM */ 264 265 return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey, 266 NULL, 0, edkey->propq); 267 } 268 269 static void eddsa_freectx(void *vpeddsactx) 270 { 271 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 272 273 ossl_ecx_key_free(peddsactx->key); 274 275 OPENSSL_free(peddsactx); 276 } 277 278 static void *eddsa_dupctx(void *vpeddsactx) 279 { 280 PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx; 281 PROV_EDDSA_CTX *dstctx; 282 283 if (!ossl_prov_is_running()) 284 return NULL; 285 286 dstctx = OPENSSL_zalloc(sizeof(*srcctx)); 287 if (dstctx == NULL) 288 return NULL; 289 290 *dstctx = *srcctx; 291 dstctx->key = NULL; 292 293 if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) { 294 ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); 295 goto err; 296 } 297 dstctx->key = srcctx->key; 298 299 return dstctx; 300 err: 301 eddsa_freectx(dstctx); 302 return NULL; 303 } 304 305 static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params) 306 { 307 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; 308 OSSL_PARAM *p; 309 310 if (peddsactx == NULL) 311 return 0; 312 313 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); 314 if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid, 315 peddsactx->aid_len)) 316 return 0; 317 318 return 1; 319 } 320 321 static const OSSL_PARAM known_gettable_ctx_params[] = { 322 OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), 323 OSSL_PARAM_END 324 }; 325 326 static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx, 327 ossl_unused void *provctx) 328 { 329 return known_gettable_ctx_params; 330 } 331 332 const OSSL_DISPATCH ossl_ed25519_signature_functions[] = { 333 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, 334 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, 335 (void (*)(void))eddsa_digest_signverify_init }, 336 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, 337 (void (*)(void))ed25519_digest_sign }, 338 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, 339 (void (*)(void))eddsa_digest_signverify_init }, 340 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, 341 (void (*)(void))ed25519_digest_verify }, 342 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, 343 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, 344 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params }, 345 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, 346 (void (*)(void))eddsa_gettable_ctx_params }, 347 { 0, NULL } 348 }; 349 350 const OSSL_DISPATCH ossl_ed448_signature_functions[] = { 351 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, 352 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, 353 (void (*)(void))eddsa_digest_signverify_init }, 354 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, 355 (void (*)(void))ed448_digest_sign }, 356 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, 357 (void (*)(void))eddsa_digest_signverify_init }, 358 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, 359 (void (*)(void))ed448_digest_verify }, 360 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, 361 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, 362 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params }, 363 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, 364 (void (*)(void))eddsa_gettable_ctx_params }, 365 { 0, NULL } 366 }; 367 368 #ifdef S390X_EC_ASM 369 370 static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig, 371 const unsigned char *tbs, size_t tbslen) 372 { 373 int rc; 374 union { 375 struct { 376 unsigned char sig[64]; 377 unsigned char priv[32]; 378 } ed25519; 379 unsigned long long buff[512]; 380 } param; 381 382 memset(¶m, 0, sizeof(param)); 383 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv)); 384 385 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen); 386 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv)); 387 if (rc != 0) 388 return 0; 389 390 s390x_flip_endian32(sig, param.ed25519.sig); 391 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32); 392 return 1; 393 } 394 395 static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig, 396 const unsigned char *tbs, size_t tbslen) 397 { 398 int rc; 399 union { 400 struct { 401 unsigned char sig[128]; 402 unsigned char priv[64]; 403 } ed448; 404 unsigned long long buff[512]; 405 } param; 406 407 memset(¶m, 0, sizeof(param)); 408 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57); 409 410 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen); 411 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv)); 412 if (rc != 0) 413 return 0; 414 415 s390x_flip_endian64(param.ed448.sig, param.ed448.sig); 416 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64); 417 memcpy(sig, param.ed448.sig, 57); 418 memcpy(sig + 57, param.ed448.sig + 64, 57); 419 return 1; 420 } 421 422 static int s390x_ed25519_digestverify(const ECX_KEY *edkey, 423 const unsigned char *sig, 424 const unsigned char *tbs, size_t tbslen) 425 { 426 union { 427 struct { 428 unsigned char sig[64]; 429 unsigned char pub[32]; 430 } ed25519; 431 unsigned long long buff[512]; 432 } param; 433 434 memset(¶m, 0, sizeof(param)); 435 s390x_flip_endian32(param.ed25519.sig, sig); 436 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32); 437 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey); 438 439 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519, 440 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0; 441 } 442 443 static int s390x_ed448_digestverify(const ECX_KEY *edkey, 444 const unsigned char *sig, 445 const unsigned char *tbs, 446 size_t tbslen) 447 { 448 union { 449 struct { 450 unsigned char sig[128]; 451 unsigned char pub[64]; 452 } ed448; 453 unsigned long long buff[512]; 454 } param; 455 456 memset(¶m, 0, sizeof(param)); 457 memcpy(param.ed448.sig, sig, 57); 458 s390x_flip_endian64(param.ed448.sig, param.ed448.sig); 459 memcpy(param.ed448.sig + 64, sig + 57, 57); 460 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64); 461 memcpy(param.ed448.pub, edkey->pubkey, 57); 462 s390x_flip_endian64(param.ed448.pub, param.ed448.pub); 463 464 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448, 465 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0; 466 } 467 468 #endif /* S390X_EC_ASM */ 469