summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink/utils.h7
-rw-r--r--lib/utils.c9
-rw-r--r--lib/xfrm/sa.c96
3 files changed, 98 insertions, 14 deletions
diff --git a/include/netlink/utils.h b/include/netlink/utils.h
index ebf12cf..43c9147 100644
--- a/include/netlink/utils.h
+++ b/include/netlink/utils.h
@@ -197,6 +197,13 @@ enum {
NL_CAPABILITY_NL_OBJECT_DIFF64 = 16,
#define NL_CAPABILITY_NL_OBJECT_DIFF64 NL_CAPABILITY_NL_OBJECT_DIFF64
+ /**
+ * Support omitting @key argument to xfrmnl_sa_get_*_params() to check
+ * for required buffer size for key.
+ */
+ NL_CAPABILITY_XFRM_SA_KEY_SIZE = 17,
+#define NL_CAPABILITY_XFRM_SA_KEY_SIZE NL_CAPABILITY_XFRM_SA_KEY_SIZE
+
__NL_CAPABILITY_MAX,
NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1),
#define NL_CAPABILITY_MAX NL_CAPABILITY_MAX
diff --git a/lib/utils.c b/lib/utils.c
index 85beb86..0c91c97 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1160,6 +1160,15 @@ int nl_has_capability (int capability)
NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR,
NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE,
NL_CAPABILITY_NL_OBJECT_DIFF64),
+ _NL_SET (2,
+ NL_CAPABILITY_XFRM_SA_KEY_SIZE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0),
/* IMPORTANT: these capability numbers are intended to be universal and stable
* for libnl3. Don't allocate new numbers on your own that differ from upstream
* libnl3.
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index a1abfe7..1c0888b 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -1622,14 +1622,32 @@ int xfrmnl_sa_set_flags (struct xfrmnl_sa* sa, unsigned int flags)
return 0;
}
+/**
+ * Get the aead-params
+ * @arg sa the xfrmnl_sa object
+ * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes.
+ * @arg key_len an optional output value for the key length in bits.
+ * @arg icv_len an optional output value for the alt-icv-len.
+ * @arg key an optional buffer large enough for the key. It must contain at least
+ * ((@key_len + 7) / 8) bytes.
+ *
+ * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand,
+ * call xfrmnl_sa_get_aead_params() without @key argument to query only the required buffer size.
+ *
+ * @return 0 on success or a negative error code.
+ */
int xfrmnl_sa_get_aead_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, unsigned int* icv_len, char* key)
{
if (sa->ce_mask & XFRM_SA_ATTR_ALG_AEAD)
{
- strcpy (alg_name, sa->aead->alg_name);
- *key_len = sa->aead->alg_key_len;
- *icv_len = sa->aead->alg_icv_len;
- memcpy ((void *)key, (void *)sa->aead->alg_key, ((sa->aead->alg_key_len + 7)/8));
+ if (alg_name)
+ strcpy (alg_name, sa->aead->alg_name);
+ if (key_len)
+ *key_len = sa->aead->alg_key_len;
+ if (icv_len)
+ *icv_len = sa->aead->alg_icv_len;
+ if (key)
+ memcpy (key, sa->aead->alg_key, ((sa->aead->alg_key_len + 7)/8));
}
else
return -1;
@@ -1659,14 +1677,32 @@ int xfrmnl_sa_set_aead_params (struct xfrmnl_sa* sa, const char* alg_name, unsig
return 0;
}
+/**
+ * Get the auth-params
+ * @arg sa the xfrmnl_sa object
+ * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes.
+ * @arg key_len an optional output value for the key length in bits.
+ * @arg trunc_len an optional output value for the alg-trunc-len.
+ * @arg key an optional buffer large enough for the key. It must contain at least
+ * ((@key_len + 7) / 8) bytes.
+ *
+ * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand,
+ * call xfrmnl_sa_get_auth_params() without @key argument to query only the required buffer size.
+ *
+ * @return 0 on success or a negative error code.
+ */
int xfrmnl_sa_get_auth_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, unsigned int* trunc_len, char* key)
{
if (sa->ce_mask & XFRM_SA_ATTR_ALG_AUTH)
{
- strcpy (alg_name, sa->auth->alg_name);
- *key_len = sa->auth->alg_key_len;
- *trunc_len = sa->auth->alg_trunc_len;
- memcpy ((void *)key, (void *)sa->auth->alg_key, ((sa->auth->alg_key_len + 7)/8));
+ if (alg_name)
+ strcpy (alg_name, sa->auth->alg_name);
+ if (key_len)
+ *key_len = sa->auth->alg_key_len;
+ if (trunc_len)
+ *trunc_len = sa->auth->alg_trunc_len;
+ if (key)
+ memcpy (key, sa->auth->alg_key, (sa->auth->alg_key_len + 7)/8);
}
else
return -1;
@@ -1696,13 +1732,29 @@ int xfrmnl_sa_set_auth_params (struct xfrmnl_sa* sa, const char* alg_name, unsig
return 0;
}
+/**
+ * Get the crypto-params
+ * @arg sa the xfrmnl_sa object
+ * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes.
+ * @arg key_len an optional output value for the key length in bits.
+ * @arg key an optional buffer large enough for the key. It must contain at least
+ * ((@key_len + 7) / 8) bytes.
+ *
+ * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand,
+ * call xfrmnl_sa_get_crypto_params() without @key argument to query only the required buffer size.
+ *
+ * @return 0 on success or a negative error code.
+ */
int xfrmnl_sa_get_crypto_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, char* key)
{
if (sa->ce_mask & XFRM_SA_ATTR_ALG_CRYPT)
{
- strcpy (alg_name, sa->crypt->alg_name);
- *key_len = sa->crypt->alg_key_len;
- memcpy ((void *)key, (void *)sa->crypt->alg_key, ((sa->crypt->alg_key_len + 7)/8));
+ if (alg_name)
+ strcpy (alg_name, sa->crypt->alg_name);
+ if (key_len)
+ *key_len = sa->crypt->alg_key_len;
+ if (key)
+ memcpy (key, sa->crypt->alg_key, ((sa->crypt->alg_key_len + 7)/8));
}
else
return -1;
@@ -1731,13 +1783,29 @@ int xfrmnl_sa_set_crypto_params (struct xfrmnl_sa* sa, const char* alg_name, uns
return 0;
}
+/**
+ * Get the comp-params
+ * @arg sa the xfrmnl_sa object
+ * @arg alg_name an optional output buffer for the algorithm name. Must be at least 64 bytes.
+ * @arg key_len an optional output value for the key length in bits.
+ * @arg key an optional buffer large enough for the key. It must contain at least
+ * ((@key_len + 7) / 8) bytes.
+ *
+ * Warning: you must ensure that @key is large enough. If you don't know the key_len before-hand,
+ * call xfrmnl_sa_get_comp_params() without @key argument to query only the required buffer size.
+ *
+ * @return 0 on success or a negative error code.
+ */
int xfrmnl_sa_get_comp_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, char* key)
{
if (sa->ce_mask & XFRM_SA_ATTR_ALG_COMP)
{
- strcpy (alg_name, sa->comp->alg_name);
- *key_len = sa->comp->alg_key_len;
- memcpy ((void *)key, (void *)sa->comp->alg_key, ((sa->comp->alg_key_len + 7)/8));
+ if (alg_name)
+ strcpy (alg_name, sa->comp->alg_name);
+ if (key_len)
+ *key_len = sa->comp->alg_key_len;
+ if (key)
+ memcpy (key, sa->comp->alg_key, ((sa->comp->alg_key_len + 7)/8));
}
else
return -1;