diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 7d2ebd61c..d37824595 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -21,6 +21,12 @@ #ifndef CRYPTO_H #define CRYPTO_H +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len); + /** * md4_vector - MD4 hash for data vector * @num_elem: Number of elements in the data vector diff --git a/src/crypto/crypto_gnutls.c b/src/crypto/crypto_gnutls.c index 4ef11462b..aad265594 100644 --- a/src/crypto/crypto_gnutls.c +++ b/src/crypto/crypto_gnutls.c @@ -17,6 +17,19 @@ #include "sha512.h" #include "crypto.h" +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST validation not implemented for gnutls"); + if (crypto_name) + snprintf(crypto_name, name_len, "gnutls"); + return -1; +} + static int gnutls_digest_vector(int algo, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { diff --git a/src/crypto/crypto_internal.c b/src/crypto/crypto_internal.c index aad40af16..8c268b2f8 100644 --- a/src/crypto/crypto_internal.c +++ b/src/crypto/crypto_internal.c @@ -35,6 +35,18 @@ struct crypto_hash { size_t key_len; }; +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST not implemented by internal crypto"); + if (crypto_name) + snprintf(crypto_name, name_len, "internal"); + return -1; +} struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) diff --git a/src/crypto/crypto_libtomcrypt.c b/src/crypto/crypto_libtomcrypt.c index ed30efa02..76b354e23 100644 --- a/src/crypto/crypto_libtomcrypt.c +++ b/src/crypto/crypto_libtomcrypt.c @@ -22,6 +22,19 @@ #endif +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST validation not implemented for tomcrypt"); + if (crypto_name) + snprintf(crypto_name, name_len, "tomcrypt"); + return -1; +} + int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; diff --git a/src/crypto/crypto_linux.c b/src/crypto/crypto_linux.c index 17244561b..9d4fd9641 100644 --- a/src/crypto/crypto_linux.c +++ b/src/crypto/crypto_linux.c @@ -23,6 +23,19 @@ #endif /* SOL_ALG */ +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST validation not implemented for linux"); + if (crypto_name) + snprintf(crypto_name, name_len, "linux"); + return -1; +} + static int linux_af_alg_socket(const char *type, const char *name) { struct sockaddr_alg sa; diff --git a/src/crypto/crypto_nettle.c b/src/crypto/crypto_nettle.c index f85d36532..5fe85f576 100644 --- a/src/crypto/crypto_nettle.c +++ b/src/crypto/crypto_nettle.c @@ -26,6 +26,19 @@ #include "crypto.h" +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST validation not implemented for nettle"); + if (crypto_name) + snprintf(crypto_name, name_len, "nettle"); + return -1; +} + int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { struct des_ctx ctx; diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index b644b6ca7..5e1d06c31 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -90,6 +90,32 @@ static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) #endif /* OpenSSL version < 1.1.0 */ +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + int status=-1; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /** Check if the OpenSSL self-tests have passed, by fetching an algorithm with + * fips=yes. This will fail if either no FIPS provider is available or + * self-tests on provider load didn't pass. + */ + EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC", "fips=yes"); + if (cipher) { + status = 0; + EVP_CIPHER_free(cipher); + } +#else /* OpenSSL version >= 3.0 */ + wpa_printf(MSG_ERROR, "OpenSSL version < 3.0 not supported"); +#endif /* OpenSSL version >= 3.0 */ + if (crypto_name) + snprintf(crypto_name, name_len, "openssl"); + return status; +} + static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index 2e4bf8962..8ca354432 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -28,6 +28,18 @@ #include #include +/** + * is_fips_ready - Check FIPS POST status. + * Returns: 0 on success, -1 on failure. + */ +int is_fips_ready(char *crypto_name, const size_t name_len) +{ + /* Not supported */ + wpa_printf(MSG_ERROR, "POST validation not implemented for wolfSSL"); + if (crypto_name) + snprintf(crypto_name, name_len, "wolfssl"); + return -1; +} #ifndef CONFIG_FIPS diff --git a/wpa_supplicant/README b/wpa_supplicant/README index 391912e9b..bc124a230 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -422,6 +422,7 @@ options: -d = increase debugging verbosity (-dd even more) -D = driver name (can be multiple drivers: nl80211,wext) -f = Log output to default log location (normally /tmp) + -F = show FIPS POST status -g = global ctrl_interface -G = global ctrl_interface group -K = include keys (passwords, etc.) in debug output @@ -500,6 +501,17 @@ main interface: wpa_supplicant -cw.conf -Dnl80211 -iwlan0 -bbr0 +FIPS POST(Pre-Operational Self-Tests) Validation Support (SONiC Extension) +-------------------------------------------------------------------------- + +The POST status verification is crucial to ensure that the cryptographic +backend is properly configured and has passed the Self-Tests, when operating +in FIPS mode. + +wpa_supplicant -F + +Output: FIPS POST status: pass/fail(crypto backend: ) + Configuration file ------------------ diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c index 51a8a0298..009826234 100644 --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c @@ -16,7 +16,7 @@ #include "wpa_supplicant_i.h" #include "driver_i.h" #include "p2p_supplicant.h" - +#include "crypto/crypto.h" static void usage(void) { @@ -71,6 +71,7 @@ static void usage(void) #ifdef CONFIG_DEBUG_FILE " -f = log output to debug file instead of stdout\n" #endif /* CONFIG_DEBUG_FILE */ + " -F = show FIPS POST status\n" " -g = global ctrl_interface\n" " -G = global ctrl_interface group\n" " -h = show this help text\n" @@ -201,7 +202,7 @@ int main(int argc, char *argv[]) for (;;) { c = getopt(argc, argv, - "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); + "b:Bc:C:D:de:Ff:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); if (c < 0) break; switch (c) { @@ -331,6 +332,13 @@ int main(int argc, char *argv[]) iface = &ifaces[iface_count - 1]; os_memset(iface, 0, sizeof(*iface)); break; + case 'F': + char crypto_name[64]={0}; + int status = is_fips_ready(crypto_name, sizeof(crypto_name)); + printf("FIPS POST status: %s (crypto backend: %s)\n", + status==0 ? "pass":"fail", crypto_name); + exitcode = 0; + goto out; default: usage(); exitcode = 0;