Lines Matching +full:key +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * INET An implementation of the TCP Authentication Option (TCP-AO).
23 int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8 *key, void *ctx, in tcp_ao_calc_traffic_key() argument
29 if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp->req), in tcp_ao_calc_traffic_key()
30 mkt->key, mkt->keylen)) in tcp_ao_calc_traffic_key()
33 ret = crypto_ahash_init(hp->req); in tcp_ao_calc_traffic_key()
38 ahash_request_set_crypt(hp->req, &sg, key, len); in tcp_ao_calc_traffic_key()
39 crypto_ahash_update(hp->req); in tcp_ao_calc_traffic_key()
41 ret = crypto_ahash_final(hp->req); in tcp_ao_calc_traffic_key()
47 memset(key, 0, tcp_ao_digest_size(mkt)); in tcp_ao_calc_traffic_key()
48 return 1; in tcp_ao_calc_traffic_key()
56 if (!static_branch_unlikely(&tcp_ao_needed.key)) in tcp_ao_ignore_icmp()
60 * >> A TCP-AO implementation MUST default to ignore incoming ICMPv4 in tcp_ao_ignore_icmp()
61 * messages of Type 3 (destination unreachable), Codes 2-4 (protocol in tcp_ao_ignore_icmp()
62 * unreachable, port unreachable, and fragmentation needed -- ’hard in tcp_ao_ignore_icmp()
63 * errors’), and ICMPv6 Type 1 (destination unreachable), Code 1 in tcp_ao_ignore_icmp()
65 * for connections in synchronized states (ESTABLISHED, FIN-WAIT-1, FIN- in tcp_ao_ignore_icmp()
66 * WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT) that match MKTs. in tcp_ao_ignore_icmp()
81 switch (sk->sk_state) { in tcp_ao_ignore_icmp()
83 ao = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_ignore_icmp()
95 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_ignore_icmp()
98 if (ao && !ao->accept_icmps) { in tcp_ao_ignore_icmp()
101 atomic64_inc(&ao->counters.dropped_icmp); in tcp_ao_ignore_icmp()
115 struct tcp_ao_key *key; in tcp_ao_established_key() local
117 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_established_key()
118 if ((sndid >= 0 && key->sndid != sndid) || in tcp_ao_established_key()
119 (rcvid >= 0 && key->rcvid != rcvid)) in tcp_ao_established_key()
121 return key; in tcp_ao_established_key()
132 __be32 a1 = addr1->s_addr & mask; in ipv4_prefix_cmp()
133 __be32 a2 = addr2->s_addr & mask; in ipv4_prefix_cmp()
140 static int __tcp_ao_key_cmp(const struct tcp_ao_key *key, int l3index, in __tcp_ao_key_cmp() argument
144 if (sndid >= 0 && key->sndid != sndid) in __tcp_ao_key_cmp()
145 return (key->sndid > sndid) ? 1 : -1; in __tcp_ao_key_cmp()
146 if (rcvid >= 0 && key->rcvid != rcvid) in __tcp_ao_key_cmp()
147 return (key->rcvid > rcvid) ? 1 : -1; in __tcp_ao_key_cmp()
148 if (l3index >= 0 && (key->keyflags & TCP_AO_KEYF_IFINDEX)) { in __tcp_ao_key_cmp()
149 if (key->l3index != l3index) in __tcp_ao_key_cmp()
150 return (key->l3index > l3index) ? 1 : -1; in __tcp_ao_key_cmp()
155 if (key->family != family) in __tcp_ao_key_cmp()
156 return (key->family > family) ? 1 : -1; in __tcp_ao_key_cmp()
159 if (ntohl(key->addr.a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
161 if (ntohl(addr->a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
163 return ipv4_prefix_cmp(&key->addr.a4, &addr->a4, prefixlen); in __tcp_ao_key_cmp()
166 if (ipv6_addr_any(&key->addr.a6) || ipv6_addr_any(&addr->a6)) in __tcp_ao_key_cmp()
168 if (ipv6_prefix_equal(&key->addr.a6, &addr->a6, prefixlen)) in __tcp_ao_key_cmp()
170 return memcmp(&key->addr.a6, &addr->a6, sizeof(addr->a6)); in __tcp_ao_key_cmp()
173 return -1; in __tcp_ao_key_cmp()
176 static int tcp_ao_key_cmp(const struct tcp_ao_key *key, int l3index, in tcp_ao_key_cmp() argument
181 if (family == AF_INET6 && ipv6_addr_v4mapped(&addr->a6)) { in tcp_ao_key_cmp()
182 __be32 addr4 = addr->a6.s6_addr32[3]; in tcp_ao_key_cmp()
184 return __tcp_ao_key_cmp(key, l3index, in tcp_ao_key_cmp()
189 return __tcp_ao_key_cmp(key, l3index, addr, in tcp_ao_key_cmp()
197 struct tcp_ao_key *key; in __tcp_ao_do_lookup() local
200 if (!static_branch_unlikely(&tcp_ao_needed.key)) in __tcp_ao_do_lookup()
203 ao = rcu_dereference_check(tcp_sk(sk)->ao_info, in __tcp_ao_do_lookup()
208 hlist_for_each_entry_rcu(key, &ao->head, node) { in __tcp_ao_do_lookup()
209 u8 prefixlen = min(prefix, key->prefixlen); in __tcp_ao_do_lookup()
211 if (!tcp_ao_key_cmp(key, l3index, addr, prefixlen, in __tcp_ao_do_lookup()
213 return key; in __tcp_ao_do_lookup()
232 INIT_HLIST_HEAD(&ao->head); in tcp_ao_alloc_info()
233 refcount_set(&ao->refcnt, 1); in tcp_ao_alloc_info()
240 hlist_add_head_rcu(&mkt->node, &ao->head); in tcp_ao_link_mkt()
244 struct tcp_ao_key *key) in tcp_ao_copy_key() argument
248 new_key = sock_kmalloc(sk, tcp_ao_sizeof_key(key), in tcp_ao_copy_key()
253 *new_key = *key; in tcp_ao_copy_key()
254 INIT_HLIST_NODE(&new_key->node); in tcp_ao_copy_key()
255 tcp_sigpool_get(new_key->tcp_sigpool_id); in tcp_ao_copy_key()
256 atomic64_set(&new_key->pkt_good, 0); in tcp_ao_copy_key()
257 atomic64_set(&new_key->pkt_bad, 0); in tcp_ao_copy_key()
264 struct tcp_ao_key *key = container_of(head, struct tcp_ao_key, rcu); in tcp_ao_key_free_rcu() local
266 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_key_free_rcu()
267 kfree_sensitive(key); in tcp_ao_key_free_rcu()
273 struct tcp_ao_key *key; in tcp_ao_info_free_rcu() local
276 hlist_for_each_entry_safe(key, n, &ao->head, node) { in tcp_ao_info_free_rcu()
277 hlist_del(&key->node); in tcp_ao_info_free_rcu()
278 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_info_free_rcu()
279 kfree_sensitive(key); in tcp_ao_info_free_rcu()
288 struct tcp_ao_key *key; in tcp_ao_sk_omem_free() local
290 hlist_for_each_entry(key, &ao->head, node) in tcp_ao_sk_omem_free()
291 total_ao_sk_mem += tcp_ao_sizeof_key(key); in tcp_ao_sk_omem_free()
292 atomic_sub(total_ao_sk_mem, &sk->sk_omem_alloc); in tcp_ao_sk_omem_free()
300 ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
301 rcu_assign_pointer(tcp_twsk(sk)->ao_info, NULL); in tcp_ao_destroy_sock()
303 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
304 rcu_assign_pointer(tcp_sk(sk)->ao_info, NULL); in tcp_ao_destroy_sock()
307 if (!ao || !refcount_dec_and_test(&ao->refcnt)) in tcp_ao_destroy_sock()
312 call_rcu(&ao->rcu, tcp_ao_info_free_rcu); in tcp_ao_destroy_sock()
317 struct tcp_ao_info *ao_info = rcu_dereference_protected(tp->ao_info, 1); in tcp_ao_time_wait()
320 struct tcp_ao_key *key; in tcp_ao_time_wait() local
324 hlist_for_each_entry_safe(key, n, &ao_info->head, node) { in tcp_ao_time_wait()
325 omem += tcp_ao_sizeof_key(key); in tcp_ao_time_wait()
328 refcount_inc(&ao_info->refcnt); in tcp_ao_time_wait()
329 atomic_sub(omem, &(((struct sock *)tp)->sk_omem_alloc)); in tcp_ao_time_wait()
330 rcu_assign_pointer(tcptw->ao_info, ao_info); in tcp_ao_time_wait()
332 tcptw->ao_info = NULL; in tcp_ao_time_wait()
337 static int tcp_v4_ao_calc_key(struct tcp_ao_key *mkt, u8 *key, in tcp_v4_ao_calc_key() argument
342 /* See RFC5926 3.1.1 */ in tcp_v4_ao_calc_key()
352 err = tcp_sigpool_start(mkt->tcp_sigpool_id, &hp); in tcp_v4_ao_calc_key()
357 tmp->counter = 1; in tcp_v4_ao_calc_key()
358 memcpy(tmp->label, "TCP-AO", 6); in tcp_v4_ao_calc_key()
359 tmp->ctx.saddr = saddr; in tcp_v4_ao_calc_key()
360 tmp->ctx.daddr = daddr; in tcp_v4_ao_calc_key()
361 tmp->ctx.sport = sport; in tcp_v4_ao_calc_key()
362 tmp->ctx.dport = dport; in tcp_v4_ao_calc_key()
363 tmp->ctx.sisn = sisn; in tcp_v4_ao_calc_key()
364 tmp->ctx.disn = disn; in tcp_v4_ao_calc_key()
365 tmp->outlen = htons(tcp_ao_digest_size(mkt) * 8); /* in bits */ in tcp_v4_ao_calc_key()
367 err = tcp_ao_calc_traffic_key(mkt, key, tmp, sizeof(*tmp), &hp); in tcp_v4_ao_calc_key()
373 int tcp_v4_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, in tcp_v4_ao_calc_key_sk() argument
378 return tcp_v4_ao_calc_key(mkt, key, sk->sk_rcv_saddr, in tcp_v4_ao_calc_key_sk()
379 sk->sk_daddr, htons(sk->sk_num), in tcp_v4_ao_calc_key_sk()
380 sk->sk_dport, sisn, disn); in tcp_v4_ao_calc_key_sk()
382 return tcp_v4_ao_calc_key(mkt, key, sk->sk_daddr, in tcp_v4_ao_calc_key_sk()
383 sk->sk_rcv_saddr, sk->sk_dport, in tcp_v4_ao_calc_key_sk()
384 htons(sk->sk_num), disn, sisn); in tcp_v4_ao_calc_key_sk()
387 static int tcp_ao_calc_key_sk(struct tcp_ao_key *mkt, u8 *key, in tcp_ao_calc_key_sk() argument
391 if (mkt->family == AF_INET) in tcp_ao_calc_key_sk()
392 return tcp_v4_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); in tcp_ao_calc_key_sk()
394 else if (mkt->family == AF_INET6) in tcp_ao_calc_key_sk()
395 return tcp_v6_ao_calc_key_sk(mkt, key, sk, sisn, disn, send); in tcp_ao_calc_key_sk()
398 return -EOPNOTSUPP; in tcp_ao_calc_key_sk()
401 int tcp_v4_ao_calc_key_rsk(struct tcp_ao_key *mkt, u8 *key, in tcp_v4_ao_calc_key_rsk() argument
406 return tcp_v4_ao_calc_key(mkt, key, in tcp_v4_ao_calc_key_rsk()
407 ireq->ir_loc_addr, ireq->ir_rmt_addr, in tcp_v4_ao_calc_key_rsk()
408 htons(ireq->ir_num), ireq->ir_rmt_port, in tcp_v4_ao_calc_key_rsk()
409 htonl(tcp_rsk(req)->snt_isn), in tcp_v4_ao_calc_key_rsk()
410 htonl(tcp_rsk(req)->rcv_isn)); in tcp_v4_ao_calc_key_rsk()
413 static int tcp_v4_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, in tcp_v4_ao_calc_key_skb() argument
420 return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, in tcp_v4_ao_calc_key_skb()
421 th->source, th->dest, sisn, disn); in tcp_v4_ao_calc_key_skb()
424 static int tcp_ao_calc_key_skb(struct tcp_ao_key *mkt, u8 *key, in tcp_ao_calc_key_skb() argument
429 return tcp_v4_ao_calc_key_skb(mkt, key, skb, sisn, disn); in tcp_ao_calc_key_skb()
432 return tcp_v6_ao_calc_key_skb(mkt, key, skb, sisn, disn); in tcp_ao_calc_key_skb()
434 return -EAFNOSUPPORT; in tcp_ao_calc_key_skb()
444 bp = hp->scratch; in tcp_v4_ao_hash_pseudoheader()
445 bp->saddr = saddr; in tcp_v4_ao_hash_pseudoheader()
446 bp->daddr = daddr; in tcp_v4_ao_hash_pseudoheader()
447 bp->pad = 0; in tcp_v4_ao_hash_pseudoheader()
448 bp->protocol = IPPROTO_TCP; in tcp_v4_ao_hash_pseudoheader()
449 bp->len = cpu_to_be16(nbytes); in tcp_v4_ao_hash_pseudoheader()
452 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_v4_ao_hash_pseudoheader()
453 return crypto_ahash_update(hp->req); in tcp_v4_ao_hash_pseudoheader()
464 if (!th->check) { in tcp_ao_hash_pseudoheader()
466 return tcp_v4_ao_hash_pseudoheader(hp, sk->sk_daddr, in tcp_ao_hash_pseudoheader()
467 sk->sk_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
470 return tcp_v6_ao_hash_pseudoheader(hp, &sk->sk_v6_daddr, in tcp_ao_hash_pseudoheader()
471 &sk->sk_v6_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
474 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
480 return tcp_v4_ao_hash_pseudoheader(hp, iph->daddr, in tcp_ao_hash_pseudoheader()
481 iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
486 return tcp_v6_ao_hash_pseudoheader(hp, &iph->daddr, in tcp_ao_hash_pseudoheader()
487 &iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
490 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
499 sne--; in tcp_ao_compute_sne()
509 * @hp - used for hashing
510 * @sne - sne value
517 bp = (__be32 *)hp->scratch; in tcp_ao_hash_sne()
521 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_ao_hash_sne()
522 return crypto_ahash_update(hp->req); in tcp_ao_hash_sne()
531 u8 *hdr = hp->scratch; in tcp_ao_hash_header()
539 (u8 *)th + hash_offset - sizeof(struct tcp_ao_hdr), in tcp_ao_hash_header()
543 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
545 len = th->doff << 2; in tcp_ao_hash_header()
547 /* zero out tcp-ao hash */ in tcp_ao_hash_header()
548 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
553 ahash_request_set_crypt(hp->req, &sg, NULL, len); in tcp_ao_hash_header()
554 err = crypto_ahash_update(hp->req); in tcp_ao_hash_header()
560 struct tcp_ao_key *key, const u8 *tkey, in tcp_ao_hash_hdr() argument
565 int tkey_len = tcp_ao_digest_size(key); in tcp_ao_hash_hdr()
566 int hash_offset = ao_hash - (char *)th; in tcp_ao_hash_hdr()
574 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_hdr()
586 if (tcp_v4_ao_hash_pseudoheader(&hp, daddr->a4.s_addr, in tcp_ao_hash_hdr()
587 saddr->a4.s_addr, th->doff * 4)) in tcp_ao_hash_hdr()
591 if (tcp_v6_ao_hash_pseudoheader(&hp, &daddr->a6, in tcp_ao_hash_hdr()
592 &saddr->a6, th->doff * 4)) in tcp_ao_hash_hdr()
596 WARN_ON_ONCE(1); in tcp_ao_hash_hdr()
600 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_hdr()
601 ao_hash, hash_offset, tcp_ao_maclen(key))) in tcp_ao_hash_hdr()
607 memcpy(ao_hash, hash_buf, tcp_ao_maclen(key)); in tcp_ao_hash_hdr()
615 memset(ao_hash, 0, tcp_ao_maclen(key)); in tcp_ao_hash_hdr()
617 return 1; in tcp_ao_hash_hdr()
621 char *ao_hash, struct tcp_ao_key *key, in tcp_ao_hash_skb() argument
626 int tkey_len = tcp_ao_digest_size(key); in tcp_ao_hash_skb()
634 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_skb()
646 if (tcp_ao_hash_pseudoheader(family, sk, skb, &hp, skb->len)) in tcp_ao_hash_skb()
649 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_skb()
650 ao_hash, hash_offset, tcp_ao_maclen(key))) in tcp_ao_hash_skb()
652 if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2)) in tcp_ao_hash_skb()
658 memcpy(ao_hash, hash_buf, tcp_ao_maclen(key)); in tcp_ao_hash_skb()
666 memset(ao_hash, 0, tcp_ao_maclen(key)); in tcp_ao_hash_skb()
668 return 1; in tcp_ao_hash_skb()
671 int tcp_v4_ao_hash_skb(char *ao_hash, struct tcp_ao_key *key, in tcp_v4_ao_hash_skb() argument
675 return tcp_ao_hash_skb(AF_INET, ao_hash, key, sk, skb, in tcp_v4_ao_hash_skb()
688 return -ENOMEM; in tcp_v4_ao_synack_hash()
706 union tcp_ao_addr *addr = (union tcp_ao_addr *)&ireq->ir_rmt_addr; in tcp_v4_ao_lookup_rsk()
709 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); in tcp_v4_ao_lookup_rsk()
717 addr_sk->sk_bound_dev_if); in tcp_v4_ao_lookup()
718 union tcp_ao_addr *addr = (union tcp_ao_addr *)&addr_sk->sk_daddr; in tcp_v4_ao_lookup()
725 struct tcp_ao_key **key, char **traffic_key, in tcp_ao_prepare_reset() argument
732 /* If there's no socket - than initial sisn/disn are unknown. in tcp_ao_prepare_reset()
736 * Linux TCP-AO support provides TCP_AO_ADD_KEY and TCP_AO_REPAIR in tcp_ao_prepare_reset()
737 * options to restore a socket post-reboot. in tcp_ao_prepare_reset()
740 return -ENOTCONN; in tcp_ao_prepare_reset()
742 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { in tcp_ao_prepare_reset()
743 unsigned int family = READ_ONCE(sk->sk_family); in tcp_ao_prepare_reset()
747 if (sk->sk_state == TCP_NEW_SYN_RECV) { in tcp_ao_prepare_reset()
750 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_prepare_reset()
751 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_prepare_reset()
752 *sne = tcp_ao_compute_sne(0, tcp_rsk(req)->snt_isn, seq); in tcp_ao_prepare_reset()
754 sisn = th->seq; in tcp_ao_prepare_reset()
758 addr = (union tcp_md5_addr *)&ipv6_hdr(skb)->saddr; in tcp_ao_prepare_reset()
760 addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; in tcp_ao_prepare_reset()
762 if (family == AF_INET6 && ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_prepare_reset()
767 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
769 return -ENOENT; in tcp_ao_prepare_reset()
770 *key = tcp_ao_do_lookup(sk, l3index, addr, family, in tcp_ao_prepare_reset()
771 -1, aoh->rnext_keyid); in tcp_ao_prepare_reset()
772 if (!*key) in tcp_ao_prepare_reset()
773 return -ENOENT; in tcp_ao_prepare_reset()
774 *traffic_key = kmalloc(tcp_ao_digest_size(*key), GFP_ATOMIC); in tcp_ao_prepare_reset()
776 return -ENOMEM; in tcp_ao_prepare_reset()
778 if (tcp_ao_calc_key_skb(*key, *traffic_key, skb, in tcp_ao_prepare_reset()
780 return -1; in tcp_ao_prepare_reset()
781 *keyid = (*key)->rcvid; in tcp_ao_prepare_reset()
786 if (sk->sk_state == TCP_TIME_WAIT) { in tcp_ao_prepare_reset()
787 ao_info = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_prepare_reset()
788 snd_basis = tcp_twsk(sk)->tw_snd_nxt; in tcp_ao_prepare_reset()
790 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
791 snd_basis = tcp_sk(sk)->snd_una; in tcp_ao_prepare_reset()
794 return -ENOENT; in tcp_ao_prepare_reset()
796 *key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); in tcp_ao_prepare_reset()
797 if (!*key) in tcp_ao_prepare_reset()
798 return -ENOENT; in tcp_ao_prepare_reset()
799 *traffic_key = snd_other_key(*key); in tcp_ao_prepare_reset()
800 rnext_key = READ_ONCE(ao_info->rnext_key); in tcp_ao_prepare_reset()
801 *keyid = rnext_key->rcvid; in tcp_ao_prepare_reset()
802 *sne = tcp_ao_compute_sne(READ_ONCE(ao_info->snd_sne), in tcp_ao_prepare_reset()
809 struct tcp_ao_key *key, struct tcphdr *th, in tcp_ao_transmit_skb() argument
819 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_transmit_skb()
821 traffic_key = snd_other_key(key); in tcp_ao_transmit_skb()
822 if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) { in tcp_ao_transmit_skb()
825 if (!(tcb->tcp_flags & TCPHDR_ACK)) { in tcp_ao_transmit_skb()
827 tkey_buf = kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); in tcp_ao_transmit_skb()
829 return -ENOMEM; in tcp_ao_transmit_skb()
832 disn = ao->risn; in tcp_ao_transmit_skb()
834 tp->af_specific->ao_calc_key_sk(key, traffic_key, in tcp_ao_transmit_skb()
835 sk, ao->lisn, disn, true); in tcp_ao_transmit_skb()
837 sne = tcp_ao_compute_sne(READ_ONCE(ao->snd_sne), READ_ONCE(tp->snd_una), in tcp_ao_transmit_skb()
838 ntohl(th->seq)); in tcp_ao_transmit_skb()
839 tp->af_specific->calc_ao_hash(hash_location, key, sk, skb, traffic_key, in tcp_ao_transmit_skb()
840 hash_location - (u8 *)th, sne); in tcp_ao_transmit_skb()
853 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
859 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
870 struct tcp_ao_key *key; in tcp_ao_syncookie() local
873 /* treq->af_specific is used to perform TCP_AO lookup in tcp_ao_syncookie()
878 treq->af_specific = &tcp_request_sock_ipv6_ops; in tcp_ao_syncookie()
881 treq->af_specific = &tcp_request_sock_ipv4_ops; in tcp_ao_syncookie()
883 treq->used_tcp_ao = false; in tcp_ao_syncookie()
888 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), inet_rsk(req)->ir_iif); in tcp_ao_syncookie()
889 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_ao_syncookie()
890 if (!key) in tcp_ao_syncookie()
891 /* Key not found, continue without TCP-AO */ in tcp_ao_syncookie()
894 treq->ao_rcv_next = aoh->keyid; in tcp_ao_syncookie()
895 treq->ao_keyid = aoh->rnext_keyid; in tcp_ao_syncookie()
896 treq->used_tcp_ao = true; in tcp_ao_syncookie()
902 const struct tcp_ao_hdr *aoh, struct tcp_ao_key *key, in tcp_ao_verify_hash() argument
909 if (maclen != tcp_ao_maclen(key)) { in tcp_ao_verify_hash()
911 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
912 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
913 trace_tcp_ao_wrong_maclen(sk, skb, aoh->keyid, in tcp_ao_verify_hash()
914 aoh->rnext_keyid, maclen); in tcp_ao_verify_hash()
918 hash_buf = kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); in tcp_ao_verify_hash()
922 /* XXX: make it per-AF callback? */ in tcp_ao_verify_hash()
923 tcp_ao_hash_skb(family, hash_buf, key, sk, skb, traffic_key, in tcp_ao_verify_hash()
924 (phash - (u8 *)th), sne); in tcp_ao_verify_hash()
927 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
928 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
929 trace_tcp_ao_mismatch(sk, skb, aoh->keyid, in tcp_ao_verify_hash()
930 aoh->rnext_keyid, maclen); in tcp_ao_verify_hash()
935 atomic64_inc(&info->counters.pkt_good); in tcp_ao_verify_hash()
936 atomic64_inc(&key->pkt_good); in tcp_ao_verify_hash()
948 u8 *phash = (u8 *)(aoh + 1); /* hash goes just after the header */ in tcp_inbound_ao_hash()
951 struct tcp_ao_key *key; in tcp_inbound_ao_hash() local
957 info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_inbound_ao_hash()
960 trace_tcp_ao_key_not_found(sk, skb, aoh->keyid, in tcp_inbound_ao_hash()
961 aoh->rnext_keyid, maclen); in tcp_inbound_ao_hash()
965 if (unlikely(th->syn)) { in tcp_inbound_ao_hash()
966 sisn = th->seq; in tcp_inbound_ao_hash()
970 state = READ_ONCE(sk->sk_state); in tcp_inbound_ao_hash()
971 /* Fast-path */ in tcp_inbound_ao_hash()
972 if (likely((1 << state) & TCP_AO_ESTABLISHED)) { in tcp_inbound_ao_hash()
977 * packet. If not we lookup the key based on the keyid in tcp_inbound_ao_hash()
980 key = READ_ONCE(info->rnext_key); in tcp_inbound_ao_hash()
981 if (key->rcvid != aoh->keyid) { in tcp_inbound_ao_hash()
982 key = tcp_ao_established_key(info, -1, aoh->keyid); in tcp_inbound_ao_hash()
983 if (!key) in tcp_inbound_ao_hash()
988 if (unlikely(th->syn && !th->ack)) in tcp_inbound_ao_hash()
991 sne = tcp_ao_compute_sne(info->rcv_sne, tcp_sk(sk)->rcv_nxt, in tcp_inbound_ao_hash()
992 ntohl(th->seq)); in tcp_inbound_ao_hash()
993 /* Established socket, traffic key are cached */ in tcp_inbound_ao_hash()
994 traffic_key = rcv_other_key(key); in tcp_inbound_ao_hash()
995 err = tcp_ao_verify_hash(sk, skb, family, info, aoh, key, in tcp_inbound_ao_hash()
999 current_key = READ_ONCE(info->current_key); in tcp_inbound_ao_hash()
1000 /* Key rotation: the peer asks us to use new key (RNext) */ in tcp_inbound_ao_hash()
1001 if (unlikely(aoh->rnext_keyid != current_key->sndid)) { in tcp_inbound_ao_hash()
1002 trace_tcp_ao_rnext_request(sk, skb, current_key->sndid, in tcp_inbound_ao_hash()
1003 aoh->rnext_keyid, in tcp_inbound_ao_hash()
1005 /* If the key is not found we do nothing. */ in tcp_inbound_ao_hash()
1006 key = tcp_ao_established_key(info, aoh->rnext_keyid, -1); in tcp_inbound_ao_hash()
1007 if (key) in tcp_inbound_ao_hash()
1009 WRITE_ONCE(info->current_key, key); in tcp_inbound_ao_hash()
1017 /* Lookup key based on peer address and keyid. in tcp_inbound_ao_hash()
1020 * - request sockets would race on those key pointers in tcp_inbound_ao_hash()
1021 * - tcp_ao_del_cmd() allows async key removal in tcp_inbound_ao_hash()
1023 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_inbound_ao_hash()
1024 if (!key) in tcp_inbound_ao_hash()
1027 if (th->syn && !th->ack) in tcp_inbound_ao_hash()
1030 if ((1 << state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { in tcp_inbound_ao_hash()
1033 sne = tcp_ao_compute_sne(0, tcp_rsk(req)->rcv_isn, in tcp_inbound_ao_hash()
1034 ntohl(th->seq)); in tcp_inbound_ao_hash()
1035 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_inbound_ao_hash()
1036 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_inbound_ao_hash()
1037 } else if (unlikely(th->ack && !th->syn)) { in tcp_inbound_ao_hash()
1039 sisn = htonl(ntohl(th->seq) - 1); in tcp_inbound_ao_hash()
1040 disn = htonl(ntohl(th->ack_seq) - 1); in tcp_inbound_ao_hash()
1042 ntohl(th->seq)); in tcp_inbound_ao_hash()
1043 } else if (unlikely(!th->syn)) { in tcp_inbound_ao_hash()
1044 /* no way to figure out initial sisn/disn - drop */ in tcp_inbound_ao_hash()
1047 } else if ((1 << state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { in tcp_inbound_ao_hash()
1048 disn = info->lisn; in tcp_inbound_ao_hash()
1049 if (th->syn || th->rst) in tcp_inbound_ao_hash()
1050 sisn = th->seq; in tcp_inbound_ao_hash()
1052 sisn = info->risn; in tcp_inbound_ao_hash()
1054 WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", state); in tcp_inbound_ao_hash()
1058 traffic_key = kmalloc(tcp_ao_digest_size(key), GFP_ATOMIC); in tcp_inbound_ao_hash()
1061 tcp_ao_calc_key_skb(key, traffic_key, skb, sisn, disn, family); in tcp_inbound_ao_hash()
1062 ret = tcp_ao_verify_hash(sk, skb, family, info, aoh, key, in tcp_inbound_ao_hash()
1069 atomic64_inc(&info->counters.key_not_found); in tcp_inbound_ao_hash()
1070 trace_tcp_ao_key_not_found(sk, skb, aoh->keyid, in tcp_inbound_ao_hash()
1071 aoh->rnext_keyid, maclen); in tcp_inbound_ao_hash()
1083 ao->lisn, ao->risn, true); in tcp_ao_cache_traffic_keys()
1089 ao->lisn, ao->risn, false); in tcp_ao_cache_traffic_keys()
1099 struct tcp_ao_key *key; in tcp_ao_connect_init() local
1102 ao_info = rcu_dereference_protected(tp->ao_info, in tcp_ao_connect_init()
1108 family = sk->sk_family; in tcp_ao_connect_init()
1110 addr = (union tcp_ao_addr *)&sk->sk_daddr; in tcp_ao_connect_init()
1113 addr = (union tcp_ao_addr *)&sk->sk_v6_daddr; in tcp_ao_connect_init()
1118 sk->sk_bound_dev_if); in tcp_ao_connect_init()
1120 hlist_for_each_entry_safe(key, next, &ao_info->head, node) { in tcp_ao_connect_init()
1121 if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_connect_init()
1124 if (key == ao_info->current_key) in tcp_ao_connect_init()
1125 ao_info->current_key = NULL; in tcp_ao_connect_init()
1126 if (key == ao_info->rnext_key) in tcp_ao_connect_init()
1127 ao_info->rnext_key = NULL; in tcp_ao_connect_init()
1128 hlist_del_rcu(&key->node); in tcp_ao_connect_init()
1129 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_connect_init()
1130 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_connect_init()
1133 key = tp->af_specific->ao_lookup(sk, sk, -1, -1); in tcp_ao_connect_init()
1134 if (key) { in tcp_ao_connect_init()
1136 * use the first key matching the peer in tcp_ao_connect_init()
1138 if (!ao_info->current_key) in tcp_ao_connect_init()
1139 ao_info->current_key = key; in tcp_ao_connect_init()
1140 if (!ao_info->rnext_key) in tcp_ao_connect_init()
1141 ao_info->rnext_key = key; in tcp_ao_connect_init()
1142 tp->tcp_header_len += tcp_ao_len_aligned(key); in tcp_ao_connect_init()
1144 ao_info->lisn = htonl(tp->write_seq); in tcp_ao_connect_init()
1145 ao_info->snd_sne = 0; in tcp_ao_connect_init()
1148 * at least one tcp-ao key that matches the remote peer. in tcp_ao_connect_init()
1150 WARN_ON_ONCE(1); in tcp_ao_connect_init()
1151 rcu_assign_pointer(tp->ao_info, NULL); in tcp_ao_connect_init()
1159 struct tcp_ao_key *key; in tcp_ao_established() local
1161 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_established()
1166 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_established()
1167 tcp_ao_cache_traffic_keys(sk, ao, key); in tcp_ao_established()
1173 struct tcp_ao_key *key; in tcp_ao_finish_connect() local
1175 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_finish_connect()
1180 WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); in tcp_ao_finish_connect()
1181 ao->rcv_sne = 0; in tcp_ao_finish_connect()
1183 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_finish_connect()
1184 tcp_ao_cache_traffic_keys(sk, ao, key); in tcp_ao_finish_connect()
1191 struct tcp_ao_key *key, *new_key, *first_key; in tcp_ao_copy_all_matching() local
1194 int l3index, ret = -ENOMEM; in tcp_ao_copy_all_matching()
1198 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_copy_all_matching()
1202 /* New socket without TCP-AO on it */ in tcp_ao_copy_all_matching()
1208 return -ENOMEM; in tcp_ao_copy_all_matching()
1209 new_ao->lisn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_copy_all_matching()
1210 new_ao->risn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_copy_all_matching()
1211 new_ao->ao_required = ao->ao_required; in tcp_ao_copy_all_matching()
1212 new_ao->accept_icmps = ao->accept_icmps; in tcp_ao_copy_all_matching()
1215 addr = (union tcp_ao_addr *)&newsk->sk_daddr; in tcp_ao_copy_all_matching()
1218 addr = (union tcp_ao_addr *)&newsk->sk_v6_daddr; in tcp_ao_copy_all_matching()
1221 ret = -EAFNOSUPPORT; in tcp_ao_copy_all_matching()
1225 newsk->sk_bound_dev_if); in tcp_ao_copy_all_matching()
1227 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_copy_all_matching()
1228 if (tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_copy_all_matching()
1231 new_key = tcp_ao_copy_key(newsk, key); in tcp_ao_copy_all_matching()
1241 /* RFC5925 (7.4.1) specifies that the TCP-AO status in tcp_ao_copy_all_matching()
1243 * At this point the connection was TCP-AO enabled, so in tcp_ao_copy_all_matching()
1244 * it can't switch to being unsigned if peer's key in tcp_ao_copy_all_matching()
1247 ret = -EKEYREJECTED; in tcp_ao_copy_all_matching()
1251 if (!static_key_fast_inc_not_disabled(&tcp_ao_needed.key.key)) { in tcp_ao_copy_all_matching()
1252 ret = -EUSERS; in tcp_ao_copy_all_matching()
1256 key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); in tcp_ao_copy_all_matching()
1259 key = tcp_ao_established_key(new_ao, tcp_rsk(req)->ao_keyid, -1); in tcp_ao_copy_all_matching()
1260 if (key) in tcp_ao_copy_all_matching()
1261 new_ao->current_key = key; in tcp_ao_copy_all_matching()
1263 new_ao->current_key = first_key; in tcp_ao_copy_all_matching()
1266 key = tcp_ao_established_key(new_ao, -1, tcp_rsk(req)->ao_rcv_next); in tcp_ao_copy_all_matching()
1267 if (key) in tcp_ao_copy_all_matching()
1268 new_ao->rnext_key = key; in tcp_ao_copy_all_matching()
1270 new_ao->rnext_key = first_key; in tcp_ao_copy_all_matching()
1273 rcu_assign_pointer(tcp_sk(newsk)->ao_info, new_ao); in tcp_ao_copy_all_matching()
1278 hlist_for_each_entry_safe(key, key_head, &new_ao->head, node) { in tcp_ao_copy_all_matching()
1279 hlist_del(&key->node); in tcp_ao_copy_all_matching()
1280 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_copy_all_matching()
1281 atomic_sub(tcp_ao_sizeof_key(key), &newsk->sk_omem_alloc); in tcp_ao_copy_all_matching()
1282 kfree_sensitive(key); in tcp_ao_copy_all_matching()
1292 if (sk->sk_state == TCP_LISTEN) in tcp_ao_can_set_current_rnext()
1300 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd->addr; in tcp_ao_verify_ipv4()
1303 if (sin->sin_family != AF_INET) in tcp_ao_verify_ipv4()
1304 return -EINVAL; in tcp_ao_verify_ipv4()
1307 if (sin->sin_port != 0) in tcp_ao_verify_ipv4()
1308 return -EINVAL; in tcp_ao_verify_ipv4()
1311 if (cmd->prefix != 0) { in tcp_ao_verify_ipv4()
1314 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY) in tcp_ao_verify_ipv4()
1315 return -EINVAL; in tcp_ao_verify_ipv4()
1316 if (cmd->prefix > 32) in tcp_ao_verify_ipv4()
1317 return -EINVAL; in tcp_ao_verify_ipv4()
1319 mask = inet_make_mask(cmd->prefix); in tcp_ao_verify_ipv4()
1320 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_verify_ipv4()
1321 return -EINVAL; in tcp_ao_verify_ipv4()
1324 if (ntohl(inet->inet_daddr) != INADDR_ANY && in tcp_ao_verify_ipv4()
1325 (inet->inet_daddr & mask) != sin->sin_addr.s_addr) in tcp_ao_verify_ipv4()
1326 return -EINVAL; in tcp_ao_verify_ipv4()
1328 if (ntohl(sin->sin_addr.s_addr) != INADDR_ANY) in tcp_ao_verify_ipv4()
1329 return -EINVAL; in tcp_ao_verify_ipv4()
1332 *addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_verify_ipv4()
1336 static int tcp_ao_parse_crypto(struct tcp_ao_add *cmd, struct tcp_ao_key *key) in tcp_ao_parse_crypto() argument
1346 if (!strcmp("cmac(aes128)", cmd->alg_name)) { in tcp_ao_parse_crypto()
1347 strscpy(cmd->alg_name, "cmac(aes)", sizeof(cmd->alg_name)); in tcp_ao_parse_crypto()
1348 is_kdf_aes_128_cmac = (cmd->keylen != 16); in tcp_ao_parse_crypto()
1349 tmp_key = kmalloc(cmd->keylen, GFP_KERNEL); in tcp_ao_parse_crypto()
1351 return -ENOMEM; in tcp_ao_parse_crypto()
1354 key->maclen = cmd->maclen ?: 12; /* 12 is the default in RFC5925 */ in tcp_ao_parse_crypto()
1356 /* Check: maclen + tcp-ao header <= (MAX_TCP_OPTION_SPACE - mss in tcp_ao_parse_crypto()
1357 * - tstamp (including sackperm) in tcp_ao_parse_crypto()
1358 * - wscale), in tcp_ao_parse_crypto()
1361 * In order to allow D-SACK with TCP-AO, the header size should be: in tcp_ao_parse_crypto()
1362 * (MAX_TCP_OPTION_SPACE - TCPOLEN_TSTAMP_ALIGNED in tcp_ao_parse_crypto()
1363 * - TCPOLEN_SACK_BASE_ALIGNED in tcp_ao_parse_crypto()
1364 * - 2 * TCPOLEN_SACK_PERBLOCK) = 8 (maclen = 4), in tcp_ao_parse_crypto()
1368 * Typical MACs are 96-128 bits (12-16 bytes), but any length in tcp_ao_parse_crypto()
1373 * TCP-AO continues to consume 16 bytes in non-SYN segments, in tcp_ao_parse_crypto()
1377 * such as to handle D-SACK, a smaller TCP-AO MAC would be required in tcp_ao_parse_crypto()
1379 * bytes for the D-SACK variant of the SACK option) [RFC2883]. in tcp_ao_parse_crypto()
1380 * Note that D-SACK is not supportable in TCP MD5 in the presence in tcp_ao_parse_crypto()
1385 syn_tcp_option_space -= TCPOLEN_MSS_ALIGNED; in tcp_ao_parse_crypto()
1386 syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED; in tcp_ao_parse_crypto()
1387 syn_tcp_option_space -= TCPOLEN_WSCALE_ALIGNED; in tcp_ao_parse_crypto()
1388 if (tcp_ao_len_aligned(key) > syn_tcp_option_space) { in tcp_ao_parse_crypto()
1389 err = -EMSGSIZE; in tcp_ao_parse_crypto()
1393 key->keylen = cmd->keylen; in tcp_ao_parse_crypto()
1394 memcpy(key->key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1396 err = tcp_sigpool_start(key->tcp_sigpool_id, &hp); in tcp_ao_parse_crypto()
1405 memcpy(tmp_key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1406 sg_init_one(&sg, tmp_key, cmd->keylen); in tcp_ao_parse_crypto()
1408 /* Using zero-key of 16 bytes as described in RFC5926 */ in tcp_ao_parse_crypto()
1418 ahash_request_set_crypt(hp.req, &sg, key->key, cmd->keylen); in tcp_ao_parse_crypto()
1426 key->keylen = 16; in tcp_ao_parse_crypto()
1429 err = crypto_ahash_setkey(tfm, key->key, key->keylen); in tcp_ao_parse_crypto()
1436 if (tcp_ao_maclen(key) > key->digest_size) in tcp_ao_parse_crypto()
1437 return -EINVAL; in tcp_ao_parse_crypto()
1453 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd->addr; in tcp_ao_verify_ipv6()
1454 struct in6_addr *addr = &sin6->sin6_addr; in tcp_ao_verify_ipv6()
1455 u8 prefix = cmd->prefix; in tcp_ao_verify_ipv6()
1457 if (sin6->sin6_family != AF_INET6) in tcp_ao_verify_ipv6()
1458 return -EINVAL; in tcp_ao_verify_ipv6()
1461 if (sin6->sin6_port != 0) in tcp_ao_verify_ipv6()
1462 return -EINVAL; in tcp_ao_verify_ipv6()
1465 if (cmd->prefix != 0 && ipv6_addr_v4mapped(addr)) { in tcp_ao_verify_ipv6()
1466 __be32 addr4 = addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1470 return -EINVAL; in tcp_ao_verify_ipv6()
1474 return -EINVAL; in tcp_ao_verify_ipv6()
1477 if (!ipv6_addr_any(&sk->sk_v6_daddr)) { in tcp_ao_verify_ipv6()
1478 __be32 daddr4 = sk->sk_v6_daddr.s6_addr32[3]; in tcp_ao_verify_ipv6()
1480 if (!ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_verify_ipv6()
1481 return -EINVAL; in tcp_ao_verify_ipv6()
1483 return -EINVAL; in tcp_ao_verify_ipv6()
1486 *paddr = (union tcp_ao_addr *)&addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1489 } else if (cmd->prefix != 0) { in tcp_ao_verify_ipv6()
1493 return -EINVAL; in tcp_ao_verify_ipv6()
1497 return -EINVAL; in tcp_ao_verify_ipv6()
1500 if (!ipv6_addr_any(&sk->sk_v6_daddr) && in tcp_ao_verify_ipv6()
1501 !ipv6_prefix_equal(&sk->sk_v6_daddr, addr, prefix)) in tcp_ao_verify_ipv6()
1503 return -EINVAL; in tcp_ao_verify_ipv6()
1506 return -EINVAL; in tcp_ao_verify_ipv6()
1517 return -EOPNOTSUPP; in tcp_ao_verify_ipv6()
1524 return rcu_dereference_protected(tcp_sk(sk)->ao_info, in setsockopt_ao_info()
1526 } else if (sk->sk_state == TCP_TIME_WAIT) { in setsockopt_ao_info()
1527 return rcu_dereference_protected(tcp_twsk(sk)->ao_info, in setsockopt_ao_info()
1530 return ERR_PTR(-ESOCKTNOSUPPORT); in setsockopt_ao_info()
1536 return rcu_dereference(tcp_sk(sk)->ao_info); in getsockopt_ao_info()
1537 else if (sk->sk_state == TCP_TIME_WAIT) in getsockopt_ao_info()
1538 return rcu_dereference(tcp_twsk(sk)->ao_info); in getsockopt_ao_info()
1540 return ERR_PTR(-ESOCKTNOSUPPORT); in getsockopt_ao_info()
1549 const char *algo = cmd->alg_name; in tcp_ao_key_alloc()
1552 struct tcp_ao_key *key; in tcp_ao_key_alloc() local
1557 /* Force null-termination of alg_name */ in tcp_ao_key_alloc()
1558 cmd->alg_name[ARRAY_SIZE(cmd->alg_name) - 1] = '\0'; in tcp_ao_key_alloc()
1564 /* Full TCP header (th->doff << 2) should fit into scratch area, in tcp_ao_key_alloc()
1579 size = sizeof(struct tcp_ao_key) + (digest_size << 1); in tcp_ao_key_alloc()
1580 key = sock_kmalloc(sk, size, GFP_KERNEL); in tcp_ao_key_alloc()
1581 if (!key) { in tcp_ao_key_alloc()
1582 err = -ENOMEM; in tcp_ao_key_alloc()
1586 key->tcp_sigpool_id = pool_id; in tcp_ao_key_alloc()
1587 key->digest_size = digest_size; in tcp_ao_key_alloc()
1588 return key; in tcp_ao_key_alloc()
1600 struct tcp_ao_key *key; in tcp_ao_add_cmd() local
1606 return -EINVAL; in tcp_ao_add_cmd()
1613 return -EINVAL; in tcp_ao_add_cmd()
1616 return -EINVAL; in tcp_ao_add_cmd()
1626 return -EINVAL; in tcp_ao_add_cmd()
1630 return -EINVAL; in tcp_ao_add_cmd()
1634 return -EINVAL; in tcp_ao_add_cmd()
1636 /* For cmd.tcp_ifindex = 0 the key will apply to the default VRF */ in tcp_ao_add_cmd()
1638 int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); in tcp_ao_add_cmd()
1644 l3index = dev->ifindex; in tcp_ao_add_cmd()
1648 return -EINVAL; in tcp_ao_add_cmd()
1652 * non peer-matching key on an established TCP-AO in tcp_ao_add_cmd()
1655 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_add_cmd()
1656 return -EINVAL; in tcp_ao_add_cmd()
1660 * re-bind to a different dev (with CAP_NET_RAW). in tcp_ao_add_cmd()
1665 net_warn_ratelimited("AO key ifindex %d != sk bound ifindex %d\n", in tcp_ao_add_cmd()
1669 /* Don't allow keys for peers that have a matching TCP-MD5 key */ in tcp_ao_add_cmd()
1671 /* Non-_exact version of tcp_md5_do_lookup() will in tcp_ao_add_cmd()
1673 * (that will make them match AO key with in tcp_ao_add_cmd()
1674 * sysctl_tcp_l3dev_accept = 1 in tcp_ao_add_cmd()
1677 return -EKEYREJECTED; in tcp_ao_add_cmd()
1680 return -EKEYREJECTED; in tcp_ao_add_cmd()
1690 return -ENOMEM; in tcp_ao_add_cmd()
1694 * existing key for the peer, RFC5925 3.1: in tcp_ao_add_cmd()
1698 if (__tcp_ao_do_lookup(sk, l3index, addr, family, cmd.prefix, -1, cmd.rcvid)) in tcp_ao_add_cmd()
1699 return -EEXIST; in tcp_ao_add_cmd()
1701 cmd.prefix, cmd.sndid, -1)) in tcp_ao_add_cmd()
1702 return -EEXIST; in tcp_ao_add_cmd()
1705 key = tcp_ao_key_alloc(sk, &cmd); in tcp_ao_add_cmd()
1706 if (IS_ERR(key)) { in tcp_ao_add_cmd()
1707 ret = PTR_ERR(key); in tcp_ao_add_cmd()
1711 INIT_HLIST_NODE(&key->node); in tcp_ao_add_cmd()
1712 memcpy(&key->addr, addr, (family == AF_INET) ? sizeof(struct in_addr) : in tcp_ao_add_cmd()
1714 key->prefixlen = cmd.prefix; in tcp_ao_add_cmd()
1715 key->family = family; in tcp_ao_add_cmd()
1716 key->keyflags = cmd.keyflags; in tcp_ao_add_cmd()
1717 key->sndid = cmd.sndid; in tcp_ao_add_cmd()
1718 key->rcvid = cmd.rcvid; in tcp_ao_add_cmd()
1719 key->l3index = l3index; in tcp_ao_add_cmd()
1720 atomic64_set(&key->pkt_good, 0); in tcp_ao_add_cmd()
1721 atomic64_set(&key->pkt_bad, 0); in tcp_ao_add_cmd()
1723 ret = tcp_ao_parse_crypto(&cmd, key); in tcp_ao_add_cmd()
1727 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) { in tcp_ao_add_cmd()
1728 tcp_ao_cache_traffic_keys(sk, ao_info, key); in tcp_ao_add_cmd()
1730 ao_info->current_key = key; in tcp_ao_add_cmd()
1731 ao_info->rnext_key = key; in tcp_ao_add_cmd()
1735 tcp_ao_link_mkt(ao_info, key); in tcp_ao_add_cmd()
1737 if (!static_branch_inc(&tcp_ao_needed.key)) { in tcp_ao_add_cmd()
1738 ret = -EUSERS; in tcp_ao_add_cmd()
1742 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_add_cmd()
1746 WRITE_ONCE(ao_info->current_key, key); in tcp_ao_add_cmd()
1748 WRITE_ONCE(ao_info->rnext_key, key); in tcp_ao_add_cmd()
1752 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_add_cmd()
1753 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_add_cmd()
1754 kfree_sensitive(key); in tcp_ao_add_cmd()
1762 bool del_async, struct tcp_ao_key *key, in tcp_ao_delete_key() argument
1768 hlist_del_rcu(&key->node); in tcp_ao_delete_key()
1775 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1776 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1780 /* At this moment another CPU could have looked this key up in tcp_ao_delete_key()
1782 * after which the key is off-list and can't be looked up again; in tcp_ao_delete_key()
1785 * Free the key with next RCU grace period (in case it was in tcp_ao_delete_key()
1787 * changed it in forced-delete). in tcp_ao_delete_key()
1791 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_delete_key()
1793 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_delete_key()
1795 if (unlikely(READ_ONCE(ao_info->current_key) == key || in tcp_ao_delete_key()
1796 READ_ONCE(ao_info->rnext_key) == key)) { in tcp_ao_delete_key()
1797 err = -EBUSY; in tcp_ao_delete_key()
1801 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1802 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1806 hlist_add_head_rcu(&key->node, &ao_info->head); in tcp_ao_delete_key()
1814 struct tcp_ao_key *key, *new_current = NULL, *new_rnext = NULL; in tcp_ao_del_cmd() local
1823 return -EINVAL; in tcp_ao_del_cmd()
1830 return -EINVAL; in tcp_ao_del_cmd()
1834 return -EINVAL; in tcp_ao_del_cmd()
1838 return -EINVAL; in tcp_ao_del_cmd()
1843 * if there is no key for that ifindex. in tcp_ao_del_cmd()
1846 return -EINVAL; in tcp_ao_del_cmd()
1852 return -ENOENT; in tcp_ao_del_cmd()
1860 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_del_cmd()
1862 return -ENOENT; in tcp_ao_del_cmd()
1865 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_del_cmd()
1867 return -ENOENT; in tcp_ao_del_cmd()
1869 if (cmd.del_async && sk->sk_state != TCP_LISTEN) in tcp_ao_del_cmd()
1870 return -EINVAL; in tcp_ao_del_cmd()
1875 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_del_cmd()
1877 port = ntohs(sin->sin_port); in tcp_ao_del_cmd()
1880 struct in6_addr *addr6 = &sin6->sin6_addr; in tcp_ao_del_cmd()
1883 addr = (union tcp_ao_addr *)&addr6->s6_addr32[3]; in tcp_ao_del_cmd()
1890 port = ntohs(sin6->sin6_port); in tcp_ao_del_cmd()
1896 return -EINVAL; in tcp_ao_del_cmd()
1898 /* We could choose random present key here for current/rnext in tcp_ao_del_cmd()
1900 * allow removing a key that's in use. RFC5925 doesn't in tcp_ao_del_cmd()
1901 * specify how-to coordinate key removal, but says: in tcp_ao_del_cmd()
1905 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_del_cmd()
1906 if (cmd.sndid != key->sndid || in tcp_ao_del_cmd()
1907 cmd.rcvid != key->rcvid) in tcp_ao_del_cmd()
1910 if (family != key->family || in tcp_ao_del_cmd()
1911 prefix != key->prefixlen || in tcp_ao_del_cmd()
1912 memcmp(addr, &key->addr, addr_len)) in tcp_ao_del_cmd()
1916 (key->keyflags & TCP_AO_KEYF_IFINDEX)) in tcp_ao_del_cmd()
1919 if (key->l3index != l3index) in tcp_ao_del_cmd()
1922 if (key == new_current || key == new_rnext) in tcp_ao_del_cmd()
1925 return tcp_ao_delete_key(sk, ao_info, cmd.del_async, key, in tcp_ao_del_cmd()
1928 return -ENOENT; in tcp_ao_del_cmd()
1931 /* cmd.ao_required makes a socket TCP-AO only.
1934 * ao_info->ao_required on inbound tcp segment fast-path.
1941 if (!static_branch_unlikely(&tcp_md5_needed.key)) in tcp_ao_required_verify()
1944 md5sig = rcu_dereference_check(tcp_sk(sk)->md5sig_info, in tcp_ao_required_verify()
1949 if (rcu_dereference_check(hlist_first_rcu(&md5sig->head), in tcp_ao_required_verify()
1951 return 1; in tcp_ao_required_verify()
1966 return -EINVAL; in tcp_ao_info_cmd()
1974 return -EINVAL; in tcp_ao_info_cmd()
1978 return -EINVAL; in tcp_ao_info_cmd()
1984 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_info_cmd()
1985 return -EINVAL; in tcp_ao_info_cmd()
1988 return -ENOMEM; in tcp_ao_info_cmd()
1993 err = -EKEYREJECTED; in tcp_ao_info_cmd()
2003 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_info_cmd()
2005 err = -ENOENT; in tcp_ao_info_cmd()
2010 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_info_cmd()
2012 err = -ENOENT; in tcp_ao_info_cmd()
2017 atomic64_set(&ao_info->counters.pkt_good, cmd.pkt_good); in tcp_ao_info_cmd()
2018 atomic64_set(&ao_info->counters.pkt_bad, cmd.pkt_bad); in tcp_ao_info_cmd()
2019 atomic64_set(&ao_info->counters.key_not_found, cmd.pkt_key_not_found); in tcp_ao_info_cmd()
2020 atomic64_set(&ao_info->counters.ao_required, cmd.pkt_ao_required); in tcp_ao_info_cmd()
2021 atomic64_set(&ao_info->counters.dropped_icmp, cmd.pkt_dropped_icmp); in tcp_ao_info_cmd()
2024 ao_info->ao_required = cmd.ao_required; in tcp_ao_info_cmd()
2025 ao_info->accept_icmps = cmd.accept_icmps; in tcp_ao_info_cmd()
2027 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_info_cmd()
2029 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_info_cmd()
2031 if (!static_branch_inc(&tcp_ao_needed.key)) { in tcp_ao_info_cmd()
2032 err = -EUSERS; in tcp_ao_info_cmd()
2036 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_info_cmd()
2049 return -EAFNOSUPPORT; in tcp_parse_ao()
2059 WARN_ON_ONCE(1); in tcp_parse_ao()
2060 return -EINVAL; in tcp_parse_ao()
2096 * (ksize - usize) are interpreted as 0 by the kernel.
2098 * older kernel. The trailing bytes unknown to the kernel (usize - ksize)
2099 * are checked to ensure they are zeroed, otherwise -E2BIG is returned.
2108 struct tcp_ao_key *key, *current_key; in tcp_ao_copy_mkts_to_user() local
2120 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2123 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2132 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2134 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2136 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2139 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2142 l3index = (opt_in.keyflags & TCP_AO_KEYF_IFINDEX) ? opt_in.ifindex : -1; in tcp_ao_copy_mkts_to_user()
2146 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2156 port = sin->sin_port; in tcp_ao_copy_mkts_to_user()
2157 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_copy_mkts_to_user()
2160 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2162 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY && in tcp_ao_copy_mkts_to_user()
2164 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2167 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_copy_mkts_to_user()
2168 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2177 addr = (union tcp_ao_addr *)&sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2178 addr6 = &sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2179 port = sin6->sin6_port; in tcp_ao_copy_mkts_to_user()
2182 * ipv6_addr_v4mapped() like in key adding: in tcp_ao_copy_mkts_to_user()
2187 __be32 mask, addr4 = addr6->s6_addr32[3]; in tcp_ao_copy_mkts_to_user()
2191 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2194 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2200 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2204 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2207 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2216 return -EAFNOSUPPORT; in tcp_ao_copy_mkts_to_user()
2222 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2224 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2229 /* May change in RX, while we're dumping, pre-fetch it */ in tcp_ao_copy_mkts_to_user()
2230 current_key = READ_ONCE(ao_info->current_key); in tcp_ao_copy_mkts_to_user()
2232 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_copy_mkts_to_user()
2237 if (opt_in.is_current && key == current_key) in tcp_ao_copy_mkts_to_user()
2239 if (opt_in.is_rnext && key == ao_info->rnext_key) in tcp_ao_copy_mkts_to_user()
2244 if (tcp_ao_key_cmp(key, l3index, addr, opt_in.prefix, in tcp_ao_copy_mkts_to_user()
2255 if (key->family == AF_INET) { in tcp_ao_copy_mkts_to_user()
2258 sin_out->sin_family = key->family; in tcp_ao_copy_mkts_to_user()
2259 sin_out->sin_port = 0; in tcp_ao_copy_mkts_to_user()
2260 memcpy(&sin_out->sin_addr, &key->addr, sizeof(struct in_addr)); in tcp_ao_copy_mkts_to_user()
2264 sin6_out->sin6_family = key->family; in tcp_ao_copy_mkts_to_user()
2265 sin6_out->sin6_port = 0; in tcp_ao_copy_mkts_to_user()
2266 memcpy(&sin6_out->sin6_addr, &key->addr, sizeof(struct in6_addr)); in tcp_ao_copy_mkts_to_user()
2268 opt_out.sndid = key->sndid; in tcp_ao_copy_mkts_to_user()
2269 opt_out.rcvid = key->rcvid; in tcp_ao_copy_mkts_to_user()
2270 opt_out.prefix = key->prefixlen; in tcp_ao_copy_mkts_to_user()
2271 opt_out.keyflags = key->keyflags; in tcp_ao_copy_mkts_to_user()
2272 opt_out.is_current = (key == current_key); in tcp_ao_copy_mkts_to_user()
2273 opt_out.is_rnext = (key == ao_info->rnext_key); in tcp_ao_copy_mkts_to_user()
2275 opt_out.maclen = key->maclen; in tcp_ao_copy_mkts_to_user()
2276 opt_out.keylen = key->keylen; in tcp_ao_copy_mkts_to_user()
2277 opt_out.ifindex = key->l3index; in tcp_ao_copy_mkts_to_user()
2278 opt_out.pkt_good = atomic64_read(&key->pkt_good); in tcp_ao_copy_mkts_to_user()
2279 opt_out.pkt_bad = atomic64_read(&key->pkt_bad); in tcp_ao_copy_mkts_to_user()
2280 memcpy(&opt_out.key, key->key, key->keylen); in tcp_ao_copy_mkts_to_user()
2281 tcp_sigpool_algo(key->tcp_sigpool_id, opt_out.alg_name, 64); in tcp_ao_copy_mkts_to_user()
2283 /* Copy key to user */ in tcp_ao_copy_mkts_to_user()
2286 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2292 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2297 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2310 return -ENOENT; in tcp_ao_get_mkts()
2323 return -EFAULT; in tcp_ao_get_sock_info()
2326 return -EINVAL; in tcp_ao_get_sock_info()
2337 return -EINVAL; in tcp_ao_get_sock_info()
2343 return -ENOENT; in tcp_ao_get_sock_info()
2346 out.ao_required = ao->ao_required; in tcp_ao_get_sock_info()
2347 out.accept_icmps = ao->accept_icmps; in tcp_ao_get_sock_info()
2348 out.pkt_good = atomic64_read(&ao->counters.pkt_good); in tcp_ao_get_sock_info()
2349 out.pkt_bad = atomic64_read(&ao->counters.pkt_bad); in tcp_ao_get_sock_info()
2350 out.pkt_key_not_found = atomic64_read(&ao->counters.key_not_found); in tcp_ao_get_sock_info()
2351 out.pkt_ao_required = atomic64_read(&ao->counters.ao_required); in tcp_ao_get_sock_info()
2352 out.pkt_dropped_icmp = atomic64_read(&ao->counters.dropped_icmp); in tcp_ao_get_sock_info()
2354 current_key = READ_ONCE(ao->current_key); in tcp_ao_get_sock_info()
2356 out.set_current = 1; in tcp_ao_get_sock_info()
2357 out.current_key = current_key->sndid; in tcp_ao_get_sock_info()
2359 if (ao->rnext_key) { in tcp_ao_get_sock_info()
2360 out.set_rnext = 1; in tcp_ao_get_sock_info()
2361 out.rnext = ao->rnext_key->rcvid; in tcp_ao_get_sock_info()
2365 return -EFAULT; in tcp_ao_get_sock_info()
2374 struct tcp_ao_key *key; in tcp_ao_set_repair() local
2379 return -EINVAL; in tcp_ao_set_repair()
2385 if (!tp->repair) in tcp_ao_set_repair()
2386 return -EPERM; in tcp_ao_set_repair()
2392 return -ENOENT; in tcp_ao_set_repair()
2394 WRITE_ONCE(ao->lisn, cmd.snt_isn); in tcp_ao_set_repair()
2395 WRITE_ONCE(ao->risn, cmd.rcv_isn); in tcp_ao_set_repair()
2396 WRITE_ONCE(ao->snd_sne, cmd.snd_sne); in tcp_ao_set_repair()
2397 WRITE_ONCE(ao->rcv_sne, cmd.rcv_sne); in tcp_ao_set_repair()
2399 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_set_repair()
2400 tcp_ao_cache_traffic_keys(sk, ao, key); in tcp_ao_set_repair()
2413 return -EFAULT; in tcp_ao_get_repair()
2416 return -EINVAL; in tcp_ao_get_repair()
2418 if (!tp->repair) in tcp_ao_get_repair()
2419 return -EPERM; in tcp_ao_get_repair()
2425 return ao ? PTR_ERR(ao) : -ENOENT; in tcp_ao_get_repair()
2428 opt.snt_isn = ao->lisn; in tcp_ao_get_repair()
2429 opt.rcv_isn = ao->risn; in tcp_ao_get_repair()
2430 opt.snd_sne = READ_ONCE(ao->snd_sne); in tcp_ao_get_repair()
2431 opt.rcv_sne = READ_ONCE(ao->rcv_sne); in tcp_ao_get_repair()
2435 return -EFAULT; in tcp_ao_get_repair()