/* ipmacsec_debug.c - MACsec Debug implementation */ /* * Copyright (c) 2010 Wind River Systems, Inc. * * The right to copy, distribute, modify, or otherwise make use * of this software may be licensed only pursuant to the terms * of an applicable Wind River license agreement. * */ /* modification history -------------------- 01a,04Mar10,mry Created */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* * Implements the MACsec debug functionality (mostly used for debugging and * unit/dev testing, and is typically not part of a production system). * NOTE that all code protected by #ifdef IPMACSEC_UNIT_TEST is non supported * code and not guaranteed to work as advertised. */ /* **************************************************************************** * 2 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include "ipmacsec_debug.h" #include "ipmacsec_sysvar.h" #include "ipmacsec_secy_mgmt.h" #include "ipmacsec_h.h" #include "ipmacsec.h" #include "ipmacsec_netlink.h" #include "ipmacsec_lmi.h" /* **************************************************************************** * 3 CONFIGURATION **************************************************************************** */ #include "ipmacsec_config.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #ifdef IPMACSEC_UNIT_TEST /* Sysvars used in Unit Testing profiles */ #define IPMACSEC_UT_SYSVAR_SCI "ipmacsec.ut.secy.sci" #define IPMACSEC_UT_SYSVAR_RX_SCI_1 "ipmacsec.ut.secy.rx.sci.1" #endif /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* * **************************************************************************** * 8 DATA **************************************************************************** */ #ifdef IPMACSEC_UNIT_TEST /* Unit Test Keying material (Note that since this is only used for unit testing, keying material secrecy is not crucial ) * WARNING: DO NOT USE THE FOLLOWING KEYING MATERIAL AS PART OF A PRODUCTION SYSTEM. This will greatly diminish the security * of the system. */ IP_STATIC Ip_u8 ipmacsec_ut_128b_keymaterial_1[16] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; IP_STATIC Ip_u8 ipmacsec_ut_128b_keymaterial_2[16] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F }; IP_STATIC Ip_u8 ipmacsec_ut_128b_keymaterial_3[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; IP_STATIC Ip_u8 ipmacsec_ut_128b_keymaterial_4[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F }; /* Unit Test SAK profiles */ IP_STATIC Ipmacsec_sak_profile ipmacsec_ut_sak_128b_key_1 = { 0x0000000100008001ULL, 128/8, ipmacsec_ut_128b_keymaterial_1 }; IP_STATIC Ipmacsec_sak_profile ipmacsec_ut_sak_128b_key_2 = { 0x0000000100008002ULL, 128/8, ipmacsec_ut_128b_keymaterial_2 }; IP_STATIC Ipmacsec_sak_profile ipmacsec_ut_sak_128b_key_3 = { 0x0000000100008003ULL, 128/8, ipmacsec_ut_128b_keymaterial_3 }; IP_STATIC Ipmacsec_sak_profile ipmacsec_ut_sak_128b_key_4 = { 0x0000000100008004ULL, 128/8, ipmacsec_ut_128b_keymaterial_4 }; /* Unit Test Profile #1: Use on Station A */ Ipmacsec_secy_profile ipmacsec_ut_profile_1A = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_OFF /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* Unit Test Profile #1: Use on Station B */ Ipmacsec_secy_profile ipmacsec_ut_profile_1B = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* Unit Test Profile #2: Use on Station A to test PN exhaustion */ Ipmacsec_secy_profile ipmacsec_ut_profile_2A = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0xfffffff0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_OFF /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* Unit Test Profile #2: Use on Station B. Can be used to test Replay Windows with profile 1 or exhaustion with profile 2 */ Ipmacsec_secy_profile ipmacsec_ut_profile_2B = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_TRUE, /*replayProtect*/ 2, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 7, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 5, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* Unit Test Profile #3: Use on Station A */ Ipmacsec_secy_profile ipmacsec_ut_profile_3A = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_CHECK, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_OFF /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* Unit Test Profile #3: Use on Station B */ Ipmacsec_secy_profile ipmacsec_ut_profile_3B = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_GCM_AES_128, /*cipher_suite_index*/ IP_FALSE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_DISABLED, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_OFF, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; #ifdef IPMACSEC_CRYPTO_ALLOW_NULL_CIPHER /* NULL Cipher Unit Test Profile #1: Use on Station A */ Ipmacsec_secy_profile ipmacsec_ut_profile_null_ciph_1A = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_NULL_CIPHER_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_OFF /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; /* NULL Cipher Unit Test Profile #1: Use on Station A */ Ipmacsec_secy_profile ipmacsec_ut_profile_null_ciph_1B = { IPMACSEC_UT_SYSVAR_SCI, /*sci_sysvar*/ IPMACSEC_CIPHERSUITE_NULL_CIPHER_128, /*cipher_suite_index*/ IP_TRUE, /*protectFrames*/ IP_TRUE, /*alwaysIncludeSCI*/ IP_TRUE, /*useES*/ IP_FALSE, /*useSCB*/ IPMACSEC_SECY_VALIDATEFRAMES_STRICT, /*validateFrames*/ IP_FALSE, /*replayProtect*/ 0, /*replayWindow*/ 0, /*confidentialityOffset*/ 0, /*pn_threshold*/ IP_TRUE, /*info_notify*/ { IP_TRUE, /*ControlledPortEnabled*/ IP_PORTIF_ADMIN_PTP_MAC_FORCE_AUTO /*adminPointToPointMAC*/ }, /*cp_profile*/ { IP_TRUE, /*create*/ IP_NULL, /*sci_sysvar*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00010001, /*ref*/ &ipmacsec_ut_sak_128b_key_3, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_ON, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00010002, /*ref*/ &ipmacsec_ut_sak_128b_key_4, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_OFF, /*enableTx*/ IPMACSEC_ENABLEFLAG_IGNORE /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } }, /*tx_sc_profile*/ { { IP_TRUE, /*create*/ IPMACSEC_UT_SYSVAR_RX_SCI_1, /*sci*/ { { IP_TRUE, /*create*/ 0, /*an*/ 0x00020001, /*ref*/ &ipmacsec_ut_sak_128b_key_1, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ }, /*Ipmacsec_sa_profile[0]*/ { IP_TRUE, /*create*/ 1, /*an*/ 0x00020002, /*ref*/ &ipmacsec_ut_sak_128b_key_2, /*sak_profile*/ 0, /*nextPN*/ IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, /*confidentiality*/ 0, /*lowestPN*/ IPMACSEC_ENABLEFLAG_IGNORE, /*enableTx*/ IPMACSEC_ENABLEFLAG_ON /*enableRx*/ } /*Ipmacsec_sa_profile[1]*/ } } /*rx_sc_profile[0]*/ } }; #endif #endif /* **************************************************************************** * 9 FUNCTIONS **************************************************************************** */ #ifdef IPMACSEC_UNIT_TEST #ifdef IPMACSEC_UNIT_TEST_INLINE_HARDCODED_CONFIG Ip_bool ipmacsec_dummy_key_change = IP_FALSE; /* *=========================================================================== * ipmacsec_secy_unittest_create_dummy_key *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ipmacsec_secy_key * ipmacsec_secy_unittest_create_dummy_key(Ipnet_secy *secy) { Ip_u32 i; Ipmacsec_secy_sak dummy_sak; IP_STATIC Ip_u64 id = 0; Ipmacsec_secy_key_id key_id; dummy_sak.num_octets = 128/8; dummy_sak.buf = ipcom_malloc(dummy_sak.num_octets); if (!dummy_sak.buf) { return IP_NULL; } for (i=0; i < dummy_sak.num_octets; i++) ipcom_memset(dummy_sak.buf, 0xae^(1<config.maxTxKeys; an++) { Ipmacsec_secy_sa *sa; Ipmacsec_secy_key *dummy_key; dummy_key = ipmacsec_secy_unittest_create_dummy_key(secy); if (!dummy_key) { return -1; } if (ipmacsec_secy_install_key(secy, dummy_key, IPMACSEC_KEYTYPE_TRANSMIT | IPMACSEC_KEYTYPE_RECEIVE) != 0) { return -1; } sa = ipmacsec_secy_create_tx_sa(secy, an, (an+1)<<8, 1, IPMACSEC_CONFIDENTIALITY_UNSPECIFIED, dummy_key); if (sa == IP_NULL) { return -1; } if (ipmacsec_secy_enable_tx_sa(secy, sa, IP_TRUE) != 0) { return -1; } } IPCOM_LOG1(INFO, "IPMACSEC-UTEST: Successfully created SecY Tx SAs for interface %s", secy->netif->ipcom.name); ipcom_memset(dummy_sci, 0xAE, IPMACSEC_SCI_LEN); sc = ipmacsec_secy_create_rx_sc(secy, dummy_sci); if (!sc) { return -1; } IPCOM_LOG1(INFO, "IPMACSEC-UTEST: Successfully created SecY Rx SC for interface %s", secy->netif->ipcom.name); for (an=0; an < secy->config.maxRxKeys; an++) { Ipmacsec_secy_sa *sa; Ipmacsec_secy_key *dummy_key; dummy_key = ipmacsec_secy_unittest_create_dummy_key(secy); if (!dummy_key) { return -1; } if (ipmacsec_secy_install_key(secy, dummy_key, IPMACSEC_KEYTYPE_TRANSMIT | IPMACSEC_KEYTYPE_RECEIVE) != 0) { return -1; } sa = ipmacsec_secy_create_rx_sa(secy, sc, an, (an+1)<<16, 1, 0, dummy_key); if (sa == IP_NULL) { return -1; } if (ipmacsec_secy_enable_rx_sa(secy, sa, IP_TRUE) != 0) { return -1; } } IPCOM_LOG1(INFO, "IPMACSEC-UTEST: Successfully created SecY Rx SAs for interface %s", secy->netif->ipcom.name); return 0; } /* *=========================================================================== * ipmacsec_secy_unittest_delete_all *=========================================================================== * Description: * Parameters: * Returns: * */ IPMACSEC_PRIVATE int ipmacsec_secy_unittest_delete_all(Ipnet_secy *secy) { Ipmacsec_secy_sc *sc; Ip_u8 dummy_sci[IPMACSEC_SCI_LEN]; sc = ipmacsec_secy_lookup_rx_sc(secy, dummy_sci); if (!sc) { return -1; } if (ipmacsec_secy_delete_rx_sc(secy, sc) != 0) { return -1; } return 0; } /* *=========================================================================== * ipmacsec_secy_unittest_setup *=========================================================================== * Description: * Parameters: * Returns: * */ IPMACSEC_PRIVATE int ipmacsec_secy_unittest_setup(Ipnet_secy *secy) { if (ipmacsec_secy_unittest_create_all(secy) != 0) { IPCOM_LOG1(ERR, "IPMACSEC-UTEST: Failed to create Tx SAs for interface %s", secy->netif->ipcom.name); return -1; } return 0; } /* *=========================================================================== * ipmacsec_secy_unittest_destroy *=========================================================================== * Description: * Parameters: * Returns: * */ IPMACSEC_PRIVATE int ipmacsec_secy_unittest_destroy(Ipnet_secy *secy) { (void)ipmacsec_secy_unittest_delete_all(secy); return 0; } #endif /* IPMACSEC_UNIT_TEST_INLINE_HARDCODED_CONFIG */ IP_STATIC Ip_bool ipmacsec_netlink_monitor_test_exit = IP_FALSE; /* *=========================================================================== * ipmacsec_netlink_monitor_test_callback *=========================================================================== * Description: SecY Monitor test callback routine * Parameters: * Returns: * */ IP_STATIC int ipmacsec_netlink_monitor_test_callback(struct Ip_nlmsghdr *nlmsg, int error) { IPCOM_LOG1(DEBUG2, "IPMACSEC-NLMON_TEST: callback invoked with error = %d", error); if (nlmsg) { IPCOM_LOG3(DEBUG2,"IPMACSEC-NLMON_TEST: callback received nlmsg->nlmsg_type=%d (%s), nlmsg->nlmsg_len=%u", nlmsg->nlmsg_type, ipmacsec_netlink_type_name(nlmsg->nlmsg_type), nlmsg->nlmsg_len); } if (ipmacsec_netlink_monitor_test_exit) { /* User indicated exit condition */ ipmacsec_netlink_monitor_test_exit = IP_FALSE; return -1; } return 0; } /* *=========================================================================== * ipmacsec_netlink_monitor_test *=========================================================================== * Description: Start a netlink monitor to capture all notifications * Runs in the caller context * Parameters: timeout- timeout value in seconds * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_netlink_monitor_test(Ip_u32 timeout) { Ipmacsec_netlink_handle *nlhandle; struct Ip_timeval tv; Ip_u32 groups; int ret = -1; tv.tv_sec = timeout; tv.tv_usec = 0; groups = IP_NLMSG_GROUP_MASK(IPMACSEC_NLGRP_NOTIFY) | IP_NLMSG_GROUP_MASK(IPMACSEC_NLGRP_MONITOR); nlhandle = ipmacsec_netlink_open(groups); if (!nlhandle) { IPCOM_LOG0(ERR, "IPMACSEC-NLMON_TEST: ipmacsec_netlink_open() returned NULL handle"); goto error_out; } IPCOM_LOG1(DEBUG2, "IPMACSEC-NLMON_TEST: nlhandle = 0x%x", nlhandle); /* Register */ ret = ipmacsec_netlink_register(nlhandle, ipmacsec_netlink_monitor_test_callback, &tv, IP_TRUE); if (ret < 0) { IPCOM_LOG1(ERR, "IPMACSEC-NLMON_TEST: ipmacsec_netlink_register() returned %d", ret); goto error_out; } /* Invoke the netlink loop */ ret = ipmacsec_netlink_loop(nlhandle); IPCOM_LOG0(INFO, "IPMACSEC-NLMON_TEST: ipmacsec_netlink_loop() terminated"); error_out: ipmacsec_netlink_close(nlhandle); IPCOM_LOG1(INFO, "IPMACSEC-NLMON_TEST: Exiting with ret = %d", ret); return ret; } /* *=========================================================================== * ipmacsec_secy_mon_testd *=========================================================================== * Description: MACsec SecY Uncontrolled Port reception test daemon * Parameters: * Returns: * */ IP_STATIC IPCOM_PROCESS(ipmacsec_secy_mon_testd) { char ifname[IP_IFNAMSIZ]; Ip_size_t len; int ret; Ip_u32 timeout; char *sysvar; char strval[16]; Ip_u32 pid; IPCOM_LOG0(DEBUG2, "ipmacsec_secy_mon_testd :: Started"); ipcom_proc_init(); sysvar = "ipmacsec.secy.ut.montestd.ifname"; len = IP_IFNAMSIZ; if (ipcom_sysvar_get(sysvar, ifname, &len) == IP_NULL) { IPCOM_LOG1(WARNING, "ipmacsec_secy_mon_testd :: Failed to get sysvar %s", sysvar); goto exit; } sysvar = "ipmacsec.secy.ut.montestd.timeout"; len = sizeof(strval); if (ipcom_sysvar_get(sysvar, strval, &len) == IP_NULL) { IPCOM_LOG1(WARNING, "ipmacsec_secy_ucp_testd :: Failed to get sysvar %s", sysvar); goto exit; } timeout = ipcom_atoi(strval); ret = ipmacsec_lmi_monitor_start(timeout, IP_TRUE, &pid, IP_NULL, 0); exit: IPCOM_LOG1(DEBUG2, "ipmacsec_secy_mon_testd :: Exiting (ret = %d)", ret); ipcom_proc_exit(); } /* *=========================================================================== * ipmacsec_secy_monitor_test_start_daemon *=========================================================================== * Description: Start a MACsec SecY Monitor test daemon * Should only start one daemon at a time. * Parameters: ifname - Interface bame * num_expected_pkts - # of packets to expect before existing (0 ==> loop forever or until timeout) * timeout - # of seconds before timing out (in seconds) (0 ==> no timeout) * Returns: 0 upon successfully starting the daemon, <0 on error * */ IP_GLOBAL int ipmacsec_secy_monitor_test_start_daemon(char *ifname, Ip_u32 timeout) { Ipcom_proc_attr proc_attr; char *sysvar; char strval[16]; Ip_err rc; sysvar = "ipmacsec.secy.ut.montestd.ifname"; if ((rc = ipcom_sysvar_set(sysvar, ifname, IPCOM_SYSVAR_FLAG_OVERWRITE)) != IPCOM_SUCCESS) { IPCOM_LOG1(CRIT, "ipmacsec_secy_monitor_test_start_daemon :: Failed to set sysvar %s", sysvar); return rc; } ipcom_snprintf(strval, sizeof(strval), "%d", timeout); sysvar = "ipmacsec.secy.ut.montestd.timeout"; if ((rc = ipcom_sysvar_set(sysvar, strval, IPCOM_SYSVAR_FLAG_OVERWRITE)) != IPCOM_SUCCESS) { IPCOM_LOG1(CRIT, "ipmacsec_secy_monitor_test_start_daemon :: Failed to set sysvar %s", sysvar); return rc; } ipcom_proc_attr_init(&proc_attr); proc_attr.stacksize = IPCOM_PROC_STACK_SMALL; rc = ipcom_proc_acreate("secy_mon_testd", ipmacsec_secy_mon_testd, &proc_attr, IP_NULL); return rc; } /* *=========================================================================== * ipmacsec_netlink_test *=========================================================================== * Description: Execute some netlink message tests * Parameters: none * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_netlink_test(void) { Ipmacsec_netlink_handle *nlhandle; struct Ip_nlmsghdr empty_request; struct { struct Ip_nlmsghdr nlh; Ip_u32 command; } request; Ipmacsec_buffer response; int ret = -1; Ip_u32 num_exec_tests = 0, num_failed_tests = 0; nlhandle = ipmacsec_netlink_open(IPMACSEC_NLGRP_NONE); if (!nlhandle) { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: ipmacsec_netlink_open() returned NULL handle"); goto nl_test_done; } /* send an uninitialized request */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLTEST: Executing test #%u", num_exec_tests); ipcom_memset(&empty_request, 0, sizeof(empty_request)); empty_request.nlmsg_len = IP_NLMSG_LENGTH(0); ret = ipmacsec_netlink_request(nlhandle, &empty_request, IP_NULL); if (ret < 0) { IPCOM_LOG0(INFO, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with INVALID request/NULL response failed (expepcted result)"); } else { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with INVALID request/NULL response succeeded (unexpepcted result)"); num_failed_tests++; } /* Just send an empty request */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLTEST: Executing test #%u", num_exec_tests); ipcom_memset(&empty_request, 0, sizeof(empty_request)); empty_request.nlmsg_len = IP_NLMSG_LENGTH(0); empty_request.nlmsg_type = IPMACSEC_NLTYPE_TEST; ret = ipmacsec_netlink_request(nlhandle, &empty_request, IP_NULL); if (ret < 0) { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with EMPTY TEST request/NULL response failed"); num_failed_tests++; } else { IPCOM_LOG0(INFO, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with EMPTY TEST request/NULL response succeeded"); } /* Now send a non empty test request with a NULL response */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLTEST: Executing test #%u", num_exec_tests); ipcom_memset(&request, 0, sizeof(request)); request.nlh.nlmsg_type = IPMACSEC_NLTYPE_TEST; request.nlh.nlmsg_len = IP_NLMSG_LENGTH(sizeof(request.command)); request.command = 0; ret = ipmacsec_netlink_request(nlhandle, &request.nlh, IP_NULL); if (ret < 0) { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with TEST request/NULL response failed"); num_failed_tests++; } else { IPCOM_LOG0(INFO, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with TEST request/NULL response succeeded"); } /* Now send a non empty test request with an expcted response */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLTEST: Executing test #%u", num_exec_tests); IPMACSEC_BUF_INIT(&response); IPMACSEC_BUF_ALLOC(&response, IP_NLMSG_LENGTH(0)); if (!IPMACSEC_BUF_VERIFY(&response)) { IPCOM_LOG0(CRIT, "IPMACSEC-NLTEST: failed to alloc response"); goto nl_test_done; } ipcom_memset(&request, 0, sizeof(request)); request.nlh.nlmsg_type = IPMACSEC_NLTYPE_TEST; request.nlh.nlmsg_len = IP_NLMSG_LENGTH(sizeof(request.command)); request.command = 0; ret = ipmacsec_netlink_request(nlhandle, &request.nlh, &response); if (ret < 0) { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with TEST request/response failed"); num_failed_tests++; goto nl_test_done; } if (!IPMACSEC_BUF_VERIFY(&response)) { IPCOM_LOG0(ERR, "IPMACSEC-NLTEST: invalid response"); num_failed_tests++; goto nl_test_done; } if (response.size < IP_NLMSG_LENGTH(0)) { IPCOM_LOG1(ERR, "IPMACSEC-NLTEST: invalid response size %u", response.size); num_failed_tests++; goto nl_test_done; } if (response.truncated) { IPCOM_LOG0(DEBUG2, "IPMACSEC-NLTEST: response truncated"); } IPCOM_LOG0(INFO, "IPMACSEC-NLTEST: ipmacsec_netlink_request() with TEST request/ response succeeded"); nl_test_done: ipmacsec_netlink_close(nlhandle); if (num_failed_tests) { IPCOM_LOG2(ERR, "IPMACSEC-NLTEST: COMPLETED WITH FAILURES - %u tests executed, %u failed", num_exec_tests, num_failed_tests); ret = -1; } else { IPCOM_LOG1(INFO, "IPMACSEC-NLTEST: COMPLETED SUCCESSFULLY - %u tests executed successfully", num_exec_tests); ret = 0; } return ret; } /* *=========================================================================== * ipmacsec_netlink_multi_test *=========================================================================== * Description: Send a Mutli netlink message requests (without using an lmi handle) * Parameters: ifname - Interface name to send to. Must be attached 1st * otherwise this test will fail. * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_netlink_multi_test(char *ifname) { Ipmacsec_buffer request, response; Ip_bool en = IP_FALSE, doEnable = IP_FALSE; int ret = -1; Ip_u32 num_exec_tests = 0, num_failed_tests = 0; if (!ifname) { IPCOM_LOG0(ERR, "IPMACSEC-NLMULTI_TEST: NULL ifname. Test not executed."); return -1; } /* Init and alloc buffers */ IPMACSEC_BUF_INIT(&request); IPMACSEC_BUF_INIT(&response); if (ipmacsec_nlmsg_alloc(&request) == IP_NULL) { IPCOM_LOG0(CRIT, "IPMACSEC-NLMULTI_TEST: failed to alloc request"); goto err_out; } if (ipmacsec_nlmsg_alloc(&response) == IP_NULL) { IPCOM_LOG0(CRIT, "IPMACSEC-NLMULTI_TEST: failed to alloc response"); goto err_out; } /* 1- Disable and check status */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLMULTI_TEST: Executing test #%u", num_exec_tests); doEnable = IP_FALSE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_2; } ret = ipmacsec_lmi_secy_get_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, IP_NULL, 0); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_get_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_2; } ret = ipmacsec_lmi_cmd_send(IP_NULL, &request, &response); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_send() failed (ret=%d)", ret); num_failed_tests++; goto test_2; } ret = ipmacsec_lmi_cmd_parse_response(&response, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &en, sizeof(en)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_parse_response() failed (ret=%d)", ret); num_failed_tests++; goto test_2; } if (en != doEnable) { IPCOM_LOG2(ERR, "IPMACSEC-NLMULTI_TEST: mismatched results (en=%u, doEnable=%u)", en, doEnable); num_failed_tests++; goto test_2; } test_2: /* 2- Enable and check status */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLMULTI_TEST: Executing test #%u", num_exec_tests); IPMACSEC_BUF_WIPE(&request); IPMACSEC_BUF_WIPE(&response); doEnable = IP_TRUE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_3; } ret = ipmacsec_lmi_secy_get_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, IP_NULL, 0); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_get_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_3; } ret = ipmacsec_lmi_cmd_send(IP_NULL, &request, &response); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_send() failed (ret=%d)", ret); num_failed_tests++; goto test_3; } ret = ipmacsec_lmi_cmd_parse_response(&response, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &en, sizeof(en)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_parse_response() failed (ret=%d)", ret); num_failed_tests++; goto test_3; } if (en != doEnable) { IPCOM_LOG2(ERR, "IPMACSEC-NLMULTI_TEST: mismatched results (en=%u, doEnable=%u)", en, doEnable); num_failed_tests++; goto test_3; } test_3: /* 3- Disable/Enable and check status */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLMULTI_TEST: Executing test #%u", num_exec_tests); IPMACSEC_BUF_WIPE(&request); IPMACSEC_BUF_WIPE(&response); doEnable = IP_FALSE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_4; } doEnable = IP_TRUE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_4; } ret = ipmacsec_lmi_secy_get_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, IP_NULL, 0); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_get_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_4; } ret = ipmacsec_lmi_cmd_send(IP_NULL, &request, &response); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_send() failed (ret=%d)", ret); num_failed_tests++; goto test_4; } ret = ipmacsec_lmi_cmd_parse_response(&response, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &en, sizeof(en)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_parse_response() failed (ret=%d)", ret); num_failed_tests++; goto test_4; } if (en != doEnable) { IPCOM_LOG2(ERR, "IPMACSEC-NLMULTI_TEST: mismatched results (en=%u, doEnable=%u)", en, doEnable); num_failed_tests++; goto test_4; } test_4: /* 4- Disable/Enable/Disable and check status */ num_exec_tests++; IPCOM_LOG1(INFO, "IPMACSEC-NLMULTI_TEST: Executing test #%u", num_exec_tests); IPMACSEC_BUF_WIPE(&request); IPMACSEC_BUF_WIPE(&response); doEnable = IP_FALSE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } doEnable = IP_TRUE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } doEnable = IP_FALSE; ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &doEnable, sizeof(doEnable)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_set_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } ret = ipmacsec_lmi_secy_get_cmd_append(&request, IP_NULL, ifname, IPMACSEC_LMICMD_SECY_ENABLED, IP_NULL, 0); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_secy_get_cmd_append() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } ret = ipmacsec_lmi_cmd_send(IP_NULL, &request, &response); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_send() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } ret = ipmacsec_lmi_cmd_parse_response(&response, ifname, IPMACSEC_LMICMD_SECY_ENABLED, &en, sizeof(en)); if (ret != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-NLMULTI_TEST: ipmacsec_lmi_cmd_parse_response() failed (ret=%d)", ret); num_failed_tests++; goto test_5; } if (en != doEnable) { IPCOM_LOG2(ERR, "IPMACSEC-NLMULTI_TEST: mismatched results (en=%u, doEnable=%u)", en, doEnable); num_failed_tests++; goto test_5; } test_5: err_out: ipmacsec_nlmsg_free(&request); ipmacsec_nlmsg_free(&response); if (num_failed_tests) { IPCOM_LOG2(ERR, "IPMACSEC-NLMULTI_TEST: COMPLETED WITH FAILURES - %u tests executed, %u failed", num_exec_tests, num_failed_tests); ret = -1; } else { IPCOM_LOG1(INFO, "IPMACSEC-NLMULTI_TEST: COMPLETED SUCCESSFULLY - %u tests executed successfully", num_exec_tests); ret = 0; } return ret; } /* *=========================================================================== * ipmacsec_key_test *=========================================================================== * Description: Test the key install/remove operations. * Parameters: ifname - Interface name to send to. Must be attached 1st * otherwise this test will fail. * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_key_test(char *ifname) { Ipmacsec_secy_key_descriptor key_desc; IPMACSEC_LMI_HANDLE lh = IP_NULL; Ipmacsec_lmi_error ret = IPMACSEC_LMIERR_UNSPECIFIED_ERROR; Ip_u32 i=0, num_exec_tests = 0, num_failed_tests = 0; Ip_u64 key_id = 0xdeadbeef; Ip_u8 dummy_key[16]; Ipmacsec_buffer key_info; if (!ifname) { IPCOM_LOG0(ERR, "IPMACSEC-KEY_TEST: NULL ifname. Test not executed."); return -1; } lh = ipmacsec_lmi_handle_create(); if (!lh) { IPCOM_LOG0(ERR, "IPMACSEC-KEY_TEST: Failed to create lmi handle. Test not executed."); return -1; } /* Allocate enough buffer space for key descriptors */ IPMACSEC_BUF_INIT(&key_info); if (ipmacsec_buf_alloc(&key_info, sizeof(Ipmacsec_secy_key_descriptor)*IPMACSEC_SECY_KEYDB_SIZE) == IP_NULL) { IPCOM_LOG0(CRIT, "IPMACSEC-KEY_TEST: failed to alloc key_info buffer"); goto err_out; } /* 1- Install a Key (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG4(ERR, "IPMACSEC-KEY_TEST: Failed to install key with key_id 0x%llx, keysize %u. (ret=%d, %s).", key_desc.key_id.val, key_desc.key_size, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } else { IPCOM_LOG2(INFO, "IPMACSEC-KEY_TEST: Successfully installed key with key_id 0x%llx, keysize %u.", key_desc.key_id.val, sizeof(dummy_key)); } /* 2- Retrieve key info (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; IPMACSEC_BUF_WIPE(&key_info); ret = ipmacsec_lmi_secy_get_key_info(lh, ifname, &key_desc, &key_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-KEY_TEST: Failed to retrieve key info for key_id 0x%llx (ret=%d, %s).", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } else { Ipmacsec_secy_key_descriptor *kdesc = (Ipmacsec_secy_key_descriptor *)IPMACSEC_BUF_HEAD(&key_info); if (key_info.size < sizeof(Ipmacsec_secy_key_descriptor)) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-KEY_TEST: Invalid key descriptor for key_id 0x%llx (size = %u < %u).", key_desc.key_id.val, key_info.size, sizeof(Ipmacsec_secy_key_descriptor)); } else if (kdesc->key_id.val != key_desc.key_id.val) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: Invalid key descriptor key_id (0x%llx != 0x%llx).", kdesc->key_id.val, key_desc.key_id.val); } else { IPMACSEC_TIMEBUF(tbuf); IPMACSEC_STRFTIME(tbuf, kdesc->created_time); IPCOM_LOG6(INFO, "IPMACSEC-KEY_TEST: Successfully retrieved info for key: key_id 0x%llx, keysize %u, " "transmits %s, receives %s, inUse %s, created_time %s", kdesc->key_id.val, kdesc->key_size, IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_TRANSMIT), IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_RECEIVE), IPMACSEC_BOOL_STRING(kdesc->inUse), tbuf); } } /* 3- Try to Install the same Key again (should fail) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-KEY_TEST: Succeeded in installing key with same key_id 0x%llx. Incorrect result", key_desc.key_id.val); } else { IPCOM_LOG3(INFO, "IPMACSEC-KEY_TEST: Failed to re-install key with same key_id 0x%llx (ret=%d, %s). Expected Result", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } /* 4- Try to remove a key with a different key id (should fail) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = 0; ret = ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc); if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-KEY_TEST: Succeeded in removing key with differet key_id 0x%llx. Incorrect result", key_desc.key_id.val); } else { IPCOM_LOG3(INFO, "IPMACSEC-KEY_TEST: Failed to remove key with differet key_id 0x%llx (ret=%d, %s). Expected Result", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } /* 5- Try to remove the correct key now (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; ret = ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-KEY_TEST: Failed to remove key with same key_id 0x%llx (ret=%d, %s).", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } else { IPCOM_LOG1(INFO, "IPMACSEC-KEY_TEST: Succeeded in removing key with same key_id 0x%llx.", key_desc.key_id.val); } /* 6- Try to retrieve key info (should fail) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; IPMACSEC_BUF_WIPE(&key_info); ret = ipmacsec_lmi_secy_get_key_info(lh, ifname, &key_desc, &key_info); if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-KEY_TEST: Successfully retrieve key info for removed key_id 0x%llx (ret=%d, %s). Incorrect result", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } else { IPCOM_LOG1(INFO, "IPMACSEC-KEY_TEST: Failed to retrieve key info for removed key_id 0x%llx. Expected Result", key_desc.key_id.val); } /* 7- Try to remove the same key again (should fail) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = key_id; ret = ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc); if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-KEY_TEST: Succeeded in removing key with same key_id 0x%llx. Incorrect result", key_desc.key_id.val); } else { IPCOM_LOG3(INFO, "IPMACSEC-KEY_TEST: Failed to remove key with same key_id 0x%llx (ret=%d, %s). Expected result", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); } /* 8- Delete all keys (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ret = ipmacsec_lmi_secy_key_purge(lh, ifname); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-KEY_TEST: Failed to purge keys."); } else { IPCOM_LOG0(INFO, "IPMACSEC-KEY_TEST: Succeeded in purging keys."); } /* 9- Retrieve all key info (should succeed, but return none) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); IPMACSEC_BUF_WIPE(&key_info); ret = ipmacsec_lmi_secy_get_key_info(lh, ifname, IP_NULL, &key_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: Failed to retrieve key info list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); } else { if (key_info.size != 0) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-KEY_TEST: key info returned when there should be none (key_info.size = %u).", key_info.size); for (i = 1; i <= IPMACSEC_SECY_KEYDB_SIZE; i++) { Ip_u32 remlen; Ipmacsec_secy_key_descriptor *kdesc = (Ipmacsec_secy_key_descriptor *) ipmacsec_buf_ptr(&key_info, (i-1)*sizeof(Ipmacsec_secy_key_descriptor), &remlen); if (!kdesc) { IPCOM_LOG0(ERR, "IPMACSEC-KEY_TEST: kdesc NULL!"); } else { IPMACSEC_TIMEBUF(tbuf); IPMACSEC_STRFTIME(tbuf, kdesc->created_time); IPCOM_LOG7(INFO, "IPMACSEC-KEY_TEST: Retrieved info for key #%u: key_id 0x%llx, keysize %u, " "transmits %s, receives %s, inUse %s, created_time %s", i, kdesc->key_id.val, kdesc->key_size, IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_TRANSMIT), IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_RECEIVE), IPMACSEC_BOOL_STRING(kdesc->inUse), tbuf); } } } else { IPCOM_LOG0(INFO, "IPMACSEC-KEY_TEST: No key info retrieved. Expected result"); } } /* 10- Install Max keys (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); for (i = 1; i <= IPMACSEC_SECY_KEYDB_SIZE; i++) { ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = ((Ip_u64)i << 32 | key_id); key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG5(ERR, "IPMACSEC-KEY_TEST: Failed to install key #%u with key_id 0x%llx, keysize %u. (ret=%d, %s).", i, key_desc.key_id.val, key_desc.key_size, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } else { IPCOM_LOG3(INFO, "IPMACSEC-KEY_TEST: Successfully installed key #%u with key_id 0x%llx, keysize %u.", i, key_desc.key_id.val, sizeof(dummy_key)); } } /* 11- Install 1 more key than mac (should fail) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = ((Ip_u64)i << 32 | key_id); key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-KEY_TEST: Successfully installed key #%u with key_id 0x%llx, keysize %u. Incorrect result", i, key_desc.key_id.val, sizeof(dummy_key)); } else { IPCOM_LOG5(INFO, "IPMACSEC-KEY_TEST: Failed to install key #%u with key_id 0x%llx, keysize %u. (ret=%d, %s). Expected result", i, key_desc.key_id.val, key_desc.key_size, ret, ipmacsec_lmi_error_name(ret)); } /* 12- Retreive all key info (should succeed with max # of key info returned) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); IPMACSEC_BUF_WIPE(&key_info); ret = ipmacsec_lmi_secy_get_key_info(lh, ifname, IP_NULL, &key_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: Failed to retrieve key info list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); } else { if (key_info.size != IPMACSEC_SECY_KEYDB_SIZE*sizeof(Ipmacsec_secy_key_descriptor)) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: Incorrect number of key info returned (%u != %u). Incorrect result", key_info.size, IPMACSEC_SECY_KEYDB_SIZE*sizeof(Ipmacsec_secy_key_descriptor)); } else if (key_info.truncated) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: key info buffer truncated (size = %u, alloc_size = %u).", key_info.size, key_info.alloc_size); } else { IPCOM_LOG0(INFO, "IPMACSEC-KEY_TEST: Complete key info retrieved successfully."); for (i = 1; i <= IPMACSEC_SECY_KEYDB_SIZE; i++) { Ip_u32 remlen; Ipmacsec_secy_key_descriptor *kdesc = (Ipmacsec_secy_key_descriptor *) ipmacsec_buf_ptr(&key_info, (i-1)*sizeof(Ipmacsec_secy_key_descriptor), &remlen); if (!kdesc) { IPCOM_LOG0(WARNING, "IPMACSEC-KEY_TEST: kdesc NULL!"); } else { IPMACSEC_TIMEBUF(tbuf); IPMACSEC_STRFTIME(tbuf, kdesc->created_time); IPCOM_LOG7(INFO, "IPMACSEC-KEY_TEST: Successfully retrieved info for key #%u: key_id 0x%llx, keysize %u, " "transmits %s, receives %s, inUse %s, created_time %s", i, kdesc->key_id.val, kdesc->key_size, IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_TRANSMIT), IPMACSEC_BOOL_STRING(kdesc->key_type & IPMACSEC_KEYTYPE_RECEIVE), IPMACSEC_BOOL_STRING(kdesc->inUse), tbuf); } } } } /* 13- Delete all keys (should succeed) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); ret = ipmacsec_lmi_secy_key_purge(lh, ifname); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-KEY_TEST: Failed to purge keys."); } else { IPCOM_LOG0(INFO, "IPMACSEC-KEY_TEST: Succeeded in purging keys."); } /* 14- Retreive all key info (should succeed 0 key info returned) */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-KEY_TEST: Executing test #%u *****", num_exec_tests); IPMACSEC_BUF_WIPE(&key_info); ret = ipmacsec_lmi_secy_get_key_info(lh, ifname, IP_NULL, &key_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: Failed to retrieve key info list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); } else { if (key_info.size != 0) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-KEY_TEST: key info returned when there should be none (key_info.size = %u).", key_info.size); } else { IPCOM_LOG0(INFO, "IPMACSEC-KEY_TEST: No key info retrieved. Expected result"); } } err_out: if (num_failed_tests) { IPCOM_LOG2(ERR, "IPMACSEC-KEY_TEST: COMPLETED WITH FAILURES - %u tests executed, %u failed", num_exec_tests, num_failed_tests); ret = -1; } else { IPCOM_LOG1(INFO, "IPMACSEC-KEY_TEST: COMPLETED SUCCESSFULLY - %u tests executed successfully", num_exec_tests); ret = 0; } (void)ipmacsec_buf_free(&key_info); (void)ipmacsec_lmi_handle_delete(lh); return ret; } /* *=========================================================================== * ipmacsec_ctrl_cmd_test *=========================================================================== * Description: Test the SecY Control Set/Get operations. * Set commands will fail if executed when the Secy is enabled. * Parameters: ifname - Interface name to send to. Must be attached 1st * otherwise this test will fail. * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_ctrl_cmd_test(char *ifname) { Ipmacsec_lmi_command bool_cmds[] = {IPMACSEC_LMICMD_SECY_PROTECT_FRAMES, IPMACSEC_LMICMD_SECY_ALWAYS_INC_SCI, IPMACSEC_LMICMD_SECY_USE_ES, IPMACSEC_LMICMD_SECY_USE_SCB, IPMACSEC_LMICMD_SECY_REPLAY_PROTECT}; Ipmacsec_lmi_command ipu32_cmds[] = {IPMACSEC_LMICMD_SECY_REPLAY_WINDOW}; Ipmacsec_validateFrames_type validateFrames; IPMACSEC_LMI_HANDLE lh = IP_NULL; Ipmacsec_lmi_error ret = IPMACSEC_LMIERR_UNSPECIFIED_ERROR; Ip_u32 i = 0; Ipmacsec_buffer request, response; Ipmacsec_lmi_command cmd; if (!ifname) { IPCOM_LOG0(ERR, "IPMACSEC-CTRL_TEST: NULL ifname. Test not executed."); return -1; } lh = ipmacsec_lmi_handle_create(); if (!lh) { IPCOM_LOG0(ERR, "IPMACSEC-CTRL_TEST: Failed to create lmi handle. Test not executed."); return -1; } IPMACSEC_BUF_INIT(&request); if (ipmacsec_nlmsg_alloc(&request) == IP_NULL) { ret = IPMACSEC_LMIERR_ALLOC_FAILED; goto err_out; } IPMACSEC_BUF_INIT(&response); if (ipmacsec_nlmsg_alloc(&response) == IP_NULL) { ret = IPMACSEC_LMIERR_ALLOC_FAILED; goto err_out; } for (i=0; i < sizeof(bool_cmds)/sizeof(bool_cmds[0]); i++) { Ip_bool bool_val; for (bool_val = 0; bool_val <= 1; bool_val++) { Ip_bool val = bool_val; cmd = bool_cmds[i]; ret = ipmacsec_lmi_cmd_send_bool(lh, ifname, cmd, &val, IPMACSEC_LMICMD_ISSET); if (ret != IPMACSEC_LMIERR_NONE) { goto set_cmd_send_err; } ret = ipmacsec_lmi_cmd_send_bool(lh, ifname, cmd, &val, IPMACSEC_LMICMD_ISGET); if (ret != IPMACSEC_LMIERR_NONE) { goto get_cmd_send_err; } if (val != bool_val) { IPCOM_LOG3(ERR, "IPMACSEC-CTRL_TEST: cmd %s result mismatch (%s, expected %s)", ipmacsec_lmi_cmd_name(cmd), IPMACSEC_BOOL_STRING(val), IPMACSEC_BOOL_STRING(bool_val)); goto err_out; } } } for (i=0; i < sizeof(ipu32_cmds)/sizeof(ipu32_cmds[0]); i++) { Ip_u32 ipu32_val = 0; cmd = ipu32_cmds[i]; for (;;) { Ip_u32 val = ipu32_val; ret = ipmacsec_lmi_cmd_send_u32(lh, ifname, cmd, &val, IPMACSEC_LMICMD_ISSET); if (ret != IPMACSEC_LMIERR_NONE) { goto set_cmd_send_err; } ret = ipmacsec_lmi_cmd_send_u32(lh, ifname, cmd, &val, IPMACSEC_LMICMD_ISGET); if (ret != IPMACSEC_LMIERR_NONE) { goto get_cmd_send_err; } if (val != ipu32_val) { IPCOM_LOG3(ERR, "IPMACSEC-CTRL_TEST: cmd %s result mismatch (%u, expected %u)", ipmacsec_lmi_cmd_name(cmd), val, ipu32_val); goto err_out; } if (ipu32_val == 0xffffffffL) break; ipu32_val++; if (ipu32_val == 1) ipu32_val = 0xffffffffL; } } for (validateFrames=__IPMACSEC_SECY_VALIDATEFRAMES_INVALID; validateFrames<= __IPMACSEC_SECY_VALIDATEFRAMES_MAX; validateFrames++) { Ipmacsec_validateFrames_type val = validateFrames; cmd = IPMACSEC_LMICMD_SECY_VALIDATE_FRAMES; IPMACSEC_BUF_WIPE(&request); ret = ipmacsec_lmi_secy_set_cmd_append(&request, IP_NULL, ifname, cmd, &val, sizeof(val)); if (ret != IPMACSEC_LMIERR_NONE) { goto set_cmd_append_err; } ret = ipmacsec_lmi_cmd_send(IPMACSEC_LMI_TO_NETLINK_HANDLE(lh), &request, IP_NULL); if (IPMACSEC_VALIDATEFRAMES_VALID(validateFrames)) { if (ret != IPMACSEC_LMIERR_NONE) { goto set_cmd_send_err; } } else { if (ret == IPMACSEC_LMIERR_NONE) { ret = -1; goto set_cmd_send_err; } ret = 0; continue; } IPMACSEC_BUF_WIPE(&request); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_cmd_append(&request, IP_NULL, ifname, cmd, &val, sizeof(val)); if (ret != IPMACSEC_LMIERR_NONE) { goto get_cmd_append_err; } ret = ipmacsec_lmi_cmd_send(IPMACSEC_LMI_TO_NETLINK_HANDLE(lh), &request, &response); if (ret != IPMACSEC_LMIERR_NONE) { goto get_cmd_send_err; } if (IPMACSEC_VALIDATEFRAMES_VALID(validateFrames) && (val != validateFrames)) { IPCOM_LOG3(ERR, "IPMACSEC-CTRL_TEST: cmd %s result mismatch (%u, expected %u)", ipmacsec_lmi_cmd_name(cmd), val, validateFrames); goto err_out; } } goto err_out; set_cmd_append_err: IPCOM_LOG1(ERR, "IPMACSEC-CTRL_TEST: Failed to append set cmd %s", ipmacsec_lmi_cmd_name(cmd)); goto err_out; get_cmd_append_err: IPCOM_LOG1(ERR, "IPMACSEC-CTRL_TEST: Failed to append get cmd %s", ipmacsec_lmi_cmd_name(cmd)); goto err_out; set_cmd_send_err: IPCOM_LOG1(ERR, "IPMACSEC-CTRL_TEST: Unexpected result for set cmd %s", ipmacsec_lmi_cmd_name(cmd)); goto err_out; get_cmd_send_err: IPCOM_LOG1(ERR, "IPMACSEC-CTRL_TEST: Unexpected result for get cmd %s", ipmacsec_lmi_cmd_name(cmd)); goto err_out; err_out: (void)ipmacsec_nlmsg_free(&request); (void)ipmacsec_nlmsg_free(&response); return ret; } /* *=========================================================================== * ipmacsec_sc_sa_test *=========================================================================== * Description: Test the SecY SC/SA Create/Delete/Control operations. * Parameters: ifname - Interface name to send to. Must be attached 1st * otherwise this test will fail. * Returns: 0 upon success, <0 otherwise * */ IP_GLOBAL int ipmacsec_sc_sa_test(char *ifname) { IPMACSEC_LMI_HANDLE lh = IP_NULL; Ipmacsec_lmi_error ret = IPMACSEC_LMIERR_UNSPECIFIED_ERROR; Ip_u32 num_exec_tests = 0, num_failed_tests = 0; Ipmacsec_buffer response; Ipmacsec_secy_sc_info sc_info, *scinf = IP_NULL; #ifdef IPMACSEC_USE_STATS Ipmacsec_secy_sc_stats sc_stats; #endif Ipmacsec_secy_sa_info *sai = IP_NULL; Ip_u8 my_sci[IPMACSEC_SCI_LEN], sci[IPMACSEC_SCI_LEN]; Ip_u16 maxTxSAs = 0, maxRxSCs =0, maxRxSAs = 0; Ip_u8 an = 0; Ip_u16 sc = 0; Ip_u32 remlen = 0; /* Verify param */ if (!ifname) { IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: NULL ifname. Test not executed."); return IPMACSEC_LMIERR_INVALID_PARAMETER; } /* Initialize things */ IPMACSEC_BUF_INIT(&response); if (ipmacsec_nlmsg_alloc(&response) == IP_NULL) { ret = IPMACSEC_LMIERR_ALLOC_FAILED; goto err_out; } IPCOM_LOG1(INFO, "IPMACSEC-SC_SA_TEST: STARTING tests on interface %s.", ifname); /* Create an LMI handle */ lh = ipmacsec_lmi_handle_create(); if (!lh) { IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: Failed to create lmi handle. Test not executed."); return -1; } /* 1st Disable the SecY to make sure everything is started from a clean slate * This also serves as a test for the SecY existence */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Disabling SecY *****", num_exec_tests); ret = ipmacsec_lmi_secy_enable(lh, ifname, IP_FALSE); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to disable SecY (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Set the TX SCI */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Setting the TX SCI *****", num_exec_tests); ipcom_memset(my_sci, 0x11, IPMACSEC_SCI_LEN); ret = ipmacsec_lmi_secy_set_tx_sci(lh, ifname, my_sci); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to set the TX SCI (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Verify the TX SCI */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving the TX SCI *****", num_exec_tests); ret = ipmacsec_lmi_secy_get_tx_sci(lh, ifname, sci); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to get the TX SCI (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (ipcom_memcmp(my_sci, sci, IPMACSEC_SCI_LEN) != 0) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: TX SCI mismatch"); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Now Enable the SecY, which creates the SecY TX SC */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Enabling SecY *****", num_exec_tests); ret = ipmacsec_lmi_secy_enable(lh, ifname, IP_TRUE); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to enable SecY (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Verify that the TX SC was created and verify some sc_info fields and stats */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Verifying TX SC status and statistics *****", num_exec_tests); ipcom_memset(&sc_info, 0, sizeof(sc_info)); ret = ipmacsec_lmi_secy_get_tx_sc_status(lh, ifname, &sc_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (ipcom_memcmp(my_sci, sc_info.sci, IPMACSEC_SCI_LEN) != 0) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: TX SCI mismatch in sc_info"); goto err_out; } if (sc_info.dir != IPMACSEC_TX) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: TX SCI direction mismatch (%s, %u)", IPMACSEC_DIR_STRING(sc_info.dir), sc_info.dir); goto err_out; } if (sc_info.status.tx.transmitting) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: TX SCI should not be transmitting"); goto err_out; } #ifdef IPMACSEC_USE_STATS ret = ipmacsec_lmi_secy_get_tx_sc_stats(lh, ifname, &sc_stats); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC stats (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } #endif IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve the max # of TX SAs */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving max # of supported TX SAs *****", num_exec_tests); ret = ipmacsec_lmi_secy_get_maxTxKeys(lh, ifname, &maxTxSAs); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve maxTxKeys (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (maxTxSAs != IPMACSEC_MAX_SA ) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Invalid maxTxSAs=%u (!= %u)", maxTxSAs, IPMACSEC_MAX_SA); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Create max # of TX SAs + 1, last one should fail*/ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Create+Get Status+Get Stats+Control %u TX SAs (Last one should fail) *****", num_exec_tests, maxTxSAs+1); for (an=0; an <= (Ip_u8)maxTxSAs; an++) { Ipmacsec_secy_key_descriptor key_desc; Ipmacsec_secy_sa_descriptor sa_desc; Ipmacsec_secy_sa_info sa_info; Ip_u32 ref = (an+1)<<8; Ip_u8 dummy_key[16]; Ip_u32 nextPN=1; Ipmacsec_confidentiality confidentiality = IPMACSEC_CONFIDENTIALITY_UNSPECIFIED; /* Install a key */ ipcom_memset(dummy_key, 0xAE, sizeof(dummy_key)); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = (Ip_u64)(an+1); key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG4(ERR, "IPMACSEC-SC_SA_TEST: Failed to install key with key_id 0x%llx, keysize %u. (ret=%d, %s).", key_desc.key_id.val, key_desc.key_size, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Init the SA descriptor and info structures */ if (an < (Ip_u8)maxTxSAs) { if (ipmacsec_lmi_secy_sa_descriptor_init(&sa_desc, my_sci, an, IPMACSEC_TX, ref, &key_desc.key_id) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA descriptor for AN = %u.", an); goto err_out; } } else { /* For an invalid AN, we need to do it manually since ipmacsec_lmi_secy_sa_descriptor_init() does not allow it */ IPMACSEC_COPY_SCI(sa_desc.sci, my_sci); sa_desc.an = an; sa_desc.dir = IPMACSEC_TX; sa_desc.ref = ref; sa_desc.key_id.val = key_desc.key_id.val; } if (ipmacsec_lmi_secy_tx_sa_info_init(&sa_info, nextPN, confidentiality) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA info for AN = %u.", an); goto err_out; } nextPN++; /* Create the SA and verify you can retrieve its info and control it */ ret = ipmacsec_lmi_secy_create_tx_sa(lh, ifname, &sa_desc, &sa_info); if (an < (Ip_u8)maxTxSAs) { #ifdef IPMACSEC_USE_STATS Ipmacsec_secy_sa_stats sa_stats; #endif Ipmacsec_secy_sa_ctrl sa_ctrl; if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to create TX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Retrieve SA status, should succeed */ IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_tx_sa_status(lh, ifname, an, ref, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to get status for TX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!sai || (remlen < sizeof(Ipmacsec_secy_sa_info))) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid status for TX SA with AN %u (sai=%p, remlen=%u < %u).", (void *)sai, remlen, sizeof(Ipmacsec_secy_sa_info)); goto err_out; } #ifdef IPMACSEC_USE_STATS /* Retrieve SA staistics, should succeed */ ret = ipmacsec_lmi_secy_get_tx_sa_stats(lh, ifname, &sa_stats, an, ref); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to get statistics for TX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } #endif /* Control the SA, should succeed */ if (ipmacsec_lmi_secy_rx_sa_ctrl_init(&sa_ctrl, IPMACSEC_ENABLEFLAG_ON, 2, IPMACSEC_CONFIDENTIALITY_UNSPECIFIED) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA control struct for AN = %u.", an); goto err_out; } ret = ipmacsec_lmi_secy_control_tx_sa(lh, ifname, &sa_desc, &sa_ctrl); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to control TX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* TX SC should be transmitting */ ipcom_memset(&sc_info, 0, sizeof(sc_info)); ret = ipmacsec_lmi_secy_get_tx_sc_status(lh, ifname, &sc_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (!sc_info.status.tx.transmitting) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: TX SCI should be transmitting"); goto err_out; } } else { /* Remove the unused key */ if (ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc) != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed in removing key with key_id 0x%llx.", key_desc.key_id.val); } /* Should have failed to install 1 more SA than Max */ if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success creating TX SA with AN %u", an); goto err_out; } } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve TX SA list. There should be exactly maxTxSAs infos */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving TX SA list *****", num_exec_tests); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_tx_sa_status(lh, ifname, -1, 0, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SA list (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!sai || (remlen < sizeof(Ipmacsec_secy_sa_info)*maxTxSAs)) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid TX SA list (sai=%p, remlen=%u < %u).", (void *)sai, remlen, sizeof(Ipmacsec_secy_sa_info)*maxTxSAs); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Delete # of TX SAs + 1, last one should fail*/ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Deleting %u TX SAs (Last one should fail) *****", num_exec_tests, maxTxSAs+1); for (an=0; an <= (Ip_u8)maxTxSAs; an++) { Ipmacsec_secy_key_descriptor key_desc; Ipmacsec_secy_sa_descriptor sa_desc; Ip_u32 ref = (an+1)<<8; /* Init the key descriptor */ ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = (Ip_u64)(an+1); key_desc.key_type |= IPMACSEC_KEYTYPE_TRANSMIT; /* Init the SA descriptor */ if (an < (Ip_u8)maxTxSAs) { if (ipmacsec_lmi_secy_sa_descriptor_init(&sa_desc, my_sci, an, IPMACSEC_TX, ref, &key_desc.key_id) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA descriptor for AN = %u.", an); goto err_out; } } else { /* For an invalid AN, we need to do it manually since ipmacsec_lmi_secy_sa_descriptor_init() does not allow it */ IPMACSEC_COPY_SCI(sa_desc.sci, my_sci); sa_desc.an = an; sa_desc.dir = IPMACSEC_TX; sa_desc.ref = ref; sa_desc.key_id.val = key_desc.key_id.val; } /* Delete the SA */ ret = ipmacsec_lmi_secy_delete_tx_sa(lh, ifname, &sa_desc); if (an < (Ip_u8)maxTxSAs) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to delete TX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Remove the key */ ret = ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to remove key with key_id 0x%llx. (ret=%d, %s).", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } else { /* Should have failed to delete 1 more SA than Max */ if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success deleting TX SA with AN %u", an); goto err_out; } } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve TX SA list. There should be none */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving TX SA list *****", num_exec_tests); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_tx_sa_status(lh, ifname, -1, 0, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SA list (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (remlen != 0) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Invalid TX SA list (sai=%p, remlen=%u).", (void *)sai, remlen); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Verify the TX SC is not transmitting anymore */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving TX SA list *****", num_exec_tests); ipcom_memset(&sc_info, 0, sizeof(sc_info)); ret = ipmacsec_lmi_secy_get_tx_sc_status(lh, ifname, &sc_info); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (sc_info.status.tx.transmitting) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: TX SCI should not be transmitting"); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve the max # of RX SCs */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving max # of supported RX SCs *****", num_exec_tests); ret = ipmacsec_lmi_secy_get_maxRxSCs(lh, ifname, &maxRxSCs); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (maxRxSCs != IPMACSEC_MAX_RX_SC) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Invalid maxTxSAs=%u (!= %u).", maxRxSCs, IPMACSEC_MAX_RX_SC); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Create and verify maxRxSCs RX SCs + 1 (last one should fail) */ for (sc=1; sc <= maxRxSCs+1; sc++) { Ip_u8 rx_sci[IPMACSEC_SCI_LEN]; num_exec_tests++; if (sc < maxRxSCs+1) IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Creating RX SC #%u *****", num_exec_tests, sc); else IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Trying to create one more RX SC that suported (#%u should fail) *****", num_exec_tests, sc); ipcom_memset(rx_sci, (Ip_u8)sc, IPMACSEC_SCI_LEN); ret = ipmacsec_lmi_secy_create_rx_sc(lh, ifname, rx_sci); if (sc < maxRxSCs+1) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to create RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } else { if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success in creating RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Verify that the RX SC was created and verify some sc_info fields and stats */ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Verifying RX SC #%u status and statistics *****", num_exec_tests, sc); ipcom_memset(&sc_info, 0, sizeof(sc_info)); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sc_status(lh, ifname, rx_sci, &response); if (sc < maxRxSCs+1) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } scinf = (Ipmacsec_secy_sc_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!scinf || (remlen < sizeof(Ipmacsec_secy_sc_info))) { num_failed_tests++; IPCOM_LOG4(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SC status for sc #%u (scinf=%p, remlen=%u < %u).", sc, (void *)scinf, remlen, sizeof(Ipmacsec_secy_sc_info)); goto err_out; } if (ipcom_memcmp(rx_sci, scinf->sci, IPMACSEC_SCI_LEN) != 0) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: RX SCI mismatch in sc_info for sc #%u", sc); goto err_out; } if (scinf->dir != IPMACSEC_RX) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: RX SCI direction mismatch for sc #%u (%s, %u)", sc, IPMACSEC_DIR_STRING(scinf->dir), scinf->dir); goto err_out; } if (scinf->status.rx.receiving) { num_failed_tests++; IPCOM_LOG0(ERR, "IPMACSEC-SC_SA_TEST: RX SCI #%u should not be receiving"); goto err_out; } } else { if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success in retrieving RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } #ifdef IPMACSEC_USE_STATS ret = ipmacsec_lmi_secy_get_rx_sc_stats(lh, ifname, &sc_stats, rx_sci); if (sc < maxRxSCs+1) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC stats (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } else { if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success in retrieving stats for RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } #endif IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve the max # of RX SAs */ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving max # of supported RX SAs for SC #%u *****", num_exec_tests, sc); ret = ipmacsec_lmi_secy_get_maxRxKeys(lh, ifname, &maxRxSAs); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve maxRxKeys (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } if (maxRxSAs != IPMACSEC_MAX_SA) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Invalid maxRxSAs=%u (!= %u)", maxRxSAs, IPMACSEC_MAX_SA); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Create max # of RX SAs + 1, last one should fail*/ num_exec_tests++; IPCOM_LOG3(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Create+Get Status+Get Stats+Control %u RX SAs for SC #%u (Last one should fail) *****", num_exec_tests, maxRxSAs+1, sc); for (an=0; (sc < maxRxSCs+1) && (an <= (Ip_u8)maxRxSAs); an++) { Ipmacsec_secy_key_descriptor key_desc; Ipmacsec_secy_sa_descriptor sa_desc; Ipmacsec_secy_sa_info sa_info; Ip_u32 ref = (an+1)<<16; Ip_u8 dummy_key[16]; Ip_u32 nextPN=1, lowestPN = 1; /* Install a key */ ipcom_memset(dummy_key, 0xAE, sizeof(dummy_key)); ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = (Ip_u64)((sc<<8)+an+1); key_desc.key_size = sizeof(dummy_key); key_desc.key_type |= IPMACSEC_KEYTYPE_RECEIVE; ret = ipmacsec_lmi_secy_key_install(lh, ifname, &key_desc, dummy_key); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG4(ERR, "IPMACSEC-SC_SA_TEST: Failed to install key with key_id 0x%llx, keysize %u. (ret=%d, %s).", key_desc.key_id.val, key_desc.key_size, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Init the SA descriptor and info structures */ if (an < (Ip_u8)maxRxSAs) { if (ipmacsec_lmi_secy_sa_descriptor_init(&sa_desc, rx_sci, an, IPMACSEC_RX, ref, &key_desc.key_id) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA descriptor for AN = %u.", an); goto err_out; } } else { /* For an invalid AN, we need to do it manually since ipmacsec_lmi_secy_sa_descriptor_init() does not allow it */ IPMACSEC_COPY_SCI(sa_desc.sci, rx_sci); sa_desc.an = an; sa_desc.dir = IPMACSEC_RX; sa_desc.ref = ref; sa_desc.key_id.val = key_desc.key_id.val; } if (ipmacsec_lmi_secy_rx_sa_info_init(&sa_info, nextPN, lowestPN) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA info for AN = %u.", an); goto err_out; } nextPN = ++lowestPN; /* Create the SA and verify you can retrieve its info and control it */ ret = ipmacsec_lmi_secy_create_rx_sa(lh, ifname, &sa_desc, &sa_info); if (an < (Ip_u8)maxRxSAs) { #ifdef IPMACSEC_USE_STATS Ipmacsec_secy_sa_stats sa_stats; #endif Ipmacsec_secy_sa_ctrl sa_ctrl; if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to create RX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Retrieve SA status, should succeed */ IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sa_status(lh, ifname, rx_sci, an, ref, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to get status for RX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!sai || (remlen < sizeof(Ipmacsec_secy_sa_info))) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid status for RX SA with AN %u (sai=%p, remlen=%u < %u).", (void *)sai, remlen, sizeof(Ipmacsec_secy_sa_info)); goto err_out; } #ifdef IPMACSEC_USE_STATS /* Retrieve SA staistics, should succeed */ ret = ipmacsec_lmi_secy_get_rx_sa_stats(lh, ifname, &sa_stats, rx_sci, an, ref); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to get statistics for RX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } #endif /* Control the SA, should succeed */ if (ipmacsec_lmi_secy_rx_sa_ctrl_init(&sa_ctrl, IPMACSEC_ENABLEFLAG_ON, 2, 1) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA control struct for AN = %u.", an); goto err_out; } ret = ipmacsec_lmi_secy_control_rx_sa(lh, ifname, &sa_desc, &sa_ctrl); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to control RX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* RX SC should be receiving */ IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sc_status(lh, ifname, rx_sci, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; scinf = (Ipmacsec_secy_sc_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!scinf || (remlen < sizeof(Ipmacsec_secy_sc_info))) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SC list (scinf=%p, remlen=%u < %u).", (void *)scinf, remlen, sizeof(Ipmacsec_secy_sc_info)); goto err_out; } if (!scinf->status.rx.receiving) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: RX SC #%u should be receiving", sc); goto err_out; } } else { /* Remove the unused key */ if (ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc) != IPMACSEC_LMIERR_NONE) { IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed in removing key with key_id 0x%llx.", key_desc.key_id.val); } /* Should have failed to install 1 more SA than Max */ if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success creating RX SA with AN %u", an); goto err_out; } } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve RX SA list. There should be exactly maxRxSAs infos */ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving RX SA for Rx SC #%u list *****", num_exec_tests, sc); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sa_status(lh, ifname, rx_sci, -1, 0, &response); if (sc < maxRxSCs+1) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve RX SA list for sc #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!sai || (remlen < sizeof(Ipmacsec_secy_sa_info)*maxRxSAs)) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SA list (sai=%p, remlen=%u < %u).", (void *)sai, remlen, sizeof(Ipmacsec_secy_sa_info)*maxRxSAs); goto err_out; } } else { if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success in retrieving RX SA list for sc #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Delete # of RX SAs + 1, last one should fail*/ num_exec_tests++; IPCOM_LOG3(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Deleting %u RX SAs for RX SC #%u (Last one should fail) *****", num_exec_tests, maxRxSAs+1, sc); for (an=0; (sc < maxRxSCs+1) && (an <= (Ip_u8)maxRxSAs); an++) { Ipmacsec_secy_key_descriptor key_desc; Ipmacsec_secy_sa_descriptor sa_desc; Ip_u32 ref = (an+1)<<16; /* Init the key descriptor */ ipcom_memset(&key_desc, 0, sizeof(key_desc)); key_desc.key_id.val = (Ip_u64)((sc<<8)+an+1); key_desc.key_type |= IPMACSEC_KEYTYPE_RECEIVE; /* Init the SA descriptor */ if (an < (Ip_u8)maxRxSAs) { if (ipmacsec_lmi_secy_sa_descriptor_init(&sa_desc, rx_sci, an, IPMACSEC_RX, ref, &key_desc.key_id) == IP_NULL) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Failed to initialize RX SA descriptor for AN = %u.", an); goto err_out; } } else { /* For an invalid AN, we need to do it manually since ipmacsec_lmi_secy_sa_descriptor_init() does not allow it */ IPMACSEC_COPY_SCI(sa_desc.sci, rx_sci); sa_desc.an = an; sa_desc.dir = IPMACSEC_RX; sa_desc.ref = ref; sa_desc.key_id.val = key_desc.key_id.val; } /* Delete the SA */ ret = ipmacsec_lmi_secy_delete_rx_sa(lh, ifname, &sa_desc); if (an < (Ip_u8)maxRxSAs) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to delete RX SA with AN %u (ret=%d, %s).", an, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } /* Remove the key */ ret = ipmacsec_lmi_secy_key_remove(lh, ifname, &key_desc); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to remove key with key_id 0x%llx. (ret=%d, %s).", key_desc.key_id.val, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } else { /* Should have failed to delete 1 more SA than Max */ if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success deleting RX SA with AN %u", an); goto err_out; } } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Retrieve RX SA list. There should be none */ if (sc < maxRxSCs+1) { num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Retrieving RX SA list *****", num_exec_tests); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sa_status(lh, ifname, rx_sci, -1, 0, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve RX SA list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; sai = (Ipmacsec_secy_sa_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (remlen != 0) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SA list (sai=%p, remlen=%u).", (void *)sai, remlen); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Verify the RX SC is not receiving anymore */ num_exec_tests++; IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Verifyign RX SC #%u is not receiving *****", num_exec_tests, sc); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sc_status(lh, ifname, rx_sci, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; scinf = (Ipmacsec_secy_sc_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!scinf || (remlen < sizeof(Ipmacsec_secy_sc_info))) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SC list (scinf=%p, remlen=%u < %u).", (void *)scinf, remlen, sizeof(Ipmacsec_secy_sc_info)); goto err_out; } if (scinf->status.rx.receiving) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: RX SC #%u should not be receiving", sc); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); } } /* Retrieve RX SC list. Should be maxRxSCs */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Verifying RX SC list retrieval *****", num_exec_tests); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sc_status(lh, ifname, IP_NULL, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; scinf = (Ipmacsec_secy_sc_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (!scinf || (remlen < sizeof(Ipmacsec_secy_sc_info)*maxRxSCs)) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Invalid RX SC list (scinf=%p, remlen=%u < %u).", (void *)scinf, remlen, sizeof(Ipmacsec_secy_sc_info)*maxRxSCs); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); /* Delete maxRxSCs RX SCs + 1 (last one should fail) */ for (sc=1; sc <= maxRxSCs+1; sc++) { Ip_u8 rx_sci[IPMACSEC_SCI_LEN]; num_exec_tests++; if (sc < maxRxSCs+1) IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Deleting RX SC #%u *****", num_exec_tests, sc); else IPCOM_LOG2(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Trying to delete one more RX SC that suported (#%u should fail) *****", num_exec_tests, sc); ipcom_memset(rx_sci, (Ip_u8)sc, IPMACSEC_SCI_LEN); ret = ipmacsec_lmi_secy_delete_rx_sc(lh, ifname, rx_sci); if (sc < maxRxSCs+1) { if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Failed to delete RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } else { if (ret == IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: Unexpected success in deleting RX SC #%u (ret=%d, %s).", sc, ret, ipmacsec_lmi_error_name(ret)); goto err_out; } } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); } /* Retrieve RX SC list. Should be none */ num_exec_tests++; IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Executing test #%u: Verifying RX SC list retrieval returns nothing *****", num_exec_tests); IPMACSEC_BUF_WIPE(&response); ret = ipmacsec_lmi_secy_get_rx_sc_status(lh, ifname, IP_NULL, &response); if (ret != IPMACSEC_LMIERR_NONE) { num_failed_tests++; IPCOM_LOG2(ERR, "IPMACSEC-SC_SA_TEST: Failed to retrieve TX SC list (ret=%d, %s).", ret, ipmacsec_lmi_error_name(ret)); goto err_out; } remlen = 0; scinf = (Ipmacsec_secy_sc_info *)ipmacsec_buf_ptr(&response, 0, &remlen); if (remlen != 0) { num_failed_tests++; IPCOM_LOG1(ERR, "IPMACSEC-SC_SA_TEST: Unexpected RX SC list not empty (remlen=%u).", remlen); goto err_out; } IPCOM_LOG1(INFO, "***** IPMACSEC-SC_SA_TEST: Test #%u Successfully executed *****", num_exec_tests); err_out: if (num_failed_tests) { IPCOM_LOG3(ERR, "IPMACSEC-SC_SA_TEST: COMPLETED WITH FAILURES - %u tests executed, %u failed for interface %s", num_exec_tests, num_failed_tests, ifname); ret = -1; } else { IPCOM_LOG2(INFO, "IPMACSEC-SC_SA_TEST: COMPLETED SUCCESSFULLY - %u tests executed successfully for interface %s", num_exec_tests, ifname); ret = 0; } (void)ipmacsec_lmi_handle_delete(lh); (void)ipmacsec_nlmsg_free(&response); return ret; } /* *=========================================================================== * ipmacsec_counter_format_test *=========================================================================== * Description: Test the ipmacsec_secy_counter_format() routine * Parameters: none * Returns: none * */ IP_GLOBAL void ipmacsec_counter_format_test(void) { Ipmacsec_secy_counter64 count; char str[80]; for (count=1; count < 10*IPMACSEC_SECY_COUNTER_1E;) { ipcom_printf("count %llu = %s\n", count-1, ipmacsec_secy_counter_format(str, sizeof(str), count-1)); ipcom_printf("count %llu = %s\n", count, ipmacsec_secy_counter_format(str, sizeof(str), count)); ipcom_printf("count %llu = %s\n", count+1, ipmacsec_secy_counter_format(str, sizeof(str), count+1)); ipcom_printf("count %llu = %s\n", count+count/1000, ipmacsec_secy_counter_format(str, sizeof(str), count+count/1000)); count = count*10; } count = 0xFFFFFFFFFFFFFFFFULL; ipcom_printf("max count %llu = %s\n", count, ipmacsec_secy_counter_format(str, sizeof(str), count)); } /* *=========================================================================== * ipmacsec_parse_sci_string_test *=========================================================================== * Description: Test the ipmacsec_parse_sci_string() routine * Parameters: none * Returns: none * */ IP_GLOBAL int ipmacsec_parse_sci_string_test(void) { Ip_u8 sci[IPMACSEC_SCI_LEN]; Ip_u8 scival[IPMACSEC_SCI_LEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; int ret = -1000; ret = ipmacsec_parse_sci_string("00-11-22-33-44-55-66-77", sci); if ((ret < 0) || (!IPMACSEC_SCI_MATCH(sci, scival))) { return -1; } ret = ipmacsec_parse_sci_string("00:11:22:33:44:55:66:77", sci); if ((ret < 0) || (!IPMACSEC_SCI_MATCH(sci, scival))) { return -2; } ret = ipmacsec_parse_sci_string("00 11 22 33 44 55 66 77", sci); if ((ret < 0) || (!IPMACSEC_SCI_MATCH(sci, scival))) { return -3; } ret = ipmacsec_parse_sci_string("0011223344556677", sci); if ((ret < 0) || (!IPMACSEC_SCI_MATCH(sci, scival))) { return -4; } ret = ipmacsec_parse_sci_string("FF-FF-FF-FF-FF-FF-FF-FF", sci); if ((ret < 0) || (!IPMACSEC_INVALID_SCI(sci))) { return -5; } ret = ipmacsec_parse_sci_string("00*11*22*33*44*55*66*77", sci); if (ret >= 0) { return -6; } ret = ipmacsec_parse_sci_string("00-11-22-33-44-55-66-", sci); if (ret >= 0) { return -7; } ret = ipmacsec_parse_sci_string("00-11-22-33-44-55-66*77", sci); if (ret >= 0) { return -8; } ret = ipmacsec_parse_sci_string("00-11-22-33-44-55-66-77-", sci); if (ret >= 0) { return -9; } ret = ipmacsec_parse_sci_string("001122334455667", sci); if (ret >= 0) { return -10; } ret = ipmacsec_parse_sci_string("00112233445566778", sci); if (ret >= 0) { return -11; } ret = ipmacsec_parse_sci_string("X0-00-00-00-00-00-00-00", sci); if (ret >= 0) { return -12; } return 0; } /* *=========================================================================== * ipmacsec_secy_ucp_test *=========================================================================== * Description: Test the MACsec SecY Uncontrolled Port reception * Parameters: ifname - Interface bame * num_expected_pkts - # of packets to expect before existing (0 ==> loop forever or until timeout) * timeout - # of seconds before timing out (in seconds) (0 ==> no timeout) * Returns: # of UCP received packets upon success, <0 on error * */ IP_GLOBAL int ipmacsec_secy_ucp_test(char *ifname, Ip_u32 num_expected_pkts, Ip_u32 timeout) { Ip_fd sock = IP_INVALID_SOCKET; struct Ip_sockaddr_ll ll; int ret = -1; Ip_u8 *pkt = IP_NULL; Ip_u32 npkts = 0, nseconds = 0; if(!ifname || ifname[0] == 0) { IPCOM_LOG0(ERR, "ipmacsec_secy_ucp_test :: ifname not set"); goto err_out; } sock = ipcom_socket(IP_PF_PACKET, IP_SOCK_RAW, IPNET_ETHFRAME_MACSEC); if (sock == IP_INVALID_SOCKET) { IPCOM_LOG1(ERR, "ipmacsec_secy_ucp_test :: ipcom_socket() failed, errno: %d\n", ipcom_errno); goto err_out; } IPCOM_LOG1(INFO, "ipmacsec_secy_ucp_test ::opened MACsec raw socket (fd = %u)\n", sock); ipcom_memset(&ll, 0, sizeof(ll)); ll.sll_family = IP_AF_PACKET; ll.sll_ifindex = ipcom_if_nametoindex(ifname); if(ll.sll_ifindex == 0) { IPCOM_LOG1(ERR, "ipmacsec_secy_ucp_test :: ipcom_if_nametoindex failed for %s", ifname); goto err_out; } /* Bind raw socket to device */ if (ipcom_setsockopt(sock, IP_SOL_SOCKET, IP_SO_BINDTODEVICE, ifname, IP_IFNAMSIZ) == IP_SOCKERR) { IPCOM_LOG3(ERR, "ipmacsec_secy_ucp_test :: ipcom_setsockopt(bindtodevice,%s) failed : %s [%d]", ifname, ipcom_strerror(ipcom_errno), ipcom_errno);; goto err_out; } IPCOM_LOG2(INFO, "ipmacsec_secy_ucp_test :: bound sock to %s (index %u)", ifname, ll.sll_ifindex); pkt = ipcom_malloc(1514); if (!pkt) { IPCOM_LOG0(ERR, "ipmacsec_secy_ucp_test :: failed to allocate packet"); goto err_out; } while(1) { int rc; Ip_fd_set rset; struct Ip_timeval tv; IP_FD_ZERO(&rset); IP_FD_SET(sock, &rset); tv.tv_sec = 1; tv.tv_usec = 0; IPCOM_LOG1(DEBUG2, "ipmacsec_secy_ucp_test :: blocking on socket %u", sock); ret = ipcom_socketselect(sock + 1, &rset, IP_NULL, IP_NULL, &tv); if (ret < 0) { IPCOM_LOG1(ERR, "ipmacsec_secy_ucp_test :: ipcom_socketselect failed (%d)", rc); goto err_out; } if (ret == 0) { nseconds++; } while (ret) { rc = ipcom_recvfrom(sock, pkt, 1514, 0, IP_NULL, IP_NULL); if (rc <= 0) { IPCOM_LOG1(ERR, "ipmacsec_secy_ucp_test :: ipcom_recvfrom failed (%d)", rc); goto err_out; } npkts++; ret--; IPCOM_LOG2(DEBUG2, "ipmacsec_secy_ucp_test ::rc = %d on socket %u", rc, sock); ipmacsec_dump_buffer("MACsec received frame: ", pkt, rc); } if (num_expected_pkts && (npkts >= num_expected_pkts)) { break; } if (timeout && (nseconds >= timeout)) break; } ret = npkts; err_out: if(sock != IP_INVALID_SOCKET) { ipcom_socketclose(sock); sock = IP_INVALID_SOCKET; } if (pkt) { ipcom_free(pkt); pkt = IP_NULL; } IPCOM_LOG1(INFO, "ipmacsec_secy_ucp_test :: Exiting (ret = %d)", ret); return ret; } /* Variable used to store # of pkts received by the MACsec SecY Uncontrolled Port reception daemon */ IP_STATIC int ucp_test_daemon_nrcv_pkts = 0; /* *=========================================================================== * ipmacsec_secy_ucp_testd *=========================================================================== * Description: MACsec SecY Uncontrolled Port reception test daemon * Parameters: * Returns: * */ IP_STATIC IPCOM_PROCESS(ipmacsec_secy_ucp_testd) { char ifname[IP_IFNAMSIZ]; Ip_size_t len; Ip_u32 num_expected_pkts; Ip_u32 timeout; char strval[16]; char *sysvar; IPCOM_LOG0(DEBUG2, "ipmacsec_secy_ucp_testd :: Started"); ucp_test_daemon_nrcv_pkts = -1; ipcom_proc_init(); sysvar = "ipmacsec.secy.ut.ucptestd.ifname"; len = IP_IFNAMSIZ; if (ipcom_sysvar_get(sysvar, ifname, &len) == IP_NULL) { IPCOM_LOG1(WARNING, "ipmacsec_secy_ucp_testd :: Failed to get sysvar %s", sysvar); goto exit; } sysvar = "ipmacsec.secy.ut.ucptestd.npkts"; len = sizeof(strval); if (ipcom_sysvar_get(sysvar, strval, &len) == IP_NULL) { IPCOM_LOG1(WARNING, "ipmacsec_secy_ucp_testd :: Failed to get sysvar %s", sysvar); goto exit; } num_expected_pkts = ipcom_atoi(strval); sysvar = "ipmacsec.secy.ut.ucptestd.timeout"; len = sizeof(strval); if (ipcom_sysvar_get(sysvar, strval, &len) == IP_NULL) { IPCOM_LOG1(WARNING, "ipmacsec_secy_ucp_testd :: Failed to get sysvar %s", sysvar); goto exit; } timeout = ipcom_atoi(strval); ucp_test_daemon_nrcv_pkts = ipmacsec_secy_ucp_test(ifname, num_expected_pkts, timeout); exit: IPCOM_LOG1(DEBUG2, "ipmacsec_secy_ucp_testd :: Exiting (ucp_test_daemon_nrcv_pkts = %d)", ucp_test_daemon_nrcv_pkts); ipcom_proc_exit(); } /* *=========================================================================== * ipmacsec_secy_ucp_test_start_daemon *=========================================================================== * Description: Start a MACsec SecY Uncontrolled Port reception test daemon * Should only start one daemon at a time. * Parameters: ifname - Interface bame * num_expected_pkts - # of packets to expect before existing (0 ==> loop forever or until timeout) * timeout - # of seconds before timing out (in seconds) (0 ==> no timeout) * Returns: 0 upon successfully starting the daemon, <0 on error * */ IP_GLOBAL int ipmacsec_secy_ucp_test_start_daemon(char *ifname, Ip_u32 num_expected_pkts, Ip_u32 timeout) { Ipcom_proc_attr proc_attr; char strval[16]; char *sysvar; Ip_err rc; sysvar = "ipmacsec.secy.ut.ucptestd.ifname"; if ((rc = ipcom_sysvar_set(sysvar, ifname, IPCOM_SYSVAR_FLAG_OVERWRITE)) != IPCOM_SUCCESS) { IPCOM_LOG1(CRIT, "ipmacsec_secy_ucp_testd :: Failed to set sysvar %s", sysvar); return rc; } ipcom_snprintf(strval, sizeof(strval), "%d", num_expected_pkts); sysvar = "ipmacsec.secy.ut.ucptestd.npkts"; if ((rc = ipcom_sysvar_set(sysvar, strval, IPCOM_SYSVAR_FLAG_OVERWRITE)) != IPCOM_SUCCESS) { IPCOM_LOG1(CRIT, "ipmacsec_secy_ucp_testd :: Failed to set sysvar %s", sysvar); return rc; } ipcom_snprintf(strval, sizeof(strval), "%d", timeout); sysvar = "ipmacsec.secy.ut.ucptestd.timeout"; if ((rc = ipcom_sysvar_set(sysvar, strval, IPCOM_SYSVAR_FLAG_OVERWRITE)) != IPCOM_SUCCESS) { IPCOM_LOG1(CRIT, "ipmacsec_secy_ucp_testd :: Failed to set sysvar %s", sysvar); return rc; } ipcom_proc_attr_init(&proc_attr); proc_attr.stacksize = IPCOM_PROC_STACK_SMALL; rc = ipcom_proc_acreate("secy_ucp_testd", ipmacsec_secy_ucp_testd, &proc_attr, IP_NULL); return rc; } /* *=========================================================================== * ipmacsec_secy_ucp_test_daemon_num_rcv_pkts *=========================================================================== * Description: Return the # of pkts received by the MACsec SecY Uncontrolled Port reception daemon * Parameters: None * Returns: # of pkts rcvd * */ IP_GLOBAL Ip_u32 ipmacsec_secy_ucp_test_daemon_num_rcv_pkts(void) { return ucp_test_daemon_nrcv_pkts; } /* UNIT TEST CODE FOR EASILY SETTING UP SECY CONFIGURATION */ Ipmacsec_secy_profile *Ipmacsec_secy_ut_profiles[] = { &ipmacsec_ut_profile_1A, &ipmacsec_ut_profile_1B, &ipmacsec_ut_profile_2A, &ipmacsec_ut_profile_2B, &ipmacsec_ut_profile_3A, &ipmacsec_ut_profile_3B }; /* *=========================================================================== * ipmacsec_lmi_secy_setup_ut_profile *=========================================================================== * Description: Setup the specified Unit Test SecY profile * Parameters: ifname - Interface bame * ut_profile_index - Index of the unit test profile to setup * Returns: IPMACSEC_LMIERR_NONE upon success, * an Ipmacsec_lmi_error <0 upon error * */ IP_GLOBAL Ipmacsec_lmi_error ipmacsec_lmi_secy_setup_ut_profile(char *ifname, Ip_u8 ut_profile_index) { if (ut_profile_index >= sizeof(Ipmacsec_secy_ut_profiles)/sizeof(Ipmacsec_secy_profile *)) { return IPMACSEC_LMIERR_INVALID_PARAMETER; } return ipmacsec_lmi_secy_setup_profile(ifname, Ipmacsec_secy_ut_profiles[ut_profile_index]); } #endif