From d7d795b7e2214aa47904c6080090baac5363b092 Mon Sep 17 00:00:00 2001 From: Alexander Gebhard Date: Fri, 7 Mar 2025 14:02:45 -0600 Subject: [PATCH 1/4] Add initial support for wolfCrypt --- incdefs.sh | 11 +++++ makefile | 3 ++ sad.c | 6 ++- sad_private.h | 3 +- sad_wolfcrypt.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 sad_wolfcrypt.c diff --git a/incdefs.sh b/incdefs.sh index 060cc0bf..ddf62997 100755 --- a/incdefs.sh +++ b/incdefs.sh @@ -113,6 +113,17 @@ user_flags() done done + # Look for wolfcrypt support. + for d in $dirs; do + files=$(find $d -type f -name hmac.h) + for f in $files; do + if grep -q wc_HmacSetKey $f; then + printf " -DHAVE_WOLFCRYPT" + break 2 + fi + done + done + # Look for openssl support. for d in $dirs; do sdirs=$(find $d -type d -name "openssl") diff --git a/makefile b/makefile index 54bff5b8..0178587e 100644 --- a/makefile +++ b/makefile @@ -60,6 +60,9 @@ SECURITY += sad_gnupg.o else ifneq (,$(findstring -DHAVE_OPENSSL, $(incdefs))) LDLIBS += -lcrypto SECURITY += sad_openssl.o +else ifneq (,$(findstring -DHAVE_WOLFCRYPT, $(incdefs))) +LDLIBS += -lwolfssl +SECURITY += sad_wolfcrypt.o endif prefix = /usr/local diff --git a/sad.c b/sad.c index 2ed05642..d3021a75 100644 --- a/sad.c +++ b/sad.c @@ -754,7 +754,8 @@ int sad_create(struct config *cfg) } #if !defined (HAVE_NETTLE) && !defined (HAVE_GNUTLS) && \ - !defined (HAVE_GNUPG) && !defined (HAVE_OPENSSL) + !defined (HAVE_GNUPG) && !defined (HAVE_OPENSSL) && \ + !defined (HAVE_WOLFCRYPT) pr_err("sa_file set but security not supported"); return -1; #endif @@ -812,7 +813,8 @@ int sad_readiness_check(int spp, size_t active_key_id, struct config *cfg) return 0; } #if !defined (HAVE_NETTLE) && !defined (HAVE_GNUTLS) && \ - !defined (HAVE_GNUPG) && !defined (HAVE_OPENSSL) + !defined (HAVE_GNUPG) && !defined (HAVE_OPENSSL) && \ + !defined (HAVE_WOLFCRYPT) if (spp >= 0 || active_key_id > 0) { pr_err("spp or active_key_id set but security not supported"); return -1; diff --git a/sad_private.h b/sad_private.h index 66d7e700..5a2f7ef9 100644 --- a/sad_private.h +++ b/sad_private.h @@ -37,7 +37,8 @@ struct security_association_key { }; #if defined (HAVE_NETTLE) || defined (HAVE_GNUTLS) || \ - defined (HAVE_GNUPG) || defined (HAVE_OPENSSL) + defined (HAVE_GNUPG) || defined (HAVE_OPENSSL) || \ + defined (HAVE_WOLFCRYPT) struct mac_data *sad_init_mac(integrity_alg_type algorithm, const unsigned char *key, size_t key_len); diff --git a/sad_wolfcrypt.c b/sad_wolfcrypt.c new file mode 100644 index 00000000..545a1be4 --- /dev/null +++ b/sad_wolfcrypt.c @@ -0,0 +1,112 @@ +/** + * @file sad_nettle.c + * @brief Security Association Database nettle functions + * @note Copyright (C) 2024 IBM Corporation, Clay Kaiser + * @note SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include + +#include "print.h" +#include "sad.h" +#include "sad_private.h" + +struct mac_data { + Hmac *hmac; +}; + +struct mac_data *sad_init_mac(integrity_alg_type algorithm, + const unsigned char *key, size_t key_len) +{ + size_t i, length; + const char *name; + const struct Hmac *mac_algorithm = NULL; + struct mac_data *mac_data; + int type; + + /* verify key length */ + if (key_len == 0) { + pr_err("BUG: key_len is zero"); + return NULL; + } + + if (wolfCrypt_Init() != 0) { + pr_err("BUG: wolfCrypt could not initialize"); + return NULL; + } + + mac_data = calloc(1, sizeof(*mac_data)); + if (!mac_data) { + return NULL; + } + + mac_algorithm = calloc(1, sizeof(Hmac)); + if (!mac_algorithm) { + return NULL; + } + + mac_data->hmac = mac_algorithm; + + /* retrieve mac algorithm */ + switch (algorithm) { + case HMAC_SHA256_128: + case HMAC_SHA256: + type = SHA256; + wc_HmacSetKey(mac_algorithm, SHA256, key, key_len); + break; + default: + pr_err("BUG: unknown algorithm"); + return NULL; + } + + return mac_data; +} + +void sad_deinit_mac(struct mac_data *mac_data) +{ + free(mac_data->hmac); + free(mac_data); + wolfCrypt_Cleanup(); +} + +int sad_hash(struct mac_data *mac_data, + const void *data, size_t data_len, + unsigned char *mac, size_t mac_len) +{ + size_t digest_len; + + /* confirm mac length is within library support */ + digest_len = SHA256_DIGEST_SIZE; + if (mac_len > digest_len) { + pr_err("BUG: mac_len larger than library support"); + return 0; + } + + /* confirm mac length is within buffer size */ + if (mac_len > MAX_DIGEST_LENGTH) { + pr_err("BUG: mac_len larger than buffer"); + return 0; + } + + wc_HmacUpdate(mac_data->hmac, data, data_len); + wc_HmacFinal(mac_data->hmac, mac); + + return mac_len; +} + +int sad_verify(struct mac_data *mac_data, + const void *data, size_t data_len, + unsigned char *mac, size_t mac_len) +{ + unsigned char digest_buf[MAX_DIGEST_LENGTH]; + + /* update data and retrieve mac */ + if (!sad_hash(mac_data, data, data_len, digest_buf, mac_len)) { + return -1; + } + + /* compare calculated with received */ + return (XMEMCMP(digest_buf, mac, mac_len) == 0); +} From c45c2b6dc66926bd278b326c362a4d39080eb283 Mon Sep 17 00:00:00 2001 From: Alex Gebhard Date: Fri, 22 Aug 2025 10:10:57 -0500 Subject: [PATCH 2/4] CMAC implementation --- sad_private.h | 1 + sad_wolfcrypt.c | 124 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 87 insertions(+), 38 deletions(-) diff --git a/sad_private.h b/sad_private.h index 5a2f7ef9..8443b5c2 100644 --- a/sad_private.h +++ b/sad_private.h @@ -8,6 +8,7 @@ #define HAVE_SAD_PRIVATE_H #define MAX_DIGEST_LENGTH 32 +#define WOLFSSL_CMAC 1 #include diff --git a/sad_wolfcrypt.c b/sad_wolfcrypt.c index 545a1be4..2e710072 100644 --- a/sad_wolfcrypt.c +++ b/sad_wolfcrypt.c @@ -4,7 +4,10 @@ * @note Copyright (C) 2024 IBM Corporation, Clay Kaiser * @note SPDX-License-Identifier: GPL-2.0+ */ +#define WOLFSSL_CMAC 1 + #include +#include #include #include #include @@ -14,17 +17,20 @@ #include "sad_private.h" struct mac_data { + int type; Hmac *hmac; + Cmac *cmac; }; struct mac_data *sad_init_mac(integrity_alg_type algorithm, const unsigned char *key, size_t key_len) { - size_t i, length; - const char *name; - const struct Hmac *mac_algorithm = NULL; + struct Hmac *mac_algorithm = NULL; + struct Cmac *cmac_algorithm = NULL; struct mac_data *mac_data; - int type; + int ret; + + printf("In sad_init_mac"); /* verify key length */ if (key_len == 0) { @@ -42,20 +48,39 @@ struct mac_data *sad_init_mac(integrity_alg_type algorithm, return NULL; } - mac_algorithm = calloc(1, sizeof(Hmac)); - if (!mac_algorithm) { - return NULL; - } - - mac_data->hmac = mac_algorithm; - /* retrieve mac algorithm */ switch (algorithm) { case HMAC_SHA256_128: case HMAC_SHA256: - type = SHA256; + mac_algorithm = calloc(1, sizeof(Hmac)); + if (!mac_algorithm) + return NULL; + + mac_data->hmac = mac_algorithm; + mac_data->type = HMAC_SHA256; wc_HmacSetKey(mac_algorithm, SHA256, key, key_len); break; + case CMAC_AES128: + case CMAC_AES256: + cmac_algorithm = calloc(1, sizeof(Cmac)); + if (!cmac_algorithm) + return NULL; + + mac_data->cmac = cmac_algorithm; + mac_data->type = algorithm; + if (algorithm == CMAC_AES128 && key_len != 16) { + pr_err("CMAC_AES128 requires a 128-bit key"); + return NULL; + } else if (algorithm == CMAC_AES256 && key_len != 32) { + pr_err("CMAC_AES256 requires a 256-bit key"); + return NULL; + } + + ret = wc_InitCmac(cmac_algorithm, key, key_len, WC_CMAC_AES, NULL); + if (ret) + return NULL; + + break; default: pr_err("BUG: unknown algorithm"); return NULL; @@ -66,7 +91,12 @@ struct mac_data *sad_init_mac(integrity_alg_type algorithm, void sad_deinit_mac(struct mac_data *mac_data) { - free(mac_data->hmac); + printf("In sad_deinit_mac"); + + if (mac_data->hmac) + free(mac_data->hmac); + if (mac_data->cmac) + free(mac_data->cmac); free(mac_data); wolfCrypt_Cleanup(); } @@ -75,25 +105,30 @@ int sad_hash(struct mac_data *mac_data, const void *data, size_t data_len, unsigned char *mac, size_t mac_len) { - size_t digest_len; - - /* confirm mac length is within library support */ - digest_len = SHA256_DIGEST_SIZE; - if (mac_len > digest_len) { - pr_err("BUG: mac_len larger than library support"); - return 0; - } - - /* confirm mac length is within buffer size */ - if (mac_len > MAX_DIGEST_LENGTH) { - pr_err("BUG: mac_len larger than buffer"); - return 0; + printf("In sad_hash"); + if (mac_data->type == SHA256) { + /* confirm mac length is within library support */ + if (mac_len > SHA256_DIGEST_SIZE) { + pr_err("BUG: mac_len larger than library support"); + return 0; + } + + /* confirm mac length is within buffer size */ + if (mac_len > MAX_DIGEST_LENGTH) { + pr_err("BUG: mac_len larger than buffer"); + return 0; + } + + wc_HmacUpdate(mac_data->hmac, data, data_len); + wc_HmacFinal(mac_data->hmac, mac); + + return mac_len; + } else { + wc_CmacUpdate(mac_data->cmac, data, data_len); + wc_CmacFinal(mac_data->cmac, mac, &mac_len); + + return mac_len; } - - wc_HmacUpdate(mac_data->hmac, data, data_len); - wc_HmacFinal(mac_data->hmac, mac); - - return mac_len; } int sad_verify(struct mac_data *mac_data, @@ -101,12 +136,25 @@ int sad_verify(struct mac_data *mac_data, unsigned char *mac, size_t mac_len) { unsigned char digest_buf[MAX_DIGEST_LENGTH]; - - /* update data and retrieve mac */ - if (!sad_hash(mac_data, data, data_len, digest_buf, mac_len)) { - return -1; + unsigned char cmac_buf[16]; + + printf("In sad_verify"); + + if (mac_data->type == SHA256) { + /* update data and retrieve mac */ + if (!sad_hash(mac_data, data, data_len, digest_buf, mac_len)) { + return -1; + } + + /* compare calculated with received */ + return (XMEMCMP(digest_buf, mac, mac_len) == 0); + } else { + /* update data and retrieve mac */ + if (!sad_hash(mac_data, data, data_len, cmac_buf, mac_len)) { + return -1; + } + + /* compare calculated with received */ + return (XMEMCMP(cmac_buf, mac, mac_len) == 0); } - - /* compare calculated with received */ - return (XMEMCMP(digest_buf, mac, mac_len) == 0); } From 5b3ebcb61aee6bb7ba7028dbecf1eed3ac5738b4 Mon Sep 17 00:00:00 2001 From: Alex Gebhard Date: Tue, 26 Aug 2025 10:50:46 -0500 Subject: [PATCH 3/4] Add more error checking. Add support for CMAC --- sad_private.h | 1 - sad_wolfcrypt.c | 292 ++++++++++++++++++++++++++++-------------------- 2 files changed, 170 insertions(+), 123 deletions(-) diff --git a/sad_private.h b/sad_private.h index 8443b5c2..5a2f7ef9 100644 --- a/sad_private.h +++ b/sad_private.h @@ -8,7 +8,6 @@ #define HAVE_SAD_PRIVATE_H #define MAX_DIGEST_LENGTH 32 -#define WOLFSSL_CMAC 1 #include diff --git a/sad_wolfcrypt.c b/sad_wolfcrypt.c index 2e710072..88570976 100644 --- a/sad_wolfcrypt.c +++ b/sad_wolfcrypt.c @@ -1,11 +1,11 @@ + /** * @file sad_nettle.c * @brief Security Association Database nettle functions * @note Copyright (C) 2024 IBM Corporation, Clay Kaiser * @note SPDX-License-Identifier: GPL-2.0+ */ -#define WOLFSSL_CMAC 1 - +#include #include #include #include @@ -16,145 +16,193 @@ #include "sad.h" #include "sad_private.h" +#define MAX_HEX_OUTPUT_LEN 1024 +#define MAX_KEY_LEN 1024 + struct mac_data { - int type; - Hmac *hmac; - Cmac *cmac; + Hmac *hmac; + Cmac *cmac; + int is_cmac; + unsigned char key[MAX_KEY_LEN]; + int key_len; }; -struct mac_data *sad_init_mac(integrity_alg_type algorithm, - const unsigned char *key, size_t key_len) -{ - struct Hmac *mac_algorithm = NULL; - struct Cmac *cmac_algorithm = NULL; - struct mac_data *mac_data; - int ret; - - printf("In sad_init_mac"); +void print_hex_array(const unsigned char *arr, size_t len) { + if (!arr || len == 0 || len * 2 + 1 > MAX_HEX_OUTPUT_LEN) { + pr_err("Invalid input to print_hex_array"); + return; + } - /* verify key length */ - if (key_len == 0) { - pr_err("BUG: key_len is zero"); - return NULL; - } + char output[(len * 2) + 1]; + char *ptr = output; - if (wolfCrypt_Init() != 0) { - pr_err("BUG: wolfCrypt could not initialize"); - return NULL; - } + for (size_t i = 0; i < len; i++) { + ptr += sprintf(ptr, "%02X", arr[i]); + } - mac_data = calloc(1, sizeof(*mac_data)); - if (!mac_data) { - return NULL; - } + *ptr = '\0'; + pr_err("%s", output); +} - /* retrieve mac algorithm */ - switch (algorithm) { - case HMAC_SHA256_128: - case HMAC_SHA256: - mac_algorithm = calloc(1, sizeof(Hmac)); - if (!mac_algorithm) - return NULL; - - mac_data->hmac = mac_algorithm; - mac_data->type = HMAC_SHA256; - wc_HmacSetKey(mac_algorithm, SHA256, key, key_len); - break; +struct mac_data *sad_init_mac(integrity_alg_type algorithm, + const unsigned char *key, size_t key_len) +{ + if (!key || key_len == 0 || key_len > MAX_KEY_LEN) { + pr_err("Invalid key or key length"); + return NULL; + } + + if (wolfCrypt_Init() != 0) { + pr_err("wolfCrypt initialization failed"); + return NULL; + } + + struct mac_data *mac_data = calloc(1, sizeof(*mac_data)); + if (!mac_data) { + pr_err("Memory allocation for mac_data failed"); + wolfCrypt_Cleanup(); + return NULL; + } + + switch (algorithm) { + case HMAC_SHA256_128: + case HMAC_SHA256: + mac_data->hmac = calloc(1, sizeof(Hmac)); + if (!mac_data->hmac) { + pr_err("Memory allocation for HMAC failed"); + free(mac_data); + wolfCrypt_Cleanup(); + return NULL; + } + if (wc_HmacSetKey(mac_data->hmac, SHA256, key, (word32)key_len) != 0) { + pr_err("Failed to set HMAC key"); + sad_deinit_mac(mac_data); + return NULL; + } + mac_data->is_cmac = 0; + break; case CMAC_AES128: - case CMAC_AES256: - cmac_algorithm = calloc(1, sizeof(Cmac)); - if (!cmac_algorithm) - return NULL; - - mac_data->cmac = cmac_algorithm; - mac_data->type = algorithm; - if (algorithm == CMAC_AES128 && key_len != 16) { - pr_err("CMAC_AES128 requires a 128-bit key"); - return NULL; - } else if (algorithm == CMAC_AES256 && key_len != 32) { - pr_err("CMAC_AES256 requires a 256-bit key"); - return NULL; - } - - ret = wc_InitCmac(cmac_algorithm, key, key_len, WC_CMAC_AES, NULL); - if (ret) - return NULL; - - break; - default: - pr_err("BUG: unknown algorithm"); - return NULL; - } - - return mac_data; + case CMAC_AES256: + mac_data->cmac = calloc(1, sizeof(Cmac)); + if (!mac_data->cmac) { + pr_err("Memory allocation for CMAC failed"); + free(mac_data); + wolfCrypt_Cleanup(); + return NULL; + } + if (wc_InitCmac(mac_data->cmac, key, key_len, 1, NULL) != 0) { + pr_err("Failed to set CMAC key"); + sad_deinit_mac(mac_data); + return NULL; + } + + if (key_len <= MAX_KEY_LEN) { + memcpy(mac_data->key, key, key_len); + } else { + return NULL; + } + mac_data->is_cmac = 1; + mac_data->key_len = key_len; + break; + + default: + pr_err("Unknown integrity algorithm"); + sad_deinit_mac(mac_data); + return NULL; + } + + return mac_data; } void sad_deinit_mac(struct mac_data *mac_data) { - printf("In sad_deinit_mac"); - - if (mac_data->hmac) - free(mac_data->hmac); - if (mac_data->cmac) - free(mac_data->cmac); - free(mac_data); - wolfCrypt_Cleanup(); + if (!mac_data) + return; + + if (mac_data->hmac) { + free(mac_data->hmac); + mac_data->hmac = NULL; + } + + if (mac_data->cmac) { + free(mac_data->cmac); + mac_data->cmac = NULL; + } + + free(mac_data); + wolfCrypt_Cleanup(); } int sad_hash(struct mac_data *mac_data, - const void *data, size_t data_len, - unsigned char *mac, size_t mac_len) + const void *data, size_t data_len, + unsigned char *mac, size_t mac_len) { - printf("In sad_hash"); - if (mac_data->type == SHA256) { - /* confirm mac length is within library support */ - if (mac_len > SHA256_DIGEST_SIZE) { - pr_err("BUG: mac_len larger than library support"); - return 0; - } - - /* confirm mac length is within buffer size */ - if (mac_len > MAX_DIGEST_LENGTH) { - pr_err("BUG: mac_len larger than buffer"); - return 0; - } - - wc_HmacUpdate(mac_data->hmac, data, data_len); - wc_HmacFinal(mac_data->hmac, mac); - - return mac_len; - } else { - wc_CmacUpdate(mac_data->cmac, data, data_len); - wc_CmacFinal(mac_data->cmac, mac, &mac_len); - - return mac_len; + if (!mac_data || !data || !mac || data_len == 0 || mac_len == 0) { + pr_err("Invalid input to sad_hash"); + return 0; + } + + if (mac_data->is_cmac) { + if (mac_len > AES_BLOCK_SIZE || mac_len > MAX_DIGEST_LENGTH) { + pr_err("mac_len exceeds CMAC size"); + return 0; + } + + int ret = 0; + if ( (ret = wc_CmacUpdate(mac_data->cmac, data, (word32)data_len)) != 0) { + + pr_err("CMAC update failed with code 0x%08X", ret); + return 0; + } + + if (wc_CmacFinal(mac_data->cmac, mac, &mac_len) != 0) { + pr_err("CMAC finalization failed"); + return 0; + } + + if (wc_InitCmac(mac_data->cmac, mac_data->key, mac_data->key_len, WC_CMAC_AES, NULL) != 0) { + pr_err("CMAC initialization failed"); + return 0; } + + return mac_len; + } else { + const size_t digest_len = SHA256_DIGEST_SIZE; + if (mac_len > digest_len || mac_len > MAX_DIGEST_LENGTH) { + pr_err("mac_len exceeds HMAC size"); + return 0; + } + + if (wc_HmacUpdate(mac_data->hmac, data, (word32)data_len) != 0) { + pr_err("HMAC update failed"); + return 0; + } + + if (wc_HmacFinal(mac_data->hmac, mac) != 0) { + pr_err("HMAC finalization failed"); + return 0; + } + + return mac_len; + } } int sad_verify(struct mac_data *mac_data, - const void *data, size_t data_len, - unsigned char *mac, size_t mac_len) + const void *data, size_t data_len, + unsigned char *mac, size_t mac_len) { - unsigned char digest_buf[MAX_DIGEST_LENGTH]; - unsigned char cmac_buf[16]; - - printf("In sad_verify"); - - if (mac_data->type == SHA256) { - /* update data and retrieve mac */ - if (!sad_hash(mac_data, data, data_len, digest_buf, mac_len)) { - return -1; - } - - /* compare calculated with received */ - return (XMEMCMP(digest_buf, mac, mac_len) == 0); - } else { - /* update data and retrieve mac */ - if (!sad_hash(mac_data, data, data_len, cmac_buf, mac_len)) { - return -1; - } - - /* compare calculated with received */ - return (XMEMCMP(cmac_buf, mac, mac_len) == 0); - } + unsigned char digest_buf[MAX_DIGEST_LENGTH]; + + if (!mac || mac_len == 0) { + pr_err("Invalid MAC input to sad_verify"); + return -1; + } + + if (!sad_hash(mac_data, data, data_len, digest_buf, mac_len)) { + pr_err("Failed to compute hash for verification"); + return -1; + } + + return XMEMCMP(digest_buf, mac, mac_len); } + From 2aa37bf6f04a5091cf8354ebeefe8ebe857a7bbf Mon Sep 17 00:00:00 2001 From: Alex Gebhard Date: Wed, 27 Aug 2025 10:31:51 -0500 Subject: [PATCH 4/4] Update sad_wolfcrypt.c --- sad_wolfcrypt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sad_wolfcrypt.c b/sad_wolfcrypt.c index 88570976..e21af25f 100644 --- a/sad_wolfcrypt.c +++ b/sad_wolfcrypt.c @@ -1,8 +1,8 @@ /** - * @file sad_nettle.c - * @brief Security Association Database nettle functions - * @note Copyright (C) 2024 IBM Corporation, Clay Kaiser + * @file sad_wolfcrypt.c + * @brief Security Association Database wolfcrypt functions + * @note Copyright (C) 2025 Alex Gebhard * @note SPDX-License-Identifier: GPL-2.0+ */ #include