diff --git a/include/acvp/acvp.h b/include/acvp/acvp.h index ae78f2ea..79dd121d 100644 --- a/include/acvp/acvp.h +++ b/include/acvp/acvp.h @@ -1,3 +1,4 @@ + /** * @file * @brief This is the public header file to be included by applications @@ -17,6 +18,7 @@ #define acvp_h #include +#include #ifdef __cplusplus extern "C" @@ -273,7 +275,11 @@ typedef enum acvp_cipher { ACVP_SLH_DSA_KEYGEN, ACVP_SLH_DSA_SIGGEN, ACVP_SLH_DSA_SIGVER, - ACVP_CIPHER_END + ACVP_ASCON_AEAD128, // 120 + ACVP_ASCON_CXOF128, + ACVP_ASCON_HASH256, + ACVP_ASCON_XOF128, + ACVP_CIPHER_END } ACVP_CIPHER; @@ -387,6 +393,14 @@ typedef enum acvp_alg_type_dsa { ACVP_SUB_DSA_SIGVER, } ACVP_SUB_DSA; +/** @enum ACVP_SUB_ASCON */ +typedef enum acvp_alg_type_ascon { + ACVP_SUB_ASCON_AEAD128 = ACVP_ASCON_AEAD128, + ACVP_SUB_ASCON_CXOF128, + ACVP_SUB_ASCON_HASH256, + ACVP_SUB_ASCON_XOF128, +} ACVP_SUB_ASCON; + /** @enum ACVP_SUB_RSA */ typedef enum acvp_alg_type_rsa { ACVP_SUB_RSA_KEYGEN = ACVP_RSA_KEYGEN, @@ -1959,6 +1973,61 @@ typedef struct acvp_dsa_tc_t { unsigned char *msg; } ACVP_DSA_TC; +/** @enum ACVP_ASCON_PARM */ +typedef enum acvp_ascon_parm { + ACVP_ASCON_PARM_MODE = 1, + ACVP_ASCON_PARM_REV, + ACVP_ASCON_PARM_DIR, + ACVP_ASCON_PARM_PAYLEN, + ACVP_ASCON_PARM_ADLEN, + ACVP_ASCON_PARM_TAGLEN, + ACVP_ASCON_PARM_NONCEMASK, + ACVP_ASCON_PARM_MSGLEN, + ACVP_ASCON_PARM_OUTLEN, + ACVP_ASCON_PARM_CUSSTRLEN, +} ACVP_ASCON_PARM; + +typedef enum acvp_ascon_direction { + ACVP_ASCON_DIR_ENCRYPT = 1, + ACVP_ASCON_DIR_DECRYPT, + ACVP_ASCON_DIR_BOTH, +} ACVP_ASCON_DIRECTION; + +typedef enum acvp_ascon_testtype { + ACVP_ASCON_AFT = 1, +} ACVP_ASCON_TESTTYPE; + +/** + * @struct ACVP_ASCON_TC + * @brief This struct holds data that represents a single test case for ASCON + * testing. This data is passed between libacvp and the crypto module. + */ +typedef struct acvp_ascon_tc_t { + int tg_id; + int tc_id; + ACVP_CIPHER cipher; + ACVP_ASCON_TESTTYPE testtype; + ACVP_ASCON_DIRECTION direction; // AEAD128 + bool supports_nonce_mask; // AEAD128 + unsigned char *key; // AEAD128 + unsigned char *second_key; // AEAD128 + unsigned char *nonce; // AEAD128 + unsigned char *ad; // AEAD128 + int ad_len; // AEAD128 + unsigned char *tag; // AEAD128 + int tag_len; // AEAD128 + bool tag_match; // AEAD128 + unsigned char *pt; // AEAD128 + unsigned char *ct; // AEAD128 + int payload_len; // AEAD128 + unsigned char *msg; // CXOF128, Hash256, XOF128 + int msg_len; // CXOF128, Hash256, XOF128 + unsigned char *md; // CXOF128, XOF128 + int out_len; // CXOF128, XOF128 + unsigned char *cs; // CXOF128 + int cs_len; // CXOF128 +} ACVP_ASCON_TC; + /** @enum ACVP_KAS_ECC_MODE */ typedef enum acvp_kas_ecc_mode { ACVP_KAS_ECC_MODE_COMPONENT = 1, @@ -2997,11 +3066,14 @@ typedef struct acvp_test_case_t { ACVP_ML_DSA_TC *ml_dsa; ACVP_ML_KEM_TC *ml_kem; ACVP_SLH_DSA_TC *slh_dsa; - } tc; //!< the union abstracting the test case for passing to the user application + ACVP_ASCON_TC *ascon; + } tc; //!< the union abstracting the test case for passing to the user + //!< application } ACVP_TEST_CASE; + /** @defgroup APIs Public APIs for libacvp * @brief this section describes APIs for libacvp. */ @@ -3332,6 +3404,38 @@ ACVP_RESULT acvp_cap_dsa_set_parm(ACVP_CTX *ctx, ACVP_DSA_PARM param, int value); +/** + * @brief acvp_enable_ascon_cap() + * This function should be used to enable ASCON capabilities. Specific + * modes and parameters can use acvp_cap_ascon_set_parm. + * + * When the application enables a crypto capability, such as ASCON, it + * also needs to specify a callback function that will be used by libacvp when + * that crypto capability is needed during a test session. + * + * @param ctx Pointer to ACVP_CTX that was previously created by calling + * acvp_create_test_session. + * @param cipher ACVP_CIPHER enum value identifying the crypto capability. + * @param crypto_handler Address of function implemented by application that is + * invoked by libacvp when the crypto capability is needed during a test + * session. This crypto_handler function is expected to return 0 on success and + * 1 for failure. + * + * @return ACVP_RESULT + */ +ACVP_RESULT +acvp_cap_ascon_enable(ACVP_CTX *ctx, ACVP_CIPHER cipher, + int (*crypto_handler)(ACVP_TEST_CASE *test_case)); + +ACVP_RESULT +acvp_cap_ascon_set_parm(ACVP_CTX *ctx, ACVP_CIPHER cipher, + ACVP_ASCON_PARM param, int value); + +ACVP_RESULT +acvp_cap_ascon_set_domain(ACVP_CTX *ctx, ACVP_CIPHER cipher, + ACVP_ASCON_PARM param, int min, + int max, int increment); + /** * @brief acvp_enable_kas_ecc_cap() * This function should be used to enable KAS-ECC capabilities. Specific modes and diff --git a/include/acvp/acvp_lcl.h b/include/acvp/acvp_lcl.h index b0c5af52..a2547f46 100755 --- a/include/acvp/acvp_lcl.h +++ b/include/acvp/acvp_lcl.h @@ -164,6 +164,9 @@ // DSA #define ACVP_REV_DSA ACVP_REV_STR_1_0 +// ASCON +#define ACVP_REV_ASCON "SP800-232" + // RSA #define ACVP_REV_RSA ACVP_REV_STR_FIPS186_5 #define ACVP_REV_RSA_DECPRIM ACVP_REV_STR_SP800_56BR2 @@ -307,6 +310,12 @@ #define ACVP_ALG_CSHAKE_128 "cSHAKE-128" #define ACVP_ALG_CSHAKE_256 "cSHAKE-256" +#define ACVP_ALG_ASCON "ASCON" +#define ACVP_ALG_ASCON_AEAD128 "AEAD128" +#define ACVP_ALG_ASCON_CXOF128 "CXOF128" +#define ACVP_ALG_ASCON_HASH256 "Hash256" +#define ACVP_ALG_ASCON_XOF128 "XOF128" + #define ACVP_ALG_DSA "DSA" #define ACVP_ALG_DSA_PQGGEN "pqgGen" #define ACVP_ALG_DSA_PQGVER "pqgVer" @@ -858,6 +867,23 @@ #define ACVP_DSA_SEED_MAX_BYTES (ACVP_DSA_SEED_MAX / 2) #define ACVP_DSA_MAX_STRING 3072 //!< 3072 bytes +#define ACVP_ASCON_MSG_BIT_MAX 65536 +#define ACVP_ASCON_MSG_BYTE_MAX (ACVP_ASCON_MSG_BIT_MAX >> 3) +#define ACVP_ASCON_MSG_STRING_MAX (ACVP_ASCON_MSG_BIT_MAX >> 2) +#define ACVP_ASCON_TAG_BIT_MAX 128 +#define ACVP_ASCON_TAG_BYTE_MAX (ACVP_ASCON_TAG_BIT_MAX >> 3) +#define ACVP_ASCON_TAG_STRING_MAX (ACVP_ASCON_TAG_BIT_MAX >> 2) +#define ACVP_ASCON_KEY_BIT_MAX 128 +#define ACVP_ASCON_KEY_BYTE_MAX (ACVP_ASCON_TAG_BIT_MAX >> 3) +#define ACVP_ASCON_NONCE_BIT_MAX 128 +#define ACVP_ASCON_NONCE_BYTE_MAX (ACVP_ASCON_TAG_BIT_MAX >> 3) +#define ACVP_ASCON_HASH_BIT_MAX 256 +#define ACVP_ASCON_HASH_BYTE_MAX (ACVP_ASCON_HASH_BIT_MAX >> 3) +#define ACVP_ASCON_HASH_STRING_MAX (ACVP_ASCON_HASH_BIT_MAX >> 2) +#define ACVP_ASCON_CS_BIT_MAX 2048 +#define ACVP_ASCON_CS_BYTE_MAX (ACVP_ASCON_CS_BIT_MAX >> 3) +#define ACVP_ASCON_CS_STRING_MAX (ACVP_ASCON_CS_BIT_MAX >> 2) + #define ACVP_ECDSA_EXP_LEN_MAX 512 #define ACVP_ECDSA_MSGLEN_MAX 8192 @@ -1078,6 +1104,7 @@ struct acvp_alg_handler_t { ACVP_SUB_ML_DSA ml_dsa; ACVP_SUB_ML_KEM ml_kem; ACVP_SUB_SLH_DSA slh_dsa; + ACVP_SUB_ASCON ascon; } alg; }; @@ -1179,7 +1206,12 @@ typedef enum acvp_capability_type { ACVP_ML_KEM_XCAP_TYPE, ACVP_SLH_DSA_KEYGEN_TYPE, ACVP_SLH_DSA_SIGGEN_TYPE, - ACVP_SLH_DSA_SIGVER_TYPE + ACVP_SLH_DSA_SIGVER_TYPE, + ACVP_ASCON_TYPE, + ACVP_ASCON_AEAD128_TYPE, + ACVP_ASCON_CXOF128_TYPE, + ACVP_ASCON_HASH256_TYPE, + ACVP_ASCON_XOF128_TYPE, } ACVP_CAP_TYPE; /* @@ -1548,6 +1580,19 @@ typedef struct acvp_dsa_capability { ACVP_DSA_CAP_MODE *dsa_cap_mode; } ACVP_DSA_CAP; +#define ACVP_ASCON_MAX_MODES 4 +typedef struct acvp_ascon_capability { + ACVP_CIPHER cipher; + ACVP_ASCON_DIRECTION direction; + ACVP_JSON_DOMAIN_OBJ payload_len; + ACVP_JSON_DOMAIN_OBJ ad_len; + ACVP_JSON_DOMAIN_OBJ tag_len; + bool nonce_masking; + ACVP_JSON_DOMAIN_OBJ msg_len; + ACVP_JSON_DOMAIN_OBJ out_len; + ACVP_JSON_DOMAIN_OBJ custom_len; +} ACVP_ASCON_CAP; + typedef struct acvp_kas_ecc_mac { int alg; int curve; @@ -1786,6 +1831,7 @@ typedef struct acvp_caps_list_t { ACVP_HASH_CAP *hash_cap; ACVP_DRBG_CAP *drbg_cap; ACVP_DSA_CAP *dsa_cap; + ACVP_ASCON_CAP *ascon_cap; ACVP_HMAC_CAP *hmac_cap; ACVP_CMAC_CAP *cmac_cap; ACVP_KMAC_CAP *kmac_cap; @@ -2149,6 +2195,8 @@ ACVP_RESULT acvp_kdf_tls13_kat_handler(ACVP_CTX *ctx, JSON_Object *obj); ACVP_RESULT acvp_dsa_kat_handler(ACVP_CTX *ctx, JSON_Object *obj); +ACVP_RESULT acvp_ascon_kat_handler(ACVP_CTX *ctx, JSON_Object *obj); + ACVP_RESULT acvp_kas_ecc_kat_handler(ACVP_CTX *ctx, JSON_Object *obj); ACVP_RESULT acvp_kas_ecc_ssc_kat_handler(ACVP_CTX *ctx, JSON_Object *obj); diff --git a/src/Makefile.am b/src/Makefile.am index def1abd8..650ce9b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ libacvp_la_SOURCES = acvp.c \ acvp_operating_env.c \ acvp_parse.c \ acvp_aes.c \ + acvp_ascon.c \ acvp_des.c \ acvp_hash.c \ acvp_drbg.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 352f1148..85dd6aad 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -138,7 +138,7 @@ libacvp_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libacvp_la_OBJECTS = acvp.lo acvp_build_register.lo \ acvp_capabilities.lo acvp_operating_env.lo acvp_parse.lo \ - acvp_aes.lo acvp_des.lo acvp_hash.lo acvp_drbg.lo \ + acvp_aes.lo acvp_ascon.lo acvp_des.lo acvp_hash.lo acvp_drbg.lo \ acvp_transport.lo acvp_util.lo parson.lo acvp_hmac.lo \ acvp_cmac.lo acvp_kmac.lo acvp_cshake.lo acvp_rsa_keygen.lo \ acvp_rsa_sig.lo acvp_rsa_prim.lo acvp_dsa.lo \ @@ -382,6 +382,7 @@ libacvp_la_SOURCES = acvp.c \ acvp_operating_env.c \ acvp_parse.c \ acvp_aes.c \ + acvp_ascon.c \ acvp_des.c \ acvp_hash.c \ acvp_drbg.c \ @@ -823,6 +824,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/acvp.Plo -rm -f ./$(DEPDIR)/acvp_aes.Plo + -rm -f ./$(DEPDIR)/acvp_ascon.Plo -rm -f ./$(DEPDIR)/acvp_build_register.Plo -rm -f ./$(DEPDIR)/acvp_capabilities.Plo -rm -f ./$(DEPDIR)/acvp_cmac.Plo diff --git a/src/acvp.c b/src/acvp.c index f1318231..46661019 100644 --- a/src/acvp.c +++ b/src/acvp.c @@ -181,8 +181,11 @@ ACVP_ALG_HANDLER alg_tbl[ACVP_ALG_MAX] = { { ACVP_ML_KEM_XCAP, &acvp_ml_kem_kat_handler, ACVP_ALG_ML_KEM, ACVP_ALG_ML_KEM_XCAP, ACVP_REV_ML_KEM, {.ml_kem = ACVP_SUB_ML_KEM_XCAP}}, { ACVP_SLH_DSA_KEYGEN, &acvp_slh_dsa_kat_handler, ACVP_ALG_SLH_DSA, ACVP_ALG_SLH_DSA_KEYGEN, ACVP_REV_SLH_DSA, {.slh_dsa = ACVP_SUB_SLH_DSA_KEYGEN}}, { ACVP_SLH_DSA_SIGGEN, &acvp_slh_dsa_kat_handler, ACVP_ALG_SLH_DSA, ACVP_ALG_SLH_DSA_SIGGEN, ACVP_REV_SLH_DSA, {.slh_dsa = ACVP_SUB_SLH_DSA_SIGGEN}}, - { ACVP_SLH_DSA_SIGVER, &acvp_slh_dsa_kat_handler, ACVP_ALG_SLH_DSA, ACVP_ALG_SLH_DSA_SIGVER, ACVP_REV_SLH_DSA, {.slh_dsa = ACVP_SUB_SLH_DSA_SIGVER}} -}; + { ACVP_SLH_DSA_SIGVER, &acvp_slh_dsa_kat_handler, ACVP_ALG_SLH_DSA, ACVP_ALG_SLH_DSA_SIGVER, ACVP_REV_SLH_DSA, {.slh_dsa = ACVP_SUB_SLH_DSA_SIGVER}}, + { ACVP_ASCON_AEAD128, &acvp_ascon_kat_handler, ACVP_ALG_ASCON, ACVP_ALG_ASCON_AEAD128, ACVP_REV_ASCON, {.ascon = ACVP_SUB_ASCON_AEAD128}}, + { ACVP_ASCON_CXOF128, &acvp_ascon_kat_handler, ACVP_ALG_ASCON, ACVP_ALG_ASCON_CXOF128, ACVP_REV_ASCON, {.ascon = ACVP_SUB_ASCON_CXOF128}}, + { ACVP_ASCON_HASH256, &acvp_ascon_kat_handler, ACVP_ALG_ASCON, ACVP_ALG_ASCON_HASH256, ACVP_REV_ASCON, {.ascon = ACVP_SUB_ASCON_HASH256}}, + { ACVP_ASCON_XOF128, &acvp_ascon_kat_handler, ACVP_ALG_ASCON, ACVP_ALG_ASCON_XOF128, ACVP_REV_ASCON, {.ascon = ACVP_SUB_ASCON_XOF128}}}; /* * This is the first function the user should invoke to allocate @@ -735,6 +738,15 @@ ACVP_RESULT acvp_free_test_session(ACVP_CTX *ctx) { acvp_cap_free_dsa_attrs(cap_entry); free(cap_entry->cap.dsa_cap); break; + case ACVP_ASCON_TYPE: + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->payload_len); + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->ad_len); + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->tag_len); + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->msg_len); + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->out_len); + acvp_cap_free_domain(&cap_entry->cap.ascon_cap->custom_len); + free(cap_entry->cap.ascon_cap); + break; case ACVP_KAS_ECC_CDH_TYPE: case ACVP_KAS_ECC_COMP_TYPE: case ACVP_KAS_ECC_NOCOMP_TYPE: diff --git a/src/acvp_ascon.c b/src/acvp_ascon.c new file mode 100644 index 00000000..69a25fac --- /dev/null +++ b/src/acvp_ascon.c @@ -0,0 +1,1146 @@ +#include +#include +#include +#include + +#include "acvp.h" +#include "acvp_lcl.h" +#include "parson.h" +#include "safe_lib.h" + +static ACVP_RESULT acvp_ascon_output_tc(ACVP_CTX *ctx, ACVP_ASCON_TC *stc, + JSON_Object *tc_rsp) { + + ACVP_RESULT rv = ACVP_SUCCESS; + + json_object_set_number(tc_rsp, "tcId", stc->tc_id); + + char *tmp_tag = calloc(ACVP_ASCON_TAG_STRING_MAX + 1, sizeof(char)); + if (!tmp_tag) { + ACVP_LOG_ERR("Unable to malloc in acvp_ascon_output_tc"); + return ACVP_MALLOC_FAIL; + } + char *tmp_md = calloc(ACVP_ASCON_MSG_STRING_MAX + 1, sizeof(char)); + if (!tmp_md) { + ACVP_LOG_ERR("Unable to malloc in acvp_ascon_output_tc"); + return ACVP_MALLOC_FAIL; + } + char *tmp_txt = calloc(ACVP_ASCON_MSG_STRING_MAX + 1, sizeof(char)); + if (!tmp_txt) { + ACVP_LOG_ERR("Unable to malloc in acvp_ascon_output_tc"); + return ACVP_MALLOC_FAIL; + } + + switch (stc->cipher) { + case ACVP_ASCON_AEAD128: + if (stc->direction == ACVP_ASCON_DIR_DECRYPT) { + json_object_set_boolean(tc_rsp, "testPassed", stc->tag_match); + rv = acvp_bin_to_hexstr(stc->pt, stc->payload_len, tmp_txt, + ACVP_ASCON_MSG_STRING_MAX); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (pt)"); + goto end; + } + json_object_set_string(tc_rsp, "pt", tmp_txt); + } + if (stc->direction == ACVP_ASCON_DIR_ENCRYPT) { + rv = acvp_bin_to_hexstr(stc->ct, stc->payload_len, tmp_txt, + ACVP_ASCON_MSG_STRING_MAX); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (ct)"); + goto end; + } + json_object_set_string(tc_rsp, "ct", tmp_tag); + rv = acvp_bin_to_hexstr(stc->tag, stc->tag_len, tmp_tag, + ACVP_ASCON_TAG_STRING_MAX); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (tag)"); + goto end; + } + json_object_set_string(tc_rsp, "tag", tmp_tag); + } + break; + case ACVP_ASCON_CXOF128: + case ACVP_ASCON_HASH256: + case ACVP_ASCON_XOF128: + rv = acvp_bin_to_hexstr(stc->md, stc->out_len, tmp_md, + ACVP_ASCON_MSG_STRING_MAX); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (md)"); + goto end; + } + json_object_set_string(tc_rsp, "md", tmp_md); + break; + default: + rv = ACVP_INVALID_ARG; + goto end; + } + +end: + if (tmp_txt) + free(tmp_txt); + if (tmp_tag) + free(tmp_tag); + if (tmp_md) + free(tmp_md); + + return rv; +} + +static ACVP_RESULT acvp_ascon_aead128_init_tc( + ACVP_CTX *ctx, ACVP_ASCON_TC *stc, ACVP_ASCON_TESTTYPE testtype, int tg_id, + unsigned int tc_id, ACVP_ASCON_DIRECTION direction, + bool supports_nonce_mask, const char *key, const char *nonce, + const char *ad, int ad_len, const char *tag, int tag_len, const char *pt, + const char *ct, int payload_len, const char *second_key) { + + if (payload_len == 0 || tag_len == 0) { + return ACVP_INVALID_ARG; + } + + if (!key || !nonce) { + return ACVP_INVALID_ARG; + } + + memzero_s(stc, sizeof(ACVP_ASCON_TC)); + + stc->testtype = testtype; + stc->cipher = ACVP_ASCON_AEAD128; + stc->direction = direction; + stc->supports_nonce_mask = supports_nonce_mask; + stc->tc_id = tc_id; + stc->tg_id = tg_id; + + stc->ad = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->ad) { + return ACVP_MALLOC_FAIL; + } + stc->ad_len = ad_len; + ACVP_RESULT rv = acvp_hexstr_to_bin(ad, stc->ad, ACVP_ASCON_MSG_STRING_MAX, + &(stc->ad_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (ad)"); + return rv; + } + + stc->pt = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->pt) { + return ACVP_MALLOC_FAIL; + } + stc->ct = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->ct) { + return ACVP_MALLOC_FAIL; + } + stc->payload_len = payload_len; + + stc->key = calloc(1, ACVP_ASCON_KEY_BYTE_MAX); + if (!stc->key) { + return ACVP_MALLOC_FAIL; + } + rv = acvp_hexstr_to_bin(key, stc->key, ACVP_ASCON_KEY_BYTE_MAX, NULL); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (key)"); + return rv; + } + if (supports_nonce_mask) { + if (!second_key) { + return ACVP_INVALID_ARG; + } + + stc->second_key = calloc(1, ACVP_ASCON_KEY_BYTE_MAX); + rv = acvp_hexstr_to_bin(second_key, stc->second_key, + ACVP_ASCON_KEY_BYTE_MAX, NULL); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (second_key)"); + return rv; + } + } + stc->nonce = calloc(1, ACVP_ASCON_NONCE_BYTE_MAX); + if (!stc->nonce) { + return ACVP_MALLOC_FAIL; + } + rv = acvp_hexstr_to_bin(nonce, stc->nonce, ACVP_ASCON_NONCE_BYTE_MAX, NULL); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (nonce)"); + return rv; + } + + if (stc->direction == ACVP_ASCON_DIR_DECRYPT) { + stc->tag = calloc(1, ACVP_ASCON_TAG_BYTE_MAX); + stc->tag_len = tag_len; + rv = acvp_hexstr_to_bin(tag, stc->tag, ACVP_ASCON_TAG_BYTE_MAX, + &(stc->tag_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (tag)"); + return rv; + } + } + switch (stc->direction) { + case ACVP_ASCON_DIR_ENCRYPT: + rv = acvp_hexstr_to_bin(pt, stc->pt, ACVP_ASCON_MSG_STRING_MAX, + &(stc->payload_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (pt)"); + return rv; + } + break; + case ACVP_ASCON_DIR_DECRYPT: + rv = acvp_hexstr_to_bin(ct, stc->ct, ACVP_ASCON_MSG_STRING_MAX, + &(stc->payload_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (ct)"); + return rv; + } + break; + default: + ACVP_LOG_ERR("Invalid direction argument %d", direction); + return ACVP_INVALID_ARG; + } + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_ascon_cxof128_init_tc(ACVP_CTX *ctx, ACVP_ASCON_TC *stc, + int tg_id, unsigned int tc_id, + ACVP_ASCON_TESTTYPE testtype, + unsigned char *msg, int msg_len, + int out_len, unsigned char *cs, + int cs_len) { + if (msg_len == 0 || out_len == 0 || cs_len == 0) { + return ACVP_INVALID_ARG; + } + + memzero_s(stc, sizeof(ACVP_ASCON_TC)); + + stc->testtype = testtype; + stc->cipher = ACVP_ASCON_XOF128; + stc->tc_id = tc_id; + stc->tg_id = tg_id; + + stc->msg = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->msg) { + return ACVP_MALLOC_FAIL; + } + stc->msg_len = msg_len; + ACVP_RESULT rv = acvp_hexstr_to_bin( + msg, stc->msg, ACVP_ASCON_MSG_STRING_MAX, &(stc->msg_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (msg)"); + return rv; + } + + stc->cs = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->cs) { + return ACVP_MALLOC_FAIL; + } + stc->cs_len = cs_len; + rv = acvp_hexstr_to_bin(cs, stc->cs, ACVP_ASCON_MSG_STRING_MAX, + &(stc->cs_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (cs)"); + return rv; + } + + stc->md = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->md) { + return ACVP_MALLOC_FAIL; + } + stc->out_len = out_len; + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_ascon_hash256_init_tc(ACVP_CTX *ctx, ACVP_ASCON_TC *stc, + int tg_id, unsigned int tc_id, + ACVP_ASCON_TESTTYPE testtype, + unsigned char *msg, int msg_len) { + + if (msg_len == 0) { + return ACVP_INVALID_ARG; + } + + memzero_s(stc, sizeof(ACVP_ASCON_TC)); + + stc->testtype = testtype; + stc->cipher = ACVP_ASCON_HASH256; + stc->tc_id = tc_id; + stc->tg_id = tg_id; + + stc->msg = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->msg) { + return ACVP_MALLOC_FAIL; + } + stc->msg_len = msg_len; + ACVP_RESULT rv = + acvp_hexstr_to_bin((const char *)msg, stc->msg, + ACVP_ASCON_MSG_STRING_MAX, &(stc->msg_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (msg)"); + return rv; + } + + stc->md = calloc(1, ACVP_ASCON_HASH_STRING_MAX); + if (!stc->md) { + return ACVP_MALLOC_FAIL; + } + stc->out_len = ACVP_ASCON_HASH_BYTE_MAX; + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_ascon_xof128_init_tc(ACVP_CTX *ctx, ACVP_ASCON_TC *stc, + int tg_id, unsigned int tc_id, + ACVP_ASCON_TESTTYPE testtype, + unsigned char *msg, int msg_len, + int out_len) { + if (msg_len == 0 || out_len == 0) { + return ACVP_INVALID_ARG; + } + + memzero_s(stc, sizeof(ACVP_ASCON_TC)); + + stc->testtype = testtype; + stc->cipher = ACVP_ASCON_XOF128; + stc->tc_id = tc_id; + stc->tg_id = tg_id; + + stc->msg = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->msg) { + return ACVP_MALLOC_FAIL; + } + stc->msg_len = msg_len; + ACVP_RESULT rv = acvp_hexstr_to_bin( + msg, stc->msg, ACVP_ASCON_MSG_STRING_MAX, &(stc->msg_len)); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Hex conversion failure (msg)"); + return rv; + } + + stc->md = calloc(1, ACVP_ASCON_MSG_STRING_MAX); + if (!stc->md) { + return ACVP_MALLOC_FAIL; + } + stc->out_len = out_len; + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_ascon_release_tc(ACVP_ASCON_TC *stc) { + if (stc->msg) + free(stc->msg); + if (stc->pt) + free(stc->pt); + if (stc->ct) + free(stc->ct); + if (stc->key) + free(stc->key); + if (stc->nonce) + free(stc->nonce); + if (stc->tag) + free(stc->tag); + if (stc->second_key) + free(stc->second_key); + if (stc->md) + free(stc->md); + memzero_s(stc, sizeof(ACVP_CMAC_TC)); + + return ACVP_SUCCESS; +} + +ACVP_RESULT acvp_ascon_aead128_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { + ACVP_RESULT rv = ACVP_SUCCESS; + char *alg_str = NULL; + ACVP_TEST_CASE tc; + ACVP_ASCON_TC stc; + ACVP_CIPHER alg_id = 0; + ACVP_CAPS_LIST *cap = NULL; + JSON_Array *reg_array = NULL, *r_garr = NULL, + *groups = NULL, *r_tarr = NULL, + *tests = NULL; + JSON_Value *reg_array_val = NULL, + *r_vs_val = NULL, *groupval = NULL, + *r_gval = NULL; + JSON_Object *reg_obj = NULL, *r_vs = NULL, + *groupobj = NULL, *r_gobj = NULL; + const char *type_str = NULL, *direction_str = NULL; + ACVP_ASCON_DIRECTION direction = 0; + bool supports_nonce_masking = false; + const char *key = NULL, *second_key = NULL, + *nonce = NULL, *tag = NULL, + *ad = NULL, *pt = NULL, *ct = NULL; + unsigned int payload_len = 0, ad_len = 0, + tag_len = 0; + JSON_Value *mval = json_value_init_object(); + JSON_Object *mobj = json_value_get_object(mval); + char *json_result = NULL; + + alg_str = json_object_get_string(obj, "algorithm"); + if (!alg_str) { + ACVP_LOG_ERR("unable to parse 'algorithm' from JSON"); + return ACVP_MALFORMED_JSON; + } + + // Get a reference to the abstracted test case + tc.tc.ascon = &stc; + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + + // Get the crypto module handler for ASCON mode + alg_id = ACVP_ASCON_AEAD128; + stc.cipher = alg_id; + cap = acvp_locate_cap_entry(ctx, alg_id); + if (!cap) { + ACVP_LOG_ERR("ACVP server requesting unsupported capability"); + return ACVP_UNSUPPORTED_OP; + } + + // Create ACVP array for response + rv = acvp_create_array(®_obj, ®_array_val, ®_array); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to create JSON response struct."); + goto err; + } + + // Start to build the JSON response + rv = acvp_setup_json_rsp_group(&ctx, ®_array_val, &r_vs_val, &r_vs, + alg_str, &r_garr); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to setup json response"); + goto err; + } + + groups = json_object_get_array(obj, "testGroups"); + if (!groups) { + ACVP_LOG_ERR("Failed to include testGroups."); + rv = ACVP_MISSING_ARG; + goto err; + } + const unsigned int g_cnt = json_array_get_count(groups); + + for (unsigned int i = 0; i < g_cnt; i++) { + groupval = json_array_get_value(groups, i); + groupobj = json_value_get_object(groupval); + + /* + * Create a new group in the response with the tgid + * and an array of tests + */ + r_gval = json_value_init_object(); + r_gobj = json_value_get_object(r_gval); + int tgId = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, obj, "tgId", &tgId); + if (rv != ACVP_SUCCESS) { + goto err; + } + json_object_set_number(r_gobj, "tgId", tgId); + json_object_set_value(r_gobj, "tests", json_value_init_array()); + r_tarr = json_object_get_array(r_gobj, "tests"); + + stc.cipher = ACVP_ASCON_AEAD128; + + ACVP_LOG_VERBOSE(" Test group: %d", i); + + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_ASCON_TESTTYPE type; + rv = acvp_tc_json_get_string(ctx, alg_id, groupobj, "testType", + &type_str); + if (rv != ACVP_SUCCESS) { + goto err; + } + if (strcmp(type_str, "AFT") == 0) { + type = ACVP_ASCON_AFT; + } else { + rv = ACVP_INVALID_ARG; + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, groupobj, "direction", + &direction_str); + if (rv != ACVP_SUCCESS) { + goto err; + } + if (strcmp(direction_str, "encrypt") == 0) { + direction = ACVP_ASCON_DIR_ENCRYPT; + } else if (strcmp(direction_str, "decrypt") == 0) { + direction = ACVP_ASCON_DIR_DECRYPT; + } else { + rv = ACVP_INVALID_ARG; + goto err; + } + + rv = acvp_tc_json_get_boolean(ctx, alg_id, groupobj, + "supportsNonceMasking", + (int *)&supports_nonce_masking); + + rv = acvp_tc_json_get_array(ctx, alg_id, groupobj, "tests", &tests); + if (rv != ACVP_SUCCESS) { + goto err; + } + const int t_cnt = json_array_get_count(tests); + + for (unsigned int j = 0; j < t_cnt; j++) { + JSON_Value *testval = json_array_get_value(tests, j); + JSON_Object *testobj = json_value_get_object(testval); + + unsigned int tc_id = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "tcId", + (int *)&tc_id); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "key", &key); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "secondKey", + &second_key); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "nonce", &nonce); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "ad", &ad); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "tag", &tag); + if (rv != ACVP_SUCCESS) { + goto err; + } + + switch (direction) { + case ACVP_ASCON_DIR_ENCRYPT: + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "pt", &pt); + if (rv != ACVP_SUCCESS) { + goto err; + } + break; + case ACVP_ASCON_DIR_DECRYPT: + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "ct", &ct); + if (rv != ACVP_SUCCESS) { + goto err; + } + break; + } + + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "payloadLen", + (int *)&payload_len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "adLen", + (int *)&ad_len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "tagLen", + (int *)&tag_len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_LOG_VERBOSE(" Test case: %d", j); + ACVP_LOG_VERBOSE(" tcId: %d", tc_id); + ACVP_LOG_VERBOSE(" key: %s", key); + ACVP_LOG_VERBOSE(" nonce: %s", nonce); + ACVP_LOG_VERBOSE(" ad: %s", ad); + ACVP_LOG_VERBOSE(" tag: %s", tag); + ACVP_LOG_VERBOSE(" pt: %s", pt); + ACVP_LOG_VERBOSE(" ct: %s", ct); + ACVP_LOG_VERBOSE(" payloadLen: %s", payload_len); + ACVP_LOG_VERBOSE(" adLen: %s", ad_len); + ACVP_LOG_VERBOSE(" tagLen: %s", tag_len); + ACVP_LOG_VERBOSE(" secondKey: %s", second_key); + + acvp_ascon_aead128_init_tc(ctx, &stc, type, tgId, tc_id, direction, + supports_nonce_masking, key, nonce, ad, + ad_len, tag, tag_len, pt, ct, + payload_len, second_key); + + if ((cap->crypto_handler)(&tc)) { + ACVP_LOG_ERR("Crypto module failed the operation"); + rv = ACVP_CRYPTO_MODULE_FAIL; + goto err; + } + + // Output the test case results using JSON + rv = acvp_ascon_output_tc(ctx, &stc, mobj); + json_array_append_value(r_tarr, mval); + } + + json_array_append_value(r_garr, r_gval); + acvp_ascon_release_tc(&stc); + } + + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + json_array_append_value(reg_array, r_vs_val); + json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); + ACVP_LOG_VERBOSE("\n\n%s\n\n", json_result); + json_free_serialized_string(json_result); + rv = ACVP_SUCCESS; + +err: + if (rv != ACVP_SUCCESS) { + acvp_ascon_release_tc(&stc); + } + return rv; +} + +ACVP_RESULT acvp_ascon_cxof128_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { + const char *alg_str = json_object_get_string(obj, "algorithm"); + if (!alg_str) { + ACVP_LOG_ERR("unable to parse 'algorithm' from JSON"); + return ACVP_MALFORMED_JSON; + } + + // Get a reference to the abstracted test case + ACVP_TEST_CASE tc; + ACVP_ASCON_TC stc; + tc.tc.ascon = &stc; + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + + // Get the crypto module handler for ASCON mode + const ACVP_CIPHER alg_id = ACVP_ASCON_CXOF128; + stc.cipher = alg_id; + const ACVP_CAPS_LIST *cap = acvp_locate_cap_entry(ctx, alg_id); + if (!cap) { + ACVP_LOG_ERR("ACVP server requesting unsupported capability"); + return ACVP_UNSUPPORTED_OP; + } + + // Create ACVP array for response + JSON_Array *reg_array = NULL; + JSON_Value *reg_array_val = NULL; + JSON_Object *reg_obj = NULL; + ACVP_RESULT rv = acvp_create_array(®_obj, ®_array_val, ®_array); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to create JSON response struct."); + goto err; + } + + // Start to build the JSON response + JSON_Value *r_vs_val = NULL; + JSON_Array *r_garr = NULL; // Response testarray, grouparray + JSON_Object *r_vs = NULL; + rv = acvp_setup_json_rsp_group(&ctx, ®_array_val, &r_vs_val, &r_vs, + alg_str, &r_garr); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to setup json response"); + goto err; + } + + const JSON_Array *groups = json_object_get_array(obj, "testGroups"); + if (!groups) { + ACVP_LOG_ERR("Failed to include testGroups."); + rv = ACVP_MISSING_ARG; + goto err; + } + const unsigned int g_cnt = json_array_get_count(groups); + + for (unsigned int i = 0; i < g_cnt; i++) { + const JSON_Value *groupval = json_array_get_value(groups, i); + JSON_Object *groupobj = json_value_get_object(groupval); + + /* + * Create a new group in the response with the tgid + * and an array of tests + */ + JSON_Value *r_gval = json_value_init_object(); + JSON_Object *r_gobj = json_value_get_object(r_gval); + int tgId = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, obj, "tgId", &tgId); + if (rv != ACVP_SUCCESS) { + goto err; + } + json_object_set_number(r_gobj, "tgId", tgId); + json_object_set_value(r_gobj, "tests", json_value_init_array()); + JSON_Array *r_tarr = json_object_get_array(r_gobj, "tests"); + + stc.cipher = ACVP_ASCON_CXOF128; + + ACVP_LOG_VERBOSE(" Test group: %d", i); + + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_ASCON_TESTTYPE type; + const char *type_str; + rv = acvp_tc_json_get_string(ctx, alg_id, groupobj, "testType", + &type_str); + if (rv != ACVP_SUCCESS) { + goto err; + } + if (strcmp(type_str, "AFT") == 0) { + type = ACVP_ASCON_AFT; + } else { + rv = ACVP_INVALID_ARG; + goto err; + } + + JSON_Array *tests = NULL; + rv = acvp_tc_json_get_array(ctx, alg_id, groupobj, "tests", &tests); + if (rv != ACVP_SUCCESS) { + goto err; + } + const int t_cnt = json_array_get_count(tests); + + for (unsigned int j = 0; j < t_cnt; j++) { + JSON_Value *testval = json_array_get_value(tests, j); + JSON_Object *testobj = json_value_get_object(testval); + + unsigned int tc_id = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "tcId", + (int *)&tc_id); + if (rv != ACVP_SUCCESS) { + goto err; + } + + const char *msg; + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "msg", &msg); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int len = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "len", (int *)&len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int outlen = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "outLen", (int *)&outlen); + if (rv != ACVP_SUCCESS) { + goto err; + } + + const char *cs; + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "cs", &cs); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int cslen = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "csLen", (int *)&cslen); + if (rv != ACVP_SUCCESS) { + goto err; + } + + + + ACVP_LOG_VERBOSE(" Test case: %d", j); + ACVP_LOG_VERBOSE(" tcId: %d", tc_id); + ACVP_LOG_VERBOSE(" msg: %s", msg); + ACVP_LOG_VERBOSE(" len: %s", len); + ACVP_LOG_VERBOSE(" outlen: %s", outlen); + ACVP_LOG_VERBOSE(" cs: %s", cs); + ACVP_LOG_VERBOSE(" csLen: %s", cslen); + acvp_ascon_cxof128_init_tc(ctx, &stc, tgId, tc_id, type, msg, len, outlen, cs, cslen); + + if ((cap->crypto_handler)(&tc)) { + ACVP_LOG_ERR("Crypto module failed the operation"); + rv = ACVP_CRYPTO_MODULE_FAIL; + goto err; + } + + JSON_Value *mval = json_value_init_object(); + JSON_Object *mobj = json_value_get_object(mval); + // Output the test case results using JSON + rv = acvp_ascon_output_tc(ctx, &stc, mobj); + json_array_append_value(r_tarr, mval); + } + + json_array_append_value(r_garr, r_gval); + acvp_ascon_release_tc(&stc); + } + + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + json_array_append_value(reg_array, r_vs_val); + char *json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); + ACVP_LOG_VERBOSE("\n\n%s\n\n", json_result); + json_free_serialized_string(json_result); + rv = ACVP_SUCCESS; + +err: + if (rv != ACVP_SUCCESS) { + acvp_ascon_release_tc(&stc); + } + return rv; +} + + +ACVP_RESULT acvp_ascon_hash256_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { + const char *alg_str = json_object_get_string(obj, "algorithm"); + if (!alg_str) { + ACVP_LOG_ERR("unable to parse 'algorithm' from JSON"); + return ACVP_MALFORMED_JSON; + } + + // Get a reference to the abstracted test case + ACVP_TEST_CASE tc; + ACVP_ASCON_TC stc; + tc.tc.ascon = &stc; + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + + // Get the crypto module handler for ASCON mode + const ACVP_CIPHER alg_id = ACVP_ASCON_HASH256; + stc.cipher = alg_id; + const ACVP_CAPS_LIST *cap = acvp_locate_cap_entry(ctx, alg_id); + if (!cap) { + ACVP_LOG_ERR("ACVP server requesting unsupported capability"); + return ACVP_UNSUPPORTED_OP; + } + + // Create ACVP array for response + JSON_Array *reg_array = NULL; + JSON_Value *reg_array_val = NULL; + JSON_Object *reg_obj = NULL; + ACVP_RESULT rv = acvp_create_array(®_obj, ®_array_val, ®_array); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to create JSON response struct."); + goto err; + } + + // Start to build the JSON response + JSON_Value *r_vs_val = NULL; + JSON_Array *r_garr = NULL; // Response testarray, grouparray + JSON_Object *r_vs = NULL; + rv = acvp_setup_json_rsp_group(&ctx, ®_array_val, &r_vs_val, &r_vs, + alg_str, &r_garr); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to setup json response"); + goto err; + } + + const JSON_Array *groups = json_object_get_array(obj, "testGroups"); + if (!groups) { + ACVP_LOG_ERR("Failed to include testGroups."); + rv = ACVP_MISSING_ARG; + goto err; + } + const unsigned int g_cnt = json_array_get_count(groups); + + for (unsigned int i = 0; i < g_cnt; i++) { + const JSON_Value *groupval = json_array_get_value(groups, i); + JSON_Object *groupobj = json_value_get_object(groupval); + + /* + * Create a new group in the response with the tgid + * and an array of tests + */ + JSON_Value *r_gval = json_value_init_object(); + JSON_Object *r_gobj = json_value_get_object(r_gval); + int tgId = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, obj, "tgId", &tgId); + if (rv != ACVP_SUCCESS) { + goto err; + } + json_object_set_number(r_gobj, "tgId", tgId); + json_object_set_value(r_gobj, "tests", json_value_init_array()); + JSON_Array *r_tarr = json_object_get_array(r_gobj, "tests"); + + stc.cipher = ACVP_ASCON_HASH256; + + ACVP_LOG_VERBOSE(" Test group: %d", i); + + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_ASCON_TESTTYPE type; + const char *type_str; + rv = acvp_tc_json_get_string(ctx, alg_id, groupobj, "testType", + &type_str); + if (rv != ACVP_SUCCESS) { + goto err; + } + if (strcmp(type_str, "AFT") == 0) { + type = ACVP_ASCON_AFT; + } else { + rv = ACVP_INVALID_ARG; + goto err; + } + + JSON_Array *tests = NULL; + rv = acvp_tc_json_get_array(ctx, alg_id, groupobj, "tests", &tests); + if (rv != ACVP_SUCCESS) { + goto err; + } + const int t_cnt = json_array_get_count(tests); + + for (unsigned int j = 0; j < t_cnt; j++) { + JSON_Value *testval = json_array_get_value(tests, j); + JSON_Object *testobj = json_value_get_object(testval); + + unsigned int tc_id = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "tcId", + (int *)&tc_id); + if (rv != ACVP_SUCCESS) { + goto err; + } + + const char *msg; + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "msg", &msg); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int len = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "len", (int *)&len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_LOG_VERBOSE(" Test case: %d", j); + ACVP_LOG_VERBOSE(" tcId: %d", tc_id); + ACVP_LOG_VERBOSE(" msg: %s", msg); + ACVP_LOG_VERBOSE(" len: %s", len); + + acvp_ascon_hash256_init_tc(ctx, &stc, tgId, tc_id, type, msg, len); + + if ((cap->crypto_handler)(&tc)) { + ACVP_LOG_ERR("Crypto module failed the operation"); + rv = ACVP_CRYPTO_MODULE_FAIL; + goto err; + } + + JSON_Value *mval = json_value_init_object(); + JSON_Object *mobj = json_value_get_object(mval); + // Output the test case results using JSON + rv = acvp_ascon_output_tc(ctx, &stc, mobj); + json_array_append_value(r_tarr, mval); + } + + json_array_append_value(r_garr, r_gval); + acvp_ascon_release_tc(&stc); + } + + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + json_array_append_value(reg_array, r_vs_val); + char *json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); + ACVP_LOG_VERBOSE("\n\n%s\n\n", json_result); + json_free_serialized_string(json_result); + rv = ACVP_SUCCESS; + +err: + if (rv != ACVP_SUCCESS) { + acvp_ascon_release_tc(&stc); + } + return rv; +} + +ACVP_RESULT acvp_ascon_xof128_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { + const char *alg_str = json_object_get_string(obj, "algorithm"); + if (!alg_str) { + ACVP_LOG_ERR("unable to parse 'algorithm' from JSON"); + return ACVP_MALFORMED_JSON; + } + + // Get a reference to the abstracted test case + ACVP_TEST_CASE tc; + ACVP_ASCON_TC stc; + tc.tc.ascon = &stc; + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + + // Get the crypto module handler for ASCON mode + const ACVP_CIPHER alg_id = ACVP_ASCON_XOF128; + stc.cipher = alg_id; + const ACVP_CAPS_LIST *cap = acvp_locate_cap_entry(ctx, alg_id); + if (!cap) { + ACVP_LOG_ERR("ACVP server requesting unsupported capability"); + return ACVP_UNSUPPORTED_OP; + } + + // Create ACVP array for response + JSON_Array *reg_array = NULL; + JSON_Value *reg_array_val = NULL; + JSON_Object *reg_obj = NULL; + ACVP_RESULT rv = acvp_create_array(®_obj, ®_array_val, ®_array); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to create JSON response struct."); + goto err; + } + + // Start to build the JSON response + JSON_Value *r_vs_val = NULL; + JSON_Array *r_garr = NULL; // Response testarray, grouparray + JSON_Object *r_vs = NULL; + rv = acvp_setup_json_rsp_group(&ctx, ®_array_val, &r_vs_val, &r_vs, + alg_str, &r_garr); + if (rv != ACVP_SUCCESS) { + ACVP_LOG_ERR("Failed to setup json response"); + goto err; + } + + const JSON_Array *groups = json_object_get_array(obj, "testGroups"); + if (!groups) { + ACVP_LOG_ERR("Failed to include testGroups."); + rv = ACVP_MISSING_ARG; + goto err; + } + const unsigned int g_cnt = json_array_get_count(groups); + + for (unsigned int i = 0; i < g_cnt; i++) { + const JSON_Value *groupval = json_array_get_value(groups, i); + JSON_Object *groupobj = json_value_get_object(groupval); + + /* + * Create a new group in the response with the tgid + * and an array of tests + */ + JSON_Value *r_gval = json_value_init_object(); + JSON_Object *r_gobj = json_value_get_object(r_gval); + int tgId = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, obj, "tgId", &tgId); + if (rv != ACVP_SUCCESS) { + goto err; + } + json_object_set_number(r_gobj, "tgId", tgId); + json_object_set_value(r_gobj, "tests", json_value_init_array()); + JSON_Array *r_tarr = json_object_get_array(r_gobj, "tests"); + + stc.cipher = ACVP_ASCON_XOF128; + + ACVP_LOG_VERBOSE(" Test group: %d", i); + + if (rv != ACVP_SUCCESS) { + goto err; + } + + ACVP_ASCON_TESTTYPE type; + const char *type_str; + rv = acvp_tc_json_get_string(ctx, alg_id, groupobj, "testType", + &type_str); + if (rv != ACVP_SUCCESS) { + goto err; + } + if (strcmp(type_str, "AFT") == 0) { + type = ACVP_ASCON_AFT; + } else { + rv = ACVP_INVALID_ARG; + goto err; + } + + JSON_Array *tests = NULL; + rv = acvp_tc_json_get_array(ctx, alg_id, groupobj, "tests", &tests); + if (rv != ACVP_SUCCESS) { + goto err; + } + const int t_cnt = json_array_get_count(tests); + + for (unsigned int j = 0; j < t_cnt; j++) { + JSON_Value *testval = json_array_get_value(tests, j); + JSON_Object *testobj = json_value_get_object(testval); + + unsigned int tc_id = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "tcId", + (int *)&tc_id); + if (rv != ACVP_SUCCESS) { + goto err; + } + + const char *msg; + rv = acvp_tc_json_get_string(ctx, alg_id, testobj, "msg", &msg); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int len = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "len", (int *)&len); + if (rv != ACVP_SUCCESS) { + goto err; + } + + unsigned int outlen = 0; + rv = acvp_tc_json_get_int(ctx, alg_id, testobj, "outLen", (int *)&outlen); + if (rv != ACVP_SUCCESS) { + goto err; + } + + + ACVP_LOG_VERBOSE(" Test case: %d", j); + ACVP_LOG_VERBOSE(" tcId: %d", tc_id); + ACVP_LOG_VERBOSE(" msg: %s", msg); + ACVP_LOG_VERBOSE(" len: %s", len); + ACVP_LOG_VERBOSE(" outlen: %s", outlen); + + acvp_ascon_xof128_init_tc(ctx, &stc, tgId, tc_id, type, msg, len, outlen); + + if ((cap->crypto_handler)(&tc)) { + ACVP_LOG_ERR("Crypto module failed the operation"); + rv = ACVP_CRYPTO_MODULE_FAIL; + goto err; + } + + JSON_Value *mval = json_value_init_object(); + JSON_Object *mobj = json_value_get_object(mval); + // Output the test case results using JSON + rv = acvp_ascon_output_tc(ctx, &stc, mobj); + json_array_append_value(r_tarr, mval); + } + + json_array_append_value(r_garr, r_gval); + acvp_ascon_release_tc(&stc); + } + + memzero_s(&stc, sizeof(ACVP_ASCON_TC)); + json_array_append_value(reg_array, r_vs_val); + char *json_result = json_serialize_to_string_pretty(ctx->kat_resp, NULL); + ACVP_LOG_VERBOSE("\n\n%s\n\n", json_result); + json_free_serialized_string(json_result); + rv = ACVP_SUCCESS; + +err: + if (rv != ACVP_SUCCESS) { + acvp_ascon_release_tc(&stc); + } + return rv; +} + +#define ASCON_MODE_STR_MAX 7 + +ACVP_RESULT acvp_ascon_kat_handler(ACVP_CTX *ctx, JSON_Object *obj) { + + if (!ctx) { + ACVP_LOG_ERR("CTX is NULL."); + return ACVP_NO_CTX; + } + + if (!obj) { + ACVP_LOG_ERR("OBJ is NULL."); + return ACVP_MALFORMED_JSON; + } + + const char *mode = json_object_get_string(obj, "mode"); + int diff = 0; + if (!mode) { + ACVP_LOG_ERR("Failed to include mode."); + return ACVP_MISSING_ARG; + } + + strcmp_s(ACVP_ALG_ASCON_AEAD128, ASCON_MODE_STR_MAX, mode, &diff); + if (!diff) + return acvp_ascon_aead128_kat_handler(ctx, obj); + + strcmp_s(ACVP_ALG_ASCON_CXOF128, ASCON_MODE_STR_MAX, mode, &diff); + if (!diff) + return acvp_ascon_cxof128_kat_handler(ctx, obj); + + strcmp_s(ACVP_ALG_ASCON_HASH256, ASCON_MODE_STR_MAX, mode, &diff); + if (!diff) + return acvp_ascon_hash256_kat_handler(ctx, obj); + + strcmp_s(ACVP_ALG_ASCON_XOF128, ASCON_MODE_STR_MAX, mode, &diff); + if (!diff) + return acvp_ascon_xof128_kat_handler(ctx, obj); +} diff --git a/src/acvp_build_register.c b/src/acvp_build_register.c index 944fc3f8..235044d3 100644 --- a/src/acvp_build_register.c +++ b/src/acvp_build_register.c @@ -2996,6 +2996,297 @@ static ACVP_RESULT acvp_build_dsa_register_cap(JSON_Object *cap_obj, return ACVP_SUCCESS; } +static ACVP_RESULT acvp_build_ascon_aead128_cap(ACVP_CTX *ctx, + JSON_Object *cap_obj, + ACVP_CAPS_LIST *cap_entry) { + json_object_set_value(cap_obj, "direction", json_value_init_array()); + JSON_Array *d_arr = json_object_get_array(cap_obj, "direction"); + + ACVP_ASCON_CAP *cap = cap_entry->cap.ascon_cap; + + switch (cap->direction) { + case ACVP_ASCON_DIR_ENCRYPT: + ACVP_LOG_INFO(" Direction: Encrypt"); + json_array_append_string(d_arr, "encrypt"); + break; + case ACVP_ASCON_DIR_DECRYPT: + ACVP_LOG_INFO(" Direction: Decrypt"); + json_array_append_string(d_arr, "decrypt"); + break; + case ACVP_ASCON_DIR_BOTH: + ACVP_LOG_INFO(" Direction: Both Encrypt and Decrypt"); + json_array_append_string(d_arr, "encrypt"); + json_array_append_string(d_arr, "decrypt"); + default: + break; + } + + // Set payload data length array + json_object_set_value(cap_obj, "payloadLen", json_value_init_array()); + JSON_Array *pl_arr = json_object_get_array(cap_obj, "payloadLen"); + + if (cap->payload_len.increment != 0) { + JSON_Value *pl_value = json_value_init_object(); + JSON_Object *pl_obj = json_value_get_object(pl_value); + json_object_set_number(pl_obj, "min", cap->payload_len.min); + json_object_set_number(pl_obj, "max", cap->payload_len.max); + json_object_set_number(pl_obj, "increment", cap->payload_len.increment); + json_array_append_value(pl_arr, pl_value); + ACVP_LOG_INFO(" PayloadLen: { min = %d, max = %d, increment = %d}", + cap->payload_len.min, cap->payload_len.max, + cap->payload_len.increment); + } + + struct acvp_sl_list_t* list = cap->payload_len.values; + while (list) { + json_array_append_number(pl_arr, list->length); + list = list->next; + } + + + // Set associated data length array + json_object_set_value(cap_obj, "adLen", json_value_init_array()); + JSON_Array *ad_arr = json_object_get_array(cap_obj, "adLen"); + + if (cap->ad_len.increment != 0) { + JSON_Value *ad_value = json_value_init_object(); + JSON_Object *ad_obj = json_value_get_object(ad_value); + json_object_set_number(ad_obj, "min", cap->ad_len.min); + json_object_set_number(ad_obj, "max", cap->ad_len.max); + json_object_set_number(ad_obj, "increment", cap->payload_len.increment); + json_array_append_value(ad_arr, ad_value); + ACVP_LOG_INFO(" AdLen: { min = %d, max = %d, increment = %d}", + cap->ad_len.min, cap->ad_len.max, cap->ad_len.increment); + } + + list = cap->ad_len.values; + while (list) { + json_array_append_number(ad_arr, list->length); + list = list->next; + } + + // Set tag length array + json_object_set_value(cap_obj, "tagLen", json_value_init_array()); + JSON_Array *tag_arr = json_object_get_array(cap_obj, "tagLen"); + + + if (cap->tag_len.increment != 0) { + JSON_Value *tag_value = json_value_init_object(); + JSON_Object *tag_obj = json_value_get_object(tag_value); + json_object_set_number(tag_obj, "min", cap->tag_len.min); + json_object_set_number(tag_obj, "max", cap->tag_len.max); + json_object_set_number(tag_obj, "increment", cap->payload_len.increment); + json_array_append_value(tag_arr, tag_value); + ACVP_LOG_INFO(" TagLen: { min = %d, max = %d, increment = %d}", + cap->tag_len.min, cap->tag_len.max, cap->tag_len.increment); + } + + list = cap->tag_len.values; + while (list) { + json_array_append_number(tag_arr, list->length); + list = list->next; + } + + json_object_set_value(cap_obj, "supportsNonceMasking", + json_value_init_array()); + JSON_Array *nonce_arr = + json_object_get_array(cap_obj, "supportsNonceMasking"); + json_array_append_boolean(nonce_arr, cap->nonce_masking); + ACVP_LOG_INFO(" NonceMask: %d", cap->nonce_masking); + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_build_ascon_cxof128_cap(ACVP_CTX *ctx, + JSON_Object *cap_obj, + ACVP_CAPS_LIST *cap_entry) { + ACVP_ASCON_CAP *cap = cap_entry->cap.ascon_cap; + + // set message length array + json_object_set_value(cap_obj, "messageLength", json_value_init_array()); + JSON_Array *msg_arr = json_object_get_array(cap_obj, "messageLength"); + if (cap->msg_len.increment != 0) { + JSON_Value *msg_value = json_value_init_object(); + JSON_Object *msg_obj = json_value_get_object(msg_value); + json_object_set_number(msg_obj, "min", cap->msg_len.min); + json_object_set_number(msg_obj, "max", cap->msg_len.max); + json_object_set_number(msg_obj, "increment", cap->msg_len.increment); + json_array_append_value(msg_arr, msg_value); + } + + struct acvp_sl_list_t* list = cap->msg_len.values; + while (list) { + json_array_append_number(msg_arr, list->length); + list = list->next; + } + + // set output length array + json_object_set_value(cap_obj, "outputLength", json_value_init_array()); + JSON_Array *out_arr = json_object_get_array(cap_obj, "outputLength"); + if (cap->out_len.increment != 0) { + JSON_Value *out_value = json_value_init_object(); + JSON_Object *out_obj = json_value_get_object(out_value); + json_object_set_number(out_obj, "min", cap->out_len.min); + json_object_set_number(out_obj, "max", cap->out_len.max); + json_object_set_number(out_obj, "increment", cap->out_len.increment); + json_array_append_value(out_arr, out_value); + } + + list = cap->out_len.values; + while (list) { + json_array_append_number(out_arr, list->length); + list = list->next; + } + + // set customization string length array + json_object_set_value(cap_obj, "customizationStringLength", json_value_init_array()); + JSON_Array *cstr_arr = json_object_get_array(cap_obj, "customizationStringLength"); + if (cap->custom_len.increment != 0) { + JSON_Value *cstr_value = json_value_init_object(); + JSON_Object *cstr_obj = json_value_get_object(cstr_value); + json_object_set_number(cstr_obj, "min", cap->custom_len.min); + json_object_set_number(cstr_obj, "max", cap->custom_len.max); + json_object_set_number(cstr_obj, "increment", cap->custom_len.increment); + json_array_append_value(cstr_arr, cstr_value); + } + + list = cap->custom_len.values; + while (list) { + json_array_append_number(cstr_arr, list->length); + list = list->next; + } + + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_build_ascon_hash256_cap(ACVP_CTX *ctx, + JSON_Object *cap_obj, + ACVP_CAPS_LIST *cap_entry) { + ACVP_ASCON_CAP *cap = cap_entry->cap.ascon_cap; + + json_object_set_value(cap_obj, "messageLength", json_value_init_array()); + JSON_Array *msg_arr = json_object_get_array(cap_obj, "messageLength"); + if (cap->msg_len.increment != 0) { + JSON_Value *msg_value = json_value_init_object(); + JSON_Object *msg_obj = json_value_get_object(msg_value); + json_object_set_number(msg_obj, "min", cap->msg_len.min); + json_object_set_number(msg_obj, "max", cap->msg_len.max); + json_object_set_number(msg_obj, "increment", cap->msg_len.increment); + json_array_append_value(msg_arr, msg_value); + } + + struct acvp_sl_list_t* list = cap->msg_len.values; + while (list) { + json_array_append_number(msg_arr, list->length); + list = list->next; + } + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_build_ascon_xof128_cap(ACVP_CTX *ctx, + JSON_Object *cap_obj, + ACVP_CAPS_LIST *cap_entry) { + ACVP_ASCON_CAP *cap = cap_entry->cap.ascon_cap; + + json_object_set_value(cap_obj, "messageLength", json_value_init_array()); + JSON_Array *msg_arr = json_object_get_array(cap_obj, "outputLength"); + if (cap->msg_len.increment != 0) { + JSON_Value *msg_value = json_value_init_object(); + JSON_Object *msg_obj = json_value_get_object(msg_value); + json_object_set_number(msg_obj, "min", cap->msg_len.min); + json_object_set_number(msg_obj, "max", cap->msg_len.max); + json_object_set_number(msg_obj, "increment", cap->msg_len.increment); + json_array_append_value(msg_arr, msg_value); + } + + struct acvp_sl_list_t* list = cap->msg_len.values; + while (list) { + json_array_append_number(msg_arr, list->length); + list = list->next; + } + + json_object_set_value(cap_obj, "outputLength", json_value_init_array()); + JSON_Array *out_arr = json_object_get_array(cap_obj, "outputLength"); + if (cap->out_len.increment != 0) { + JSON_Value *out_value = json_value_init_object(); + JSON_Object *out_obj = json_value_get_object(out_value); + json_object_set_number(out_obj, "min", cap->out_len.min); + json_object_set_number(out_obj, "max", cap->out_len.max); + json_object_set_number(out_obj, "increment", cap->out_len.increment); + json_array_append_value(out_arr, out_value); + } + + list = cap->out_len.values; + while (list) { + json_array_append_number(out_arr, list->length); + list = list->next; + } + + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_build_ascon_register_cap(ACVP_CTX *ctx, + JSON_Object *cap_obj, + ACVP_CAPS_LIST *cap_entry) { + ACVP_RESULT result; + const char *revision = NULL; + + if (!cap_entry->cap.ascon_cap) { + return ACVP_NO_CAP; + } + + ACVP_ASCON_CAP *cap = cap_entry->cap.ascon_cap; + + json_object_set_string(cap_obj, "algorithm", "Ascon"); + + revision = acvp_lookup_cipher_revision(cap_entry->cipher); + if (revision == NULL) + return ACVP_INVALID_ARG; + json_object_set_string(cap_obj, "revision", revision); + + switch (cap->cipher) { + case ACVP_ASCON_AEAD128: + json_object_set_string(cap_obj, "mode", "AEAD128"); + break; + case ACVP_ASCON_CXOF128: + json_object_set_string(cap_obj, "mode", "CXOF128"); + break; + case ACVP_ASCON_HASH256: + json_object_set_string(cap_obj, "mode", "Hash256"); + break; + case ACVP_ASCON_XOF128: + json_object_set_string(cap_obj, "mode", "XOF128"); + break; + default: + return ACVP_INVALID_ARG; + } + result = acvp_lookup_prereqVals(cap_obj, cap_entry); + if (result != ACVP_SUCCESS) { + return result; + } + + switch (cap_entry->cipher) { + case ACVP_ASCON_AEAD128: + acvp_build_ascon_aead128_cap(ctx, cap_obj, cap_entry); + break; + case ACVP_ASCON_CXOF128: + acvp_build_ascon_cxof128_cap(ctx, cap_obj, cap_entry); + break; + case ACVP_ASCON_HASH256: + acvp_build_ascon_hash256_cap(ctx, cap_obj, cap_entry); + break; + case ACVP_ASCON_XOF128: + acvp_build_ascon_xof128_cap(ctx, cap_obj, cap_entry); + break; + default: + return ACVP_NO_CAP; + } + return ACVP_SUCCESS; +} + static ACVP_RESULT acvp_lookup_kas_ecc_prereqVals(JSON_Object *cap_obj, ACVP_KAS_ECC_CAP_MODE *kas_ecc_mode) { JSON_Array *prereq_array = NULL; @@ -5667,6 +5958,12 @@ ACVP_RESULT acvp_build_registration_json(ACVP_CTX *ctx, JSON_Value **reg) { case ACVP_DSA_SIGVER: rv = acvp_build_dsa_register_cap(cap_obj, cap_entry, ACVP_DSA_MODE_SIGVER); break; + case ACVP_ASCON_AEAD128: + case ACVP_ASCON_CXOF128: + case ACVP_ASCON_HASH256: + case ACVP_ASCON_XOF128: + rv = acvp_build_ascon_register_cap(ctx, cap_obj, cap_entry); + break; case ACVP_RSA_KEYGEN: rv = acvp_build_rsa_keygen_register_cap(cap_obj, cap_entry); break; @@ -6070,4 +6367,3 @@ ACVP_RESULT acvp_build_validation(ACVP_CTX *ctx, return ACVP_SUCCESS; } - diff --git a/src/acvp_capabilities.c b/src/acvp_capabilities.c index 5a552763..ad5f7606 100644 --- a/src/acvp_capabilities.c +++ b/src/acvp_capabilities.c @@ -54,6 +54,18 @@ static ACVP_DSA_CAP *allocate_dsa_cap(void) { return cap; } +static ACVP_ASCON_CAP *allocate_ascon_cap(void) { + ACVP_ASCON_CAP *cap = NULL; + + // Allocate the capability object + cap = calloc(1, sizeof(ACVP_ASCON_CAP)); + if (!cap) + return NULL; + + // Allocate the array of ascon_mode + return cap; +} + static ACVP_KAS_ECC_CAP *allocate_kas_ecc_cap(void) { ACVP_KAS_ECC_CAP *cap = NULL; ACVP_KAS_ECC_CAP_MODE *modes = NULL; @@ -207,6 +219,32 @@ static ACVP_RESULT acvp_cap_list_append(ACVP_CTX *ctx, } break; + case ACVP_ASCON_TYPE: + cap_entry->cap.ascon_cap = allocate_ascon_cap(); + if (!cap_entry->cap.ascon_cap) { + rv = ACVP_MALLOC_FAIL; + goto err; + } + + switch (cipher) { + case ACVP_ASCON_AEAD128: + cap_entry->cap.ascon_cap->cipher = ACVP_ASCON_AEAD128; + break; + case ACVP_ASCON_CXOF128: + cap_entry->cap.ascon_cap->cipher = ACVP_ASCON_CXOF128; + break; + case ACVP_ASCON_HASH256: + cap_entry->cap.ascon_cap->cipher = ACVP_ASCON_HASH256; + break; + case ACVP_ASCON_XOF128: + cap_entry->cap.ascon_cap->cipher = ACVP_ASCON_XOF128; + break; + default: + ACVP_LOG_ERR("Invalid cipher type for Ascon [found: %d]", cipher); + rv = ACVP_INVALID_ARG; + goto err; + } + break; case ACVP_ECDSA_KEYGEN_TYPE: if (cipher != ACVP_ECDSA_KEYGEN) { rv = ACVP_INVALID_ARG; @@ -1745,6 +1783,11 @@ static ACVP_RESULT acvp_validate_prereq_val(ACVP_CIPHER cipher, ACVP_PREREQ_ALG return ACVP_SUCCESS; } break; + case ACVP_ASCON_AEAD128: + case ACVP_ASCON_CXOF128: + case ACVP_ASCON_HASH256: + case ACVP_ASCON_XOF128: + return ACVP_SUCCESS; case ACVP_RSA_KEYGEN: case ACVP_RSA_SIGGEN: case ACVP_RSA_SIGVER: @@ -5603,7 +5646,6 @@ ACVP_RESULT acvp_cap_eddsa_enable(ACVP_CTX *ctx, return result; } - // The user should call this after invoking acvp_enable_dsa_cap(). ACVP_RESULT acvp_cap_dsa_set_parm(ACVP_CTX *ctx, ACVP_CIPHER cipher, @@ -5662,6 +5704,259 @@ ACVP_RESULT acvp_cap_dsa_set_parm(ACVP_CTX *ctx, return result; } +ACVP_RESULT acvp_cap_ascon_set_parm(ACVP_CTX *ctx, ACVP_CIPHER cipher, + ACVP_ASCON_PARM param, int value) { + if (cipher != ACVP_ASCON_AEAD128) { + return ACVP_INVALID_ARG; + } + + // Locate this cipher in the caps array + ACVP_CAPS_LIST *cap_list = acvp_locate_cap_entry(ctx, cipher); + if (!cap_list) { + ACVP_LOG_ERR("Cap entry not found."); + return ACVP_NO_CAP; + } + ACVP_ASCON_CAP *ascon_cap = cap_list->cap.ascon_cap; + if (ascon_cap->cipher != ACVP_ASCON_AEAD128) { + ACVP_LOG_ERR("Only Ascon AEAD128 mode can have values set (expected: " + "%d, found: %d)", + ACVP_ASCON_AEAD128, ascon_cap->cipher); + return ACVP_INVALID_ARG; + } + ACVP_ASCON_DIRECTION dir = 0; + + switch (param) { + case ACVP_ASCON_PARM_NONCEMASK: + ascon_cap->nonce_masking = (bool)value; + break; + case ACVP_ASCON_PARM_DIR: + dir = (ACVP_ASCON_DIRECTION)value; + + if (dir != ACVP_ASCON_DIR_ENCRYPT && dir != ACVP_ASCON_DIR_DECRYPT && dir != ACVP_ASCON_DIR_BOTH) { + ACVP_LOG_ERR("Bad direction value"); + return ACVP_INVALID_ARG; + } + + ascon_cap->direction = dir; + + break; + case ACVP_ASCON_PARM_ADLEN: + if (value > 0 && value < ACVP_ASCON_MSG_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + + if (acvp_append_sl_list(&ascon_cap->ad_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON associated data length to list"); + return ACVP_MALLOC_FAIL; + } + break; + case ACVP_ASCON_PARM_TAGLEN: + if (value > 0 && value < ACVP_ASCON_TAG_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + if (acvp_append_sl_list(&ascon_cap->tag_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON tag length to list"); + return ACVP_MALLOC_FAIL; + } + break; + case ACVP_ASCON_PARM_PAYLEN: + if (value > 0 && value < ACVP_ASCON_MSG_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + + if (acvp_append_sl_list(&ascon_cap->payload_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON payload length to list"); + return ACVP_MALLOC_FAIL; + } + break; + case ACVP_ASCON_PARM_MSGLEN: + if (value > 0 && value < ACVP_ASCON_MSG_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + + if (acvp_append_sl_list(&ascon_cap->msg_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON message length to list"); + return ACVP_MALLOC_FAIL; + } + break; + case ACVP_ASCON_PARM_OUTLEN: + if (value > 0 && value < ACVP_ASCON_MSG_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + + if (acvp_append_sl_list(&ascon_cap->out_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON output length to list"); + return ACVP_MALLOC_FAIL; + } + break; + case ACVP_ASCON_PARM_CUSSTRLEN: + if (value > 0 && value < ACVP_ASCON_CS_BYTE_MAX) { + return ACVP_INVALID_ARG; + } + + if (acvp_append_sl_list(&ascon_cap->custom_len.values, value) != ACVP_SUCCESS) { + ACVP_LOG_ERR("Error adding ASCON customization string length to list"); + return ACVP_MALLOC_FAIL; + } + break; + default: + ACVP_LOG_ERR("Bad parameter name."); + return ACVP_INVALID_ARG; + } + + return ACVP_SUCCESS; +} + +static ACVP_RESULT acvp_cap_ascon_aead128_set_domain(ACVP_ASCON_CAP *cap, + ACVP_ASCON_PARM param, + int min, int max, + int increment) { + switch (param) { + case ACVP_ASCON_PARM_PAYLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + cap->payload_len.min = min; + cap->payload_len.max = max; + cap->payload_len.increment = increment; + break; + case ACVP_ASCON_PARM_ADLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + cap->ad_len.min = min; + cap->ad_len.max = max; + cap->ad_len.increment = increment; + break; + case ACVP_ASCON_PARM_TAGLEN: + if (min > 0 && min < ACVP_ASCON_TAG_BYTE_MAX + && max > min && max < ACVP_ASCON_TAG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + cap->tag_len.min = min; + cap->tag_len.max = max; + cap->tag_len.increment = increment; + break; + default: + return ACVP_INVALID_ARG; + } + + return ACVP_SUCCESS; +} + +ACVP_RESULT +acvp_cap_ascon_set_domain(ACVP_CTX *ctx, ACVP_CIPHER cipher, + ACVP_ASCON_PARM param, int min, + int max, int increment) { + // Locate this cipher in the caps array + ACVP_CAPS_LIST *cap_list = acvp_locate_cap_entry(ctx, cipher); + if (!cap_list) { + ACVP_LOG_ERR("Cap entry not found."); + return ACVP_NO_CAP; + } + ACVP_ASCON_CAP *ascon_cap = cap_list->cap.ascon_cap; + + switch (cipher) { + case ACVP_ASCON_AEAD128: + return acvp_cap_ascon_aead128_set_domain(ascon_cap, param, min, max, + increment); + case ACVP_ASCON_CXOF128: + switch (param) { + case ACVP_ASCON_PARM_CUSSTRLEN: + if (min > 0 && min < ACVP_ASCON_CS_BYTE_MAX + && max > min && max < ACVP_ASCON_CS_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->custom_len.min = min; + ascon_cap->custom_len.max = max; + ascon_cap->custom_len.increment = increment; + break; + case ACVP_ASCON_PARM_OUTLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->out_len.min = min; + ascon_cap->out_len.max = max; + ascon_cap->out_len.increment = increment; + break; + case ACVP_ASCON_PARM_MSGLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->msg_len.min = min; + ascon_cap->msg_len.max = max; + ascon_cap->msg_len.increment = increment; + break; + default: + return ACVP_INVALID_ARG; + } + break; + case ACVP_ASCON_XOF128: + switch (param) { + case ACVP_ASCON_PARM_OUTLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->out_len.min = min; + ascon_cap->out_len.max = max; + ascon_cap->out_len.increment = increment; + break; + case ACVP_ASCON_PARM_MSGLEN: + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->msg_len.min = min; + ascon_cap->msg_len.max = max; + ascon_cap->msg_len.increment = increment; + break; + default: + return ACVP_INVALID_ARG; + } + break; + case ACVP_ASCON_HASH256: + if (param != ACVP_ASCON_PARM_MSGLEN) { + return ACVP_INVALID_ARG; + } else { + if (min > 0 && min < ACVP_ASCON_MSG_BYTE_MAX + && max > min && max < ACVP_ASCON_MSG_BYTE_MAX + && increment < max - min) { + return ACVP_INVALID_ARG; + } + + ascon_cap->msg_len.min = min; + ascon_cap->msg_len.max = max; + ascon_cap->msg_len.increment = increment; + } + break; + default: + return ACVP_INVALID_ARG; + } + + return ACVP_SUCCESS; +} + /* * The user should call this after invoking acvp_enable_kdf135_snmp_cap() * to specify kdf parameters @@ -6440,6 +6735,31 @@ ACVP_RESULT acvp_cap_dsa_enable(ACVP_CTX *ctx, return result; } +ACVP_RESULT +acvp_cap_ascon_enable(ACVP_CTX *ctx, ACVP_CIPHER cipher, + int (*crypto_handler)(ACVP_TEST_CASE *test_case)) { + ACVP_RESULT result = ACVP_SUCCESS; + + if (!ctx) { + return ACVP_NO_CTX; + } + + if (!crypto_handler) { + ACVP_LOG_ERR("NULL parameter 'crypto_handler'"); + return ACVP_INVALID_ARG; + } + + result = acvp_cap_list_append(ctx, ACVP_ASCON_TYPE, cipher, crypto_handler); + + if (result == ACVP_DUP_CIPHER) { + ACVP_LOG_ERR("Capability previously enabled. Duplicate not allowed."); + } else if (result == ACVP_MALLOC_FAIL) { + ACVP_LOG_ERR("Failed to allocate capability object"); + } + + return result; +} + ACVP_RESULT acvp_cap_kdf135_ikev2_set_parm(ACVP_CTX *ctx, ACVP_KDF135_IKEV2_PARM param, int value) {