/*
- * 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
#include <openssl/proverr.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
+#include <openssl/self_test.h>
#include "internal/param_build_set.h"
#include <openssl/param_build.h>
#include "crypto/ecx.h"
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;
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())
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())
#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)
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))
}
return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
}
+#endif
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
{
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;