X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=providers%2Fimplementations%2Fkeymgmt%2Fecx_kmgmt.c;h=ae11fd4bc072f146845b42161efc5d1ad700944e;hb=fbce6ebf706cdd273f2569edfea7ade106426e0b;hp=8a9fe1b21b813fdd8712f5804eb342cb204a6352;hpb=c18c301deb44deb27f35c199e8bf44ca8b80e579;p=thirdparty%2Fopenssl.git diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index 8a9fe1b21b..ae11fd4bc0 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,6 +16,7 @@ #include #include #include +#include #include "internal/param_build_set.h" #include #include "crypto/ecx.h" @@ -588,6 +589,74 @@ static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx, return settable; } +#ifdef FIPS_MODULE +/* + * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 + * Perform a pairwise test for EDDSA by signing and verifying signature. + * + * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST + * instance. + */ +static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test) +{ + int ret = 0; + OSSL_SELF_TEST *st = NULL; + OSSL_CALLBACK *cb = NULL; + void *cbarg = NULL; + + unsigned char msg[16] = {0}; + size_t msg_len = sizeof(msg); + unsigned char sig[ED448_SIGSIZE] = {0}; + + int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0; + int operation_result = 0; + + /* + * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st` + * is NULL. + */ + if (self_test) { + OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg); + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + } + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_PCT_EDDSA); + + if (is_ed25519) + operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey, + ecx->privkey, 0, 0, 0, NULL, 0, + ecx->libctx, ecx->propq); + else + operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len, + ecx->pubkey, ecx->privkey, NULL, 0, + 0, ecx->propq); + if (operation_result != 1) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, sig); + + if (is_ed25519) + operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey, + 0, 0, 0, NULL, 0, ecx->libctx, + ecx->propq); + else + operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig, + ecx->pubkey, NULL, 0, 0, ecx->propq); + if (operation_result != 1) + goto err; + + ret = 1; +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + return ret; +} +#endif + static void *ecx_gen(struct ecx_gen_ctx *gctx) { ECX_KEY *key; @@ -684,6 +753,7 @@ static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) { + ECX_KEY *key = NULL; struct ecx_gen_ctx *gctx = genctx; if (!ossl_prov_is_running()) @@ -693,14 +763,31 @@ static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519) && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519) && OPENSSL_s390xcap_P.kdsa[0] - & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) - return s390x_ecd_keygen25519(gctx); + & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) { + key = s390x_ecd_keygen25519(gctx); + } else #endif - return ecx_gen(gctx); + { + key = ecx_gen(gctx); + } + +#ifdef FIPS_MODULE + /* Exit if keygen failed OR we are doing parameter generation (blank key) */ + if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) + return key; + if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + ossl_ecx_key_free(key); + return NULL; + } +#endif + + return key; } static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) { + ECX_KEY *key = NULL; struct ecx_gen_ctx *gctx = genctx; if (!ossl_prov_is_running()) @@ -709,10 +796,26 @@ static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) #ifdef S390X_EC_ASM if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448) && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448) - && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) - return s390x_ecd_keygen448(gctx); + && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) { + key = s390x_ecd_keygen448(gctx); + } else #endif - return ecx_gen(gctx); + { + key = ecx_gen(gctx); + } + +#ifdef FIPS_MODULE + /* Exit if keygen failed OR we are doing parameter generation (blank key) */ + if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) + return key; + if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + ossl_ecx_key_free(key); + return NULL; + } +#endif + + return key; } static void ecx_gen_cleanup(void *genctx) @@ -756,6 +859,23 @@ static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type) case ECX_KEY_TYPE_X448: ossl_x448_public_from_private(pub, ecx->privkey); break; + default: + return 0; + } + return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0; +} + +#ifdef FIPS_MODULE +static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type) +{ + return ecd_fips140_pairwise_test(ecx, type, 0); +} +#else +static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type) +{ + uint8_t pub[64]; + + switch (type) { case ECX_KEY_TYPE_ED25519: if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey, ecx->propq)) @@ -771,6 +891,7 @@ static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type) } return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0; } +#endif static int ecx_validate(const void *keydata, int selection, int type, size_t keylen) { @@ -794,7 +915,12 @@ static int ecx_validate(const void *keydata, int selection, int type, size_t key if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) ok = ok && ecx->privkey != NULL; - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR) + return ok; + + if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448) + ok = ok && ecd_key_pairwise_check(ecx, type); + else ok = ok && ecx_key_pairwise_check(ecx, type); return ok;