0001
0002
0003
0004 #include <crypto/aead.h>
0005 #include <linux/debugfs.h>
0006 #include <net/xfrm.h>
0007
0008 #include "netdevsim.h"
0009
0010 #define NSIM_IPSEC_AUTH_BITS 128
0011
0012 static ssize_t nsim_dbg_netdev_ops_read(struct file *filp,
0013 char __user *buffer,
0014 size_t count, loff_t *ppos)
0015 {
0016 struct netdevsim *ns = filp->private_data;
0017 struct nsim_ipsec *ipsec = &ns->ipsec;
0018 size_t bufsize;
0019 char *buf, *p;
0020 int len;
0021 int i;
0022
0023
0024
0025
0026 bufsize = (ipsec->count * 4 * 60) + 60;
0027 buf = kzalloc(bufsize, GFP_KERNEL);
0028 if (!buf)
0029 return -ENOMEM;
0030
0031 p = buf;
0032 p += scnprintf(p, bufsize - (p - buf),
0033 "SA count=%u tx=%u\n",
0034 ipsec->count, ipsec->tx);
0035
0036 for (i = 0; i < NSIM_IPSEC_MAX_SA_COUNT; i++) {
0037 struct nsim_sa *sap = &ipsec->sa[i];
0038
0039 if (!sap->used)
0040 continue;
0041
0042 p += scnprintf(p, bufsize - (p - buf),
0043 "sa[%i] %cx ipaddr=0x%08x %08x %08x %08x\n",
0044 i, (sap->rx ? 'r' : 't'), sap->ipaddr[0],
0045 sap->ipaddr[1], sap->ipaddr[2], sap->ipaddr[3]);
0046 p += scnprintf(p, bufsize - (p - buf),
0047 "sa[%i] spi=0x%08x proto=0x%x salt=0x%08x crypt=%d\n",
0048 i, be32_to_cpu(sap->xs->id.spi),
0049 sap->xs->id.proto, sap->salt, sap->crypt);
0050 p += scnprintf(p, bufsize - (p - buf),
0051 "sa[%i] key=0x%08x %08x %08x %08x\n",
0052 i, sap->key[0], sap->key[1],
0053 sap->key[2], sap->key[3]);
0054 }
0055
0056 len = simple_read_from_buffer(buffer, count, ppos, buf, p - buf);
0057
0058 kfree(buf);
0059 return len;
0060 }
0061
0062 static const struct file_operations ipsec_dbg_fops = {
0063 .owner = THIS_MODULE,
0064 .open = simple_open,
0065 .read = nsim_dbg_netdev_ops_read,
0066 };
0067
0068 static int nsim_ipsec_find_empty_idx(struct nsim_ipsec *ipsec)
0069 {
0070 u32 i;
0071
0072 if (ipsec->count == NSIM_IPSEC_MAX_SA_COUNT)
0073 return -ENOSPC;
0074
0075
0076 for (i = 0; i < NSIM_IPSEC_MAX_SA_COUNT; i++) {
0077 if (!ipsec->sa[i].used)
0078 return i;
0079 }
0080
0081 return -ENOSPC;
0082 }
0083
0084 static int nsim_ipsec_parse_proto_keys(struct xfrm_state *xs,
0085 u32 *mykey, u32 *mysalt)
0086 {
0087 const char aes_gcm_name[] = "rfc4106(gcm(aes))";
0088 struct net_device *dev = xs->xso.real_dev;
0089 unsigned char *key_data;
0090 char *alg_name = NULL;
0091 int key_len;
0092
0093 if (!xs->aead) {
0094 netdev_err(dev, "Unsupported IPsec algorithm\n");
0095 return -EINVAL;
0096 }
0097
0098 if (xs->aead->alg_icv_len != NSIM_IPSEC_AUTH_BITS) {
0099 netdev_err(dev, "IPsec offload requires %d bit authentication\n",
0100 NSIM_IPSEC_AUTH_BITS);
0101 return -EINVAL;
0102 }
0103
0104 key_data = &xs->aead->alg_key[0];
0105 key_len = xs->aead->alg_key_len;
0106 alg_name = xs->aead->alg_name;
0107
0108 if (strcmp(alg_name, aes_gcm_name)) {
0109 netdev_err(dev, "Unsupported IPsec algorithm - please use %s\n",
0110 aes_gcm_name);
0111 return -EINVAL;
0112 }
0113
0114
0115 if (key_len > NSIM_IPSEC_AUTH_BITS) {
0116 *mysalt = ((u32 *)key_data)[4];
0117 } else if (key_len == NSIM_IPSEC_AUTH_BITS) {
0118 *mysalt = 0;
0119 } else {
0120 netdev_err(dev, "IPsec hw offload only supports 128 bit keys with optional 32 bit salt\n");
0121 return -EINVAL;
0122 }
0123 memcpy(mykey, key_data, 16);
0124
0125 return 0;
0126 }
0127
0128 static int nsim_ipsec_add_sa(struct xfrm_state *xs)
0129 {
0130 struct nsim_ipsec *ipsec;
0131 struct net_device *dev;
0132 struct netdevsim *ns;
0133 struct nsim_sa sa;
0134 u16 sa_idx;
0135 int ret;
0136
0137 dev = xs->xso.real_dev;
0138 ns = netdev_priv(dev);
0139 ipsec = &ns->ipsec;
0140
0141 if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
0142 netdev_err(dev, "Unsupported protocol 0x%04x for ipsec offload\n",
0143 xs->id.proto);
0144 return -EINVAL;
0145 }
0146
0147 if (xs->calg) {
0148 netdev_err(dev, "Compression offload not supported\n");
0149 return -EINVAL;
0150 }
0151
0152
0153 ret = nsim_ipsec_find_empty_idx(ipsec);
0154 if (ret < 0) {
0155 netdev_err(dev, "No space for SA in Rx table!\n");
0156 return ret;
0157 }
0158 sa_idx = (u16)ret;
0159
0160 memset(&sa, 0, sizeof(sa));
0161 sa.used = true;
0162 sa.xs = xs;
0163
0164 if (sa.xs->id.proto & IPPROTO_ESP)
0165 sa.crypt = xs->ealg || xs->aead;
0166
0167
0168 ret = nsim_ipsec_parse_proto_keys(xs, sa.key, &sa.salt);
0169 if (ret) {
0170 netdev_err(dev, "Failed to get key data for SA table\n");
0171 return ret;
0172 }
0173
0174 if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) {
0175 sa.rx = true;
0176
0177 if (xs->props.family == AF_INET6)
0178 memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
0179 else
0180 memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
0181 }
0182
0183
0184 memcpy(&ipsec->sa[sa_idx], &sa, sizeof(sa));
0185
0186
0187
0188
0189 xs->xso.offload_handle = sa_idx | NSIM_IPSEC_VALID;
0190 ipsec->count++;
0191
0192 return 0;
0193 }
0194
0195 static void nsim_ipsec_del_sa(struct xfrm_state *xs)
0196 {
0197 struct netdevsim *ns = netdev_priv(xs->xso.real_dev);
0198 struct nsim_ipsec *ipsec = &ns->ipsec;
0199 u16 sa_idx;
0200
0201 sa_idx = xs->xso.offload_handle & ~NSIM_IPSEC_VALID;
0202 if (!ipsec->sa[sa_idx].used) {
0203 netdev_err(ns->netdev, "Invalid SA for delete sa_idx=%d\n",
0204 sa_idx);
0205 return;
0206 }
0207
0208 memset(&ipsec->sa[sa_idx], 0, sizeof(struct nsim_sa));
0209 ipsec->count--;
0210 }
0211
0212 static bool nsim_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
0213 {
0214 struct netdevsim *ns = netdev_priv(xs->xso.real_dev);
0215 struct nsim_ipsec *ipsec = &ns->ipsec;
0216
0217 ipsec->ok++;
0218
0219 return true;
0220 }
0221
0222 static const struct xfrmdev_ops nsim_xfrmdev_ops = {
0223 .xdo_dev_state_add = nsim_ipsec_add_sa,
0224 .xdo_dev_state_delete = nsim_ipsec_del_sa,
0225 .xdo_dev_offload_ok = nsim_ipsec_offload_ok,
0226 };
0227
0228 bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
0229 {
0230 struct sec_path *sp = skb_sec_path(skb);
0231 struct nsim_ipsec *ipsec = &ns->ipsec;
0232 struct xfrm_state *xs;
0233 struct nsim_sa *tsa;
0234 u32 sa_idx;
0235
0236
0237 if (!sp)
0238 return true;
0239
0240 if (unlikely(!sp->len)) {
0241 netdev_err(ns->netdev, "no xfrm state len = %d\n",
0242 sp->len);
0243 return false;
0244 }
0245
0246 xs = xfrm_input_state(skb);
0247 if (unlikely(!xs)) {
0248 netdev_err(ns->netdev, "no xfrm_input_state() xs = %p\n", xs);
0249 return false;
0250 }
0251
0252 sa_idx = xs->xso.offload_handle & ~NSIM_IPSEC_VALID;
0253 if (unlikely(sa_idx >= NSIM_IPSEC_MAX_SA_COUNT)) {
0254 netdev_err(ns->netdev, "bad sa_idx=%d max=%d\n",
0255 sa_idx, NSIM_IPSEC_MAX_SA_COUNT);
0256 return false;
0257 }
0258
0259 tsa = &ipsec->sa[sa_idx];
0260 if (unlikely(!tsa->used)) {
0261 netdev_err(ns->netdev, "unused sa_idx=%d\n", sa_idx);
0262 return false;
0263 }
0264
0265 if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
0266 netdev_err(ns->netdev, "unexpected proto=%d\n", xs->id.proto);
0267 return false;
0268 }
0269
0270 ipsec->tx++;
0271
0272 return true;
0273 }
0274
0275 void nsim_ipsec_init(struct netdevsim *ns)
0276 {
0277 ns->netdev->xfrmdev_ops = &nsim_xfrmdev_ops;
0278
0279 #define NSIM_ESP_FEATURES (NETIF_F_HW_ESP | \
0280 NETIF_F_HW_ESP_TX_CSUM | \
0281 NETIF_F_GSO_ESP)
0282
0283 ns->netdev->features |= NSIM_ESP_FEATURES;
0284 ns->netdev->hw_enc_features |= NSIM_ESP_FEATURES;
0285
0286 ns->ipsec.pfile = debugfs_create_file("ipsec", 0400,
0287 ns->nsim_dev_port->ddir, ns,
0288 &ipsec_dbg_fops);
0289 }
0290
0291 void nsim_ipsec_teardown(struct netdevsim *ns)
0292 {
0293 struct nsim_ipsec *ipsec = &ns->ipsec;
0294
0295 if (ipsec->count)
0296 netdev_err(ns->netdev, "tearing down IPsec offload with %d SAs left\n",
0297 ipsec->count);
0298 debugfs_remove_recursive(ipsec->pfile);
0299 }