net: fastopen: robustness and endianness fixes for SipHash
[linux-2.6-microblaze.git] / net / ipv4 / tcp_fastopen.c
index f918599..3fd4512 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/tcp.h>
 #include <linux/rcupdate.h>
 #include <linux/rculist.h>
-#include <linux/siphash.h>
 #include <net/inetpeer.h>
 #include <net/tcp.h>
 
@@ -31,7 +30,7 @@ void tcp_fastopen_init_key_once(struct net *net)
         * for a valid cookie, so this is an acceptable risk.
         */
        get_random_bytes(key, sizeof(key));
-       tcp_fastopen_reset_cipher(net, NULL, key, NULL, sizeof(key));
+       tcp_fastopen_reset_cipher(net, NULL, key, NULL);
 }
 
 static void tcp_fastopen_ctx_free(struct rcu_head *head)
@@ -68,8 +67,7 @@ void tcp_fastopen_ctx_destroy(struct net *net)
 }
 
 int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
-                             void *primary_key, void *backup_key,
-                             unsigned int len)
+                             void *primary_key, void *backup_key)
 {
        struct tcp_fastopen_context *ctx, *octx;
        struct fastopen_queue *q;
@@ -81,9 +79,11 @@ int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
                goto out;
        }
 
-       memcpy(ctx->key[0], primary_key, len);
+       ctx->key[0].key[0] = get_unaligned_le64(primary_key);
+       ctx->key[0].key[1] = get_unaligned_le64(primary_key + 8);
        if (backup_key) {
-               memcpy(ctx->key[1], backup_key, len);
+               ctx->key[1].key[0] = get_unaligned_le64(backup_key);
+               ctx->key[1].key[1] = get_unaligned_le64(backup_key + 8);
                ctx->num = 2;
        } else {
                ctx->num = 1;
@@ -110,19 +110,18 @@ out:
 
 static bool __tcp_fastopen_cookie_gen_cipher(struct request_sock *req,
                                             struct sk_buff *syn,
-                                            const u8 *key,
+                                            const siphash_key_t *key,
                                             struct tcp_fastopen_cookie *foc)
 {
-       BUILD_BUG_ON(TCP_FASTOPEN_KEY_LENGTH != sizeof(siphash_key_t));
        BUILD_BUG_ON(TCP_FASTOPEN_COOKIE_SIZE != sizeof(u64));
 
        if (req->rsk_ops->family == AF_INET) {
                const struct iphdr *iph = ip_hdr(syn);
 
-               foc->val[0] = siphash(&iph->saddr,
-                                     sizeof(iph->saddr) +
-                                     sizeof(iph->daddr),
-                                     (const siphash_key_t *)key);
+               foc->val[0] = cpu_to_le64(siphash(&iph->saddr,
+                                         sizeof(iph->saddr) +
+                                         sizeof(iph->daddr),
+                                         key));
                foc->len = TCP_FASTOPEN_COOKIE_SIZE;
                return true;
        }
@@ -130,10 +129,10 @@ static bool __tcp_fastopen_cookie_gen_cipher(struct request_sock *req,
        if (req->rsk_ops->family == AF_INET6) {
                const struct ipv6hdr *ip6h = ipv6_hdr(syn);
 
-               foc->val[0] = siphash(&ip6h->saddr,
-                                     sizeof(ip6h->saddr) +
-                                     sizeof(ip6h->daddr),
-                                     (const siphash_key_t *)key);
+               foc->val[0] = cpu_to_le64(siphash(&ip6h->saddr,
+                                         sizeof(ip6h->saddr) +
+                                         sizeof(ip6h->daddr),
+                                         key));
                foc->len = TCP_FASTOPEN_COOKIE_SIZE;
                return true;
        }
@@ -154,7 +153,7 @@ static void tcp_fastopen_cookie_gen(struct sock *sk,
        rcu_read_lock();
        ctx = tcp_fastopen_get_ctx(sk);
        if (ctx)
-               __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->key[0], foc);
+               __tcp_fastopen_cookie_gen_cipher(req, syn, &ctx->key[0], foc);
        rcu_read_unlock();
 }
 
@@ -218,7 +217,7 @@ static int tcp_fastopen_cookie_gen_check(struct sock *sk,
        if (!ctx)
                goto out;
        for (i = 0; i < tcp_fastopen_context_len(ctx); i++) {
-               __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->key[i], foc);
+               __tcp_fastopen_cookie_gen_cipher(req, syn, &ctx->key[i], foc);
                if (tcp_fastopen_cookie_match(foc, orig)) {
                        ret = i + 1;
                        goto out;