Skip to content

Commit

Permalink
[Rekey] Support for configurable max SAs per Secure Channel (#47)
Browse files Browse the repository at this point in the history
Adding code to query MACSEC_PORT_TABLE max_sa_per_sc in STATE_DB.
In PR sonic-net/sonic-swss#2250 MacsecOrch will publish the max_sa_per_sc in STATE_DB.
If we don't find the max_sa_per_sc we will default to 4 for max sa per sc.

Max sa per sc is used to determine which AN values can be used during rekey.
If a non-default max sa per sc is specified we will use the max value for rekey server priority.

Infra fix in sonic_operators.cpp.
-get function was extracting value incorrectly.
-pair_count wasn't getting incremented per pair.

Signed-off-by: Nathan Wolfe nwolfe@arista.com
  • Loading branch information
arista-nwolfe authored May 6, 2022
1 parent f36c8c8 commit fc9dce8
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 3 deletions.
16 changes: 16 additions & 0 deletions src/common/ieee802_1x_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ enum validate_frames {
Strict,
};

/*
* IEEE Association Number (which identifies the SA within an SC
* in a Macsec frame) is 2b wide. Hence we can have up to 4
* SAs active at any given time per SC. This setting
* allows an implementation to specify a lower value
*/
enum max_sa_per_sc {
MAX_SA_PER_SC_1 = 1,
MAX_SA_PER_SC_2 = 2,
MAX_SA_PER_SC_3 = 3,
MAX_SA_PER_SC_4 = 4,
MAX_SA_PER_SC_DEFAULT = MAX_SA_PER_SC_4,
};

/* IEEE Std 802.1X-2010 - Table 11-6 - Confidentiality Offset */
enum confidentiality_offset {
CONFIDENTIALITY_NONE = 0,
Expand All @@ -81,6 +95,8 @@ enum confidentiality_offset {
};

/* IEEE Std 802.1X-2010 - Table 9-2 */

#define DEFAULT_PRIO_HIGHEST 0x0
#define DEFAULT_PRIO_INFRA_PORT 0x10
#define DEFAULT_PRIO_PRIMRAY_AP 0x30
#define DEFAULT_PRIO_SECONDARY_AP 0x50
Expand Down
8 changes: 8 additions & 0 deletions src/drivers/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -4021,6 +4021,14 @@ struct wpa_driver_ops {
*/
int (*macsec_get_capability)(void *priv, enum macsec_cap *cap);

/**
* macsec_get_max_sa_per_sc - Inform MKA of max number of SAs per SC
* @priv: Private driver interface data
* @max: Max number of SAs per SC
* Returns: 0 on success, -1 on failure
*/
int (*macsec_get_max_sa_per_sc)(void *priv, enum max_sa_per_sc *max);

/**
* enable_protect_frames - Set protect frames status
* @priv: Private driver interface data
Expand Down
48 changes: 48 additions & 0 deletions src/drivers/driver_macsec_sonic.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,53 @@ static int macsec_sonic_macsec_deinit(void *priv)
return ret;
}

static int macsec_sonic_macsec_get_max_sa_per_sc(void *priv,
enum max_sa_per_sc *max)
{
struct macsec_sonic_data *drv = priv;
ENTER_LOG;

const struct sonic_db_name_value_pair pairs[] =
{
{"state", "ok"},
};

int ret = sonic_db_wait(
drv->sonic_manager,
STATE_DB,
STATE_MACSEC_PORT_TABLE_NAME,
SET_COMMAND,
drv->ifname,
PAIR_ARRAY(pairs));
if (ret == SONIC_DB_SUCCESS)
{
struct sonic_db_name_value_pairs * get_pairs = sonic_db_malloc_name_value_pairs();
ret = sonic_db_get(
drv->sonic_manager,
STATE_DB,
STATE_MACSEC_PORT_TABLE_NAME,
drv->ifname,
get_pairs);
if (ret == SONIC_DB_SUCCESS) {
int max_val = -1;
for ( unsigned int i = 0; i < get_pairs->pair_count; ++i ) {
if ( strcmp( get_pairs->pairs[i].name, "max_sa_per_sc" ) == 0 ) {
PRINT_LOG( "max_sa_per_sc found: %s", get_pairs->pairs[i].value );
sscanf( get_pairs->pairs[i].value, "%4d", &max_val );
break;
}
}
if ( max_val == -1 ) {
// If we don't find a max_sa_per_sc attribute use default value
max_val = MAX_SA_PER_SC_DEFAULT;
}
*max = max_val;
}
sonic_db_free_name_value_pairs( get_pairs );
}
return ret;
}

static int macsec_sonic_get_capability(void *priv, enum macsec_cap *cap)
{
struct macsec_sonic_data *drv = priv;
Expand Down Expand Up @@ -982,6 +1029,7 @@ const struct wpa_driver_ops wpa_driver_macsec_sonic_ops = {

.macsec_init = macsec_sonic_macsec_init,
.macsec_deinit = macsec_sonic_macsec_deinit,
.macsec_get_max_sa_per_sc = macsec_sonic_macsec_get_max_sa_per_sc,
.macsec_get_capability = macsec_sonic_get_capability,
.enable_protect_frames = macsec_sonic_enable_protect_frames,
.enable_encrypt = macsec_sonic_enable_encrypt,
Expand Down
3 changes: 2 additions & 1 deletion src/drivers/sonic_operators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ class sonic_db_manager{
memcpy(name, result[i].first.data(), result[i].first.length() + 1);
pairs->pairs[pairs->pair_count].name = name;
char * value = reinterpret_cast<char *>(malloc(result[i].second.length() + 1));
memcpy(value, result[i].first.data(), result[i].second.length() + 1);
memcpy(value, result[i].second.data(), result[i].second.length() + 1);
pairs->pairs[pairs->pair_count].value = value;
pairs->pair_count++;
}
return SONIC_DB_SUCCESS;
}
Expand Down
19 changes: 17 additions & 2 deletions src/pae/ieee802_1x_kay.c
Original file line number Diff line number Diff line change
Expand Up @@ -2323,7 +2323,7 @@ ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)

kay->dist_kn++;
kay->dist_an++;
if (kay->dist_an > 3)
if (kay->dist_an > kay->max_sa_per_sc - 1)
kay->dist_an = 0;

kay->dist_time = time(NULL);
Expand Down Expand Up @@ -3595,7 +3595,6 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
kay->actor_sci.port = host_to_be16(port ? port : 0x0001);
wpa_printf(MSG_DEBUG, "KaY: Generated SCI: %s",
sci_txt(&kay->actor_sci));
kay->actor_priority = priority;

/* While actor acts as a key server, shall distribute sakey */
kay->dist_kn = 1;
Expand Down Expand Up @@ -3659,6 +3658,22 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,

wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");

enum max_sa_per_sc max;
if (secy_get_max_sa_per_sc( kay, &max ) < 0){
wpa_printf(MSG_ERROR, "KaY: Could not determine max SAs per SC");
goto error;
}
kay->max_sa_per_sc = max;

/*
* If the maximum SAs per SC is not the default, the actor_priority
* is forced to the highest value of 0 so it can be elected as key
* server and control the AN assignments to within the supported limit
*/
if (max != MAX_SA_PER_SC_4)
priority = DEFAULT_PRIO_HIGHEST;
kay->actor_priority = priority;

/* init CP */
kay->cp = ieee802_1x_cp_sm_init(kay);
if (kay->cp == NULL)
Expand Down
2 changes: 2 additions & 0 deletions src/pae/ieee802_1x_kay.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ struct ieee802_1x_kay_ctx {
/* abstract wpa driver interface */
int (*macsec_init)(void *ctx, struct macsec_init_params *params);
int (*macsec_deinit)(void *ctx);
int (*macsec_get_max_sa_per_sc)(void *priv, enum max_sa_per_sc *max);
int (*macsec_get_capability)(void *priv, enum macsec_cap *cap);
int (*enable_protect_frames)(void *ctx, bool enabled);
int (*enable_encrypt)(void *ctx, bool enabled);
Expand Down Expand Up @@ -193,6 +194,7 @@ struct ieee802_1x_kay {
bool macsec_include_sci;
bool macsec_replay_protect;
u32 macsec_replay_window;
u8 max_sa_per_sc;
enum validate_frames macsec_validate;
enum confidentiality_offset macsec_confidentiality;
u32 mka_hello_time;
Expand Down
29 changes: 29 additions & 0 deletions src/pae/ieee802_1x_secy_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,32 @@ int secy_deinit_macsec(struct ieee802_1x_kay *kay)

return ops->macsec_deinit(ops->ctx);
}

int secy_get_max_sa_per_sc(struct ieee802_1x_kay *kay, enum max_sa_per_sc *max)
{
struct ieee802_1x_kay_ctx *ops;

if (!kay) {
wpa_printf(MSG_ERROR, "KaY: %s params invalid", __func__);
return -1;
}

ops = kay->ctx;
if (!ops) {
wpa_printf(MSG_ERROR,
"KaY: secy get_max_sas_per_sc operation not supported");
return -1;
}

/*
* If the max SAs per SC setting control is not implemented by
* the driver, then return the default
*/
if( !ops->macsec_get_max_sa_per_sc) {
*max = MAX_SA_PER_SC_DEFAULT;
return 0;
}

return ops->macsec_get_max_sa_per_sc(ops->ctx, max);
}

1 change: 1 addition & 0 deletions src/pae/ieee802_1x_secy_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct ieee802_1x_kay_conf;

int secy_init_macsec(struct ieee802_1x_kay *kay);
int secy_deinit_macsec(struct ieee802_1x_kay *kay);
int secy_get_max_sa_per_sc(struct ieee802_1x_kay *kay, enum max_sa_per_sc *max);

/****** CP -> SecY ******/
int secy_cp_control_validate_frames(struct ieee802_1x_kay *kay,
Expand Down
8 changes: 8 additions & 0 deletions wpa_supplicant/driver_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,14 @@ static inline int wpa_drv_macsec_deinit(struct wpa_supplicant *wpa_s)
return wpa_s->driver->macsec_deinit(wpa_s->drv_priv);
}

static inline int wpa_drv_macsec_get_max_sa_per_sc(struct wpa_supplicant *wpa_s,
enum max_sa_per_sc *max)
{
if (!wpa_s->driver->macsec_get_max_sa_per_sc)
return -1;
return wpa_s->driver->macsec_get_max_sa_per_sc(wpa_s->drv_priv, max);
}

static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s,
enum macsec_cap *cap)
{
Expand Down
5 changes: 5 additions & 0 deletions wpa_supplicant/wpas_kay.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ static int wpas_macsec_deinit(void *priv)
return wpa_drv_macsec_deinit(priv);
}

static int wpas_macsec_get_max_sa_per_sc(void *priv, enum max_sa_per_sc *max)
{
return wpa_drv_macsec_get_max_sa_per_sc(priv, max);
}

static int wpas_macsec_get_capability(void *priv, enum macsec_cap *cap)
{
Expand Down Expand Up @@ -216,6 +220,7 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)

kay_ctx->macsec_init = wpas_macsec_init;
kay_ctx->macsec_deinit = wpas_macsec_deinit;
kay_ctx->macsec_get_max_sa_per_sc = wpas_macsec_get_max_sa_per_sc;
kay_ctx->macsec_get_capability = wpas_macsec_get_capability;
kay_ctx->enable_protect_frames = wpas_enable_protect_frames;
kay_ctx->enable_encrypt = wpas_enable_encrypt;
Expand Down

0 comments on commit fc9dce8

Please # to comment.