aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/odp_ipsec.c
diff options
context:
space:
mode:
authorJanne Peltonen <janne.peltonen@nokia.com>2020-12-03 09:00:50 +0200
committerPetri Savolainen <petri.savolainen@nokia.com>2020-12-04 16:35:15 +0200
commit9eafeb3b4ab4a5f0543407f691a19468a8d364c5 (patch)
treeac782617f68c81087db94f317a9ed11ad1496677 /platform/linux-generic/odp_ipsec.c
parenta261926444489cae0347a3be519f672b40b79c6d (diff)
linux-gen: ipsec: remove unsupported algorithms from capabilities
Set capability bits only for cryptoalgorithms for which use with ESP or AH has been defined in some RFC and for which at least one instance (defined by key lenghts etc) is supported as indicated by the more specific odp_ipsec_chipher_capability() and odp_ipsec_auth_capability() functions. Certain combined mode algorithms are configured by setting the same cipher and auth algorithm. Indicate support for either both or neither. This fixes the problems that: - Algorithms which are not supported in IPsec at all but are supported in in crypto module, such as AES-ECB, are included in IPsec capabilities. - AES-CCM is reported as supported even when the union of ICV lengths supported by the crypto module and the ICV lenghts supported for CCM in the IPsec module is empty. Signed-off-by: Janne Peltonen <janne.peltonen@nokia.com> Reviewed-by: Jere Leppänen <jere.leppanen@nokia.com>
Diffstat (limited to 'platform/linux-generic/odp_ipsec.c')
-rw-r--r--platform/linux-generic/odp_ipsec.c79
1 files changed, 74 insertions, 5 deletions
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index e6c82603d..8a21fe1f0 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -28,10 +28,82 @@
static odp_ipsec_config_t *ipsec_config;
-int odp_ipsec_capability(odp_ipsec_capability_t *capa)
+/*
+ * Set cabability bits for algorithms that are defined for use with IPsec
+ * and for which the IPsec crypto or auth capability function returns
+ * at least one supported instance.
+ */
+static int set_ipsec_crypto_capa(odp_ipsec_capability_t *capa)
{
int rc;
odp_crypto_capability_t crypto_capa;
+
+ rc = odp_crypto_capability(&crypto_capa);
+ if (rc < 0)
+ return rc;
+
+#define CHECK_CIPHER(field, alg) do { \
+ if (crypto_capa.ciphers.bit.field && \
+ odp_ipsec_cipher_capability(alg, NULL, 0) > 0) \
+ capa->ciphers.bit.field = 1; \
+} while (0)
+
+ CHECK_CIPHER(null, ODP_CIPHER_ALG_NULL);
+ CHECK_CIPHER(des, ODP_CIPHER_ALG_DES);
+ CHECK_CIPHER(trides_cbc, ODP_CIPHER_ALG_3DES_CBC);
+ CHECK_CIPHER(aes_cbc, ODP_CIPHER_ALG_AES_CBC);
+ CHECK_CIPHER(aes_ctr, ODP_CIPHER_ALG_AES_CTR);
+ CHECK_CIPHER(aes_gcm, ODP_CIPHER_ALG_AES_GCM);
+ CHECK_CIPHER(aes_ccm, ODP_CIPHER_ALG_AES_CCM);
+ CHECK_CIPHER(chacha20_poly1305, ODP_CIPHER_ALG_CHACHA20_POLY1305);
+
+#define CHECK_AUTH(field, alg) do { \
+ if (crypto_capa.auths.bit.field && \
+ odp_ipsec_auth_capability(alg, NULL, 0) > 0) \
+ capa->auths.bit.field = 1; \
+} while (0)
+
+ CHECK_AUTH(null, ODP_AUTH_ALG_NULL);
+ CHECK_AUTH(md5_hmac, ODP_AUTH_ALG_MD5_HMAC);
+ CHECK_AUTH(sha1_hmac, ODP_AUTH_ALG_SHA1_HMAC);
+ CHECK_AUTH(sha256_hmac, ODP_AUTH_ALG_SHA256_HMAC);
+ CHECK_AUTH(sha384_hmac, ODP_AUTH_ALG_SHA384_HMAC);
+ CHECK_AUTH(sha512_hmac, ODP_AUTH_ALG_SHA512_HMAC);
+ CHECK_AUTH(aes_gcm, ODP_AUTH_ALG_AES_GCM);
+ CHECK_AUTH(aes_gmac, ODP_AUTH_ALG_AES_GMAC);
+ CHECK_AUTH(aes_ccm, ODP_AUTH_ALG_AES_CCM);
+ CHECK_AUTH(aes_cmac, ODP_AUTH_ALG_AES_CMAC);
+ CHECK_AUTH(aes_xcbc_mac, ODP_AUTH_ALG_AES_XCBC_MAC);
+ CHECK_AUTH(chacha20_poly1305, ODP_AUTH_ALG_CHACHA20_POLY1305);
+
+ /*
+ * Certain combined mode algorithms are configured by setting
+ * both cipher and auth to the corresponding algorithm when
+ * creating an SA. Since such algorithms cannot be combined
+ * with anything else, clear both capability fields if the
+ * cipher and auth check did not both succeed.
+ *
+ * Although AES-GMAC is a combined mode algorithm, it does
+ * not appear here because it is configured by setting cipher
+ * to null.
+ */
+#define REQUIRE_BOTH(field) do { \
+ if (!capa->ciphers.bit.field) \
+ capa->auths.bit.field = 0; \
+ if (!capa->auths.bit.field) \
+ capa->ciphers.bit.field = 0; \
+ } while (0)
+
+ REQUIRE_BOTH(aes_gcm);
+ REQUIRE_BOTH(aes_ccm);
+ REQUIRE_BOTH(chacha20_poly1305);
+
+ return 0;
+}
+
+int odp_ipsec_capability(odp_ipsec_capability_t *capa)
+{
+ int rc;
odp_queue_capability_t queue_capa;
if (odp_global_ro.disable.ipsec) {
@@ -52,13 +124,10 @@ int odp_ipsec_capability(odp_ipsec_capability_t *capa)
capa->max_antireplay_ws = IPSEC_ANTIREPLAY_WS;
- rc = odp_crypto_capability(&crypto_capa);
+ rc = set_ipsec_crypto_capa(capa);
if (rc < 0)
return rc;
- capa->ciphers = crypto_capa.ciphers;
- capa->auths = crypto_capa.auths;
-
rc = odp_queue_capability(&queue_capa);
if (rc < 0)
return rc;