@@ -24,9 +24,6 @@
#include "proto.h"
#include "skb.h"
-#define OVPN_AUTH_TAG_SIZE 16
-#define OVPN_AAD_SIZE (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE)
-
#define ALG_NAME_AES "gcm(aes)"
#define ALG_NAME_CHACHAPOLY "rfc7539(chacha20,poly1305)"
@@ -42,7 +39,7 @@ static int ovpn_aead_encap_overhead(const struct ovpn_crypto_key_slot *ks)
* an AEAD request structure with extra space for SG
* and IV.
* @tfm: the AEAD cipher handle
- * @nfrags: the number of fragments in the skb
+ * @nents: the number of scatterlist entries
*
* This function calculates the size of a contiguous memory block that includes
* the initialization vector (IV), the AEAD request, and an array of scatterlist
@@ -54,7 +51,7 @@ static int ovpn_aead_encap_overhead(const struct ovpn_crypto_key_slot *ks)
* Return: the size of the temporary memory that needs to be allocated
*/
static unsigned int ovpn_aead_crypto_tmp_size(struct crypto_aead *tfm,
- const unsigned int nfrags)
+ const unsigned int nents)
{
unsigned int len = OVPN_NONCE_SIZE;
@@ -70,8 +67,8 @@ static unsigned int ovpn_aead_crypto_tmp_size(struct crypto_aead *tfm,
/* round up to the next multiple of the scatterlist alignment */
len = ALIGN(len, __alignof__(struct scatterlist));
- /* add enough space for nfrags + 2 scatterlist entries */
- len += array_size(sizeof(struct scatterlist), nfrags + 2);
+ /* add enough space for the scatterlist entries */
+ len += array_size(sizeof(struct scatterlist), nents);
return len;
}
@@ -135,6 +132,53 @@ static struct scatterlist *ovpn_aead_crypto_req_sg(struct crypto_aead *aead,
__alignof__(struct scatterlist));
}
+static struct aead_request *ovpn_aead_request_alloc(struct crypto_aead *aead,
+ struct sk_buff *skb,
+ unsigned int nents, u8 **iv)
+{
+ struct aead_request *req;
+ void *tmp;
+
+ /* allocate IV, request and scatterlist entries in one block */
+ tmp = kmalloc(ovpn_aead_crypto_tmp_size(aead, nents), GFP_ATOMIC);
+ if (unlikely(!tmp))
+ return ERR_PTR(-ENOMEM);
+
+ ovpn_skb_cb(skb)->crypto_tmp = tmp;
+ *iv = ovpn_aead_crypto_tmp_iv(aead, tmp);
+ req = ovpn_aead_crypto_tmp_req(aead, *iv);
+
+ return req;
+}
+
+static int ovpn_aead_encrypt_header(struct ovpn_peer *peer,
+ struct ovpn_crypto_key_slot *ks,
+ u8 *iv, u8 *data)
+{
+ u32 pktid, op;
+ int ret;
+
+ /* obtain packet ID, which is used both as a first
+ * 4 bytes of nonce and last 4 bytes of associated data.
+ */
+ ret = ovpn_pktid_xmit_next(&ks->pid_xmit, &pktid);
+ if (unlikely(ret < 0))
+ return ret;
+
+ /* concat 4 bytes packet id and 8 bytes nonce tail into 12 bytes
+ * nonce
+ */
+ ovpn_pktid_aead_write(pktid, ks->nonce_tail_xmit, iv);
+
+ /* add the packet opcode and wire nonce as associated data */
+ op = ovpn_opcode_compose(OVPN_DATA_V2, ks->key_id, peer->tx_id);
+ BUILD_BUG_ON(sizeof(op) != OVPN_OPCODE_SIZE);
+ *(__force __be32 *)data = htonl(op);
+ memcpy(data + OVPN_OPCODE_SIZE, iv, OVPN_NONCE_WIRE_SIZE);
+
+ return 0;
+}
+
int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
struct sk_buff *skb)
{
@@ -143,8 +187,6 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
struct sk_buff *trailer;
struct scatterlist *sg;
int nfrags, ret;
- u32 pktid, op;
- void *tmp;
u8 *iv;
ovpn_skb_cb(skb)->peer = peer;
@@ -175,16 +217,9 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
nfrags = 1;
}
- /* allocate temporary memory for iv, sg and req */
- tmp = kmalloc(ovpn_aead_crypto_tmp_size(ks->encrypt, nfrags),
- GFP_ATOMIC);
- if (unlikely(!tmp))
- return -ENOMEM;
-
- ovpn_skb_cb(skb)->crypto_tmp = tmp;
-
- iv = ovpn_aead_crypto_tmp_iv(ks->encrypt, tmp);
- req = ovpn_aead_crypto_tmp_req(ks->encrypt, iv);
+ req = ovpn_aead_request_alloc(ks->encrypt, skb, nfrags + 2, &iv);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
sg = ovpn_aead_crypto_req_sg(ks->encrypt, req);
/* sg table:
@@ -206,28 +241,12 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
__skb_push(skb, tag_size);
sg_set_buf(sg + ret + 1, skb->data, tag_size);
- /* obtain packet ID, which is used both as a first
- * 4 bytes of nonce and last 4 bytes of associated data.
- */
- ret = ovpn_pktid_xmit_next(&ks->pid_xmit, &pktid);
+ /* make space for the additional data and push it to the front */
+ __skb_push(skb, OVPN_AAD_SIZE);
+ ret = ovpn_aead_encrypt_header(peer, ks, iv, skb->data);
if (unlikely(ret < 0))
return ret;
- /* concat 4 bytes packet id and 8 bytes nonce tail into 12 bytes
- * nonce
- */
- ovpn_pktid_aead_write(pktid, ks->nonce_tail_xmit, iv);
-
- /* make space for packet id and push it to the front */
- __skb_push(skb, OVPN_NONCE_WIRE_SIZE);
- memcpy(skb->data, iv, OVPN_NONCE_WIRE_SIZE);
-
- /* add packet op as head of additional data */
- op = ovpn_opcode_compose(OVPN_DATA_V2, ks->key_id, peer->tx_id);
- __skb_push(skb, OVPN_OPCODE_SIZE);
- BUILD_BUG_ON(sizeof(op) != OVPN_OPCODE_SIZE);
- *((__force __be32 *)skb->data) = htonl(op);
-
/* AEAD Additional data */
sg_set_buf(sg, skb->data, OVPN_AAD_SIZE);
@@ -281,7 +300,7 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
return -ENOSPC;
/* allocate temporary memory for iv, sg and req */
- tmp = kmalloc(ovpn_aead_crypto_tmp_size(ks->decrypt, nfrags),
+ tmp = kmalloc(ovpn_aead_crypto_tmp_size(ks->decrypt, nfrags + 2),
GFP_ATOMIC);
if (unlikely(!tmp))
return -ENOMEM;
@@ -11,8 +11,7 @@
#define _NET_OVPN_OVPN_H_
/* DATA_V2 header size with AEAD encryption */
-#define OVPN_HEAD_ROOM (OVPN_OPCODE_SIZE + OVPN_NONCE_WIRE_SIZE + \
- 16 /* AEAD TAG length */ + \
+#define OVPN_HEAD_ROOM (OVPN_DATA_V2_OVERHEAD + \
max(sizeof(struct udphdr), sizeof(struct tcphdr)) +\
max(sizeof(struct ipv6hdr), sizeof(struct iphdr)))
@@ -39,6 +39,10 @@
#define OVPN_NONCE_WIRE_SIZE (OVPN_NONCE_SIZE - OVPN_NONCE_TAIL_SIZE)
#define OVPN_OPCODE_SIZE 4 /* DATA_V2 opcode size */
+#define OVPN_AUTH_TAG_SIZE 16
+#define OVPN_AAD_SIZE (OVPN_OPCODE_SIZE + \
+ OVPN_NONCE_WIRE_SIZE)
+#define OVPN_DATA_V2_OVERHEAD (OVPN_AAD_SIZE + OVPN_AUTH_TAG_SIZE)
#define OVPN_OPCODE_KEYID_MASK 0x07000000
#define OVPN_OPCODE_PKTTYPE_MASK 0xF8000000
#define OVPN_OPCODE_PEERID_MASK 0x00FFFFFF