Re: [PATCH] net/rxrpc: Fix a use after free in rxrpc_input_packet

2021-04-01 Thread David Howells
Lv Yunlong  wrote:

> In the case RXRPC_PACKET_TYPE_DATA of rxrpc_input_packet, if
> skb_unshare(skb,..) failed, it will free the skb and return NULL.
> But if skb_unshare() return NULL, the freed skb will be used by
> rxrpc_eaten_skb(skb,..).

That's not precisely the case:

void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(&rxrpc_n_rx_skbs);
trace_rxrpc_skb(skb, op, 0, n, 0, here);
}

The only thing that happens to skb here is that it's passed to
trace_rxrpc_skb(), but that doesn't dereference it either.  The *address* is
used for display purposes, but that's all.

> I see that rxrpc_eaten_skb() is used to drop a ref of skb.

It isn't.

> As the skb is already freed in skb_unshare() on error, my patch removes the
> rxrpc_eaten_skb() to avoid the uaf.

But you remove the accounting, which might lead to an assertion failure in
af_rxrpc_exit().

That said, rxrpc_eaten_skb() should probably decrement rxrpc_n_rx_skbs, not
increment it...

David



Re: [RESEND net-next] rxrpc: Fix dependency on IPv6 in udp tunnel config

2021-02-12 Thread David Howells
Vadim Fedorenko  wrote:

> As udp_port_cfg struct changes its members with dependency on IPv6
> configuration, the code in rxrpc should also check for IPv6.
> 
> Fixes: 1a9b86c9fd95 ("rxrpc: use udp tunnel APIs instead of open code in 
> rxrpc_open_socket")
> Reported-by: kernel test robot 
> Signed-off-by: Vadim Fedorenko 

Looks reasonable.

Acked-by: David Howells 



[PATCH net-next] rxrpc: Fix missing dependency on NET_UDP_TUNNEL

2021-02-09 Thread David Howells
The changes to make rxrpc create the udp socket missed a bit to add the
Kconfig dependency on the udp tunnel code to do this.

Fix this by adding making AF_RXRPC select NET_UDP_TUNNEL.

Fixes: 1a9b86c9fd95 ("rxrpc: use udp tunnel APIs instead of open code in 
rxrpc_open_socket")
Reported-by: kernel test robot 
Signed-off-by: Vadim Fedorenko 
Signed-off-by: David Howells 
Reviewed-by: Xin Long 
cc: a...@dev.mellanox.co.il
cc: Jakub Kicinski 
---

 net/rxrpc/Kconfig |1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig
index d706bb408365..0885b22e5c0e 100644
--- a/net/rxrpc/Kconfig
+++ b/net/rxrpc/Kconfig
@@ -8,6 +8,7 @@ config AF_RXRPC
depends on INET
select CRYPTO
select KEYS
+   select NET_UDP_TUNNEL
help
  Say Y or M here to include support for RxRPC session sockets (just
  the transport part, not the presentation part: (un)marshalling is




[RFC PATCH net] rxrpc: Fix missing dependency on NET_UDP_TUNNEL

2021-02-09 Thread David Howells
The changes to make rxrpc create the udp socket missed a bit to add the
Kconfig dependency on the udp tunnel code to do this.

Fix this by adding making AF_RXRPC select NET_UDP_TUNNEL.

Fixes: 1a9b86c9fd95 ("rxrpc: use udp tunnel APIs instead of open code in 
rxrpc_open_socket")
Reported-by: kernel test robot 
Suggested-by: Vadim Fedorenko 
Signed-off-by: David Howells 
cc: Xin Long 
cc: a...@dev.mellanox.co.il
cc: Jakub Kicinski 
---

 net/rxrpc/Kconfig |1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig
index d706bb408365..0885b22e5c0e 100644
--- a/net/rxrpc/Kconfig
+++ b/net/rxrpc/Kconfig
@@ -8,6 +8,7 @@ config AF_RXRPC
depends on INET
select CRYPTO
select KEYS
+   select NET_UDP_TUNNEL
help
  Say Y or M here to include support for RxRPC session sockets (just
  the transport part, not the presentation part: (un)marshalling is




Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO

2021-02-05 Thread David Howells
Xin Long  wrote:

> Subject: [PATCH net-next] rxrpc: use udp tunnel APIs instead of open code in
>  rxrpc_open_socket
> 
> Signed-off-by: Xin Long 

You can add "Acked-by: David Howells " if you want.

David



Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO

2021-02-04 Thread David Howells
Xin Long  wrote:

> > If you could arrange for a random port to be assigned in such a case (and
> > indicated back to the caller), that would be awesome.  Possibly I just don't
> > need to actually use bind in this case.
> >
> The patch is attached (based on this patch):

Initial testing seems to show that it works.  I'll poke at it some more
tomorrow.

David



Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO

2021-02-03 Thread David Howells
Xin Long  wrote:

> BTW: do you have any testing for this?

If you're using a distro like a recent-ish Fedora or, I think, Debian, you
should be able to install a kafs-client package.  If that works, start the
afs.mount service with systemctl and then look in /afs.  You should see
directories corresponding to a bunch of places that you can try accessing.  I
recommend you try "ls /afs/openafs.org".

If you don't have that available, if you have the keyutils package installed,
you can try:

mount -t afs %openafs.org:root.cell /mnt

then do "ls /mnt".

David



Re: [PATCHv5 net-next 2/2] rxrpc: call udp_tunnel_encap_enable in rxrpc_open_socket

2021-02-03 Thread David Howells
Xin Long  wrote:

> When doing encap_enable/increasing encap_needed_key, up->encap_enabled
> is not set in rxrpc_open_socket(), and it will cause encap_needed_key
> not being decreased in udpv6_destroy_sock().
> 
> This patch is to improve it by just calling udp_tunnel_encap_enable()
> where it increases both UDP and UDPv6 encap_needed_key and sets
> up->encap_enabled.
> 
> v4->v5:
>   - add the missing '#include ', as David Howells
> noticed.
> 
> Acked-and-tested-by: David Howells 
> Signed-off-by: Xin Long 

Looks good.

David



Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO

2021-02-03 Thread David Howells
Xin Long  wrote:

> BTW, I'm also thinking to use udp_sock_create(), the only problem I can
> see is it may not do bind() in rxrpc_open_socket(), is that true? or we
> can actually bind to some address when a local address is not supplied?

If a local address isn't explicitly bound to the AF_RXRPC socket, binding the
UDP socket to a random local port is fine.  In fact, sometimes I want to
explicitly bind an rxrpc server socket to a random port.  See fs/afs/rxrpc.c
function afs_open_socket():

/* bind the callback manager's address to make this a server socket */
memset(&srx, 0, sizeof(srx));
srx.srx_family  = AF_RXRPC;
srx.srx_service = CM_SERVICE;
srx.transport_type  = SOCK_DGRAM;
srx.transport_len   = sizeof(srx.transport.sin6);
srx.transport.sin6.sin6_family  = AF_INET6;
srx.transport.sin6.sin6_port= htons(AFS_CM_PORT);
...
ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
if (ret == -EADDRINUSE) {
srx.transport.sin6.sin6_port = 0;

^^^ That's hoping to get a random port bound.

ret = kernel_bind(socket, (struct sockaddr *) &srx, 
sizeof(srx));
}
if (ret < 0)
goto error_2;

The client cache manager server socket here is used to receive notifications
back from the fileserver.  There's a standard port (7001) for the service, but
if that's in use, we can use any other port.  The fileserver grabs the source
port from incoming RPC requests - and then uses that when sending 3rd-party
change notifications back.

If you could arrange for a random port to be assigned in such a case (and
indicated back to the caller), that would be awesome.  Possibly I just don't
need to actually use bind in this case.

David



[PATCH net] rxrpc: Fix clearance of Tx/Rx ring when releasing a call

2021-02-03 Thread David Howells
At the end of rxrpc_release_call(), rxrpc_cleanup_ring() is called to clear
the Rx/Tx skbuff ring, but this doesn't lock the ring whilst it's accessing
it.  Unfortunately, rxrpc_resend() might be trying to retransmit a packet
concurrently with this - and whilst it does lock the ring, this isn't
protection against rxrpc_cleanup_call().

Fix this by removing the call to rxrpc_cleanup_ring() from
rxrpc_release_call().  rxrpc_cleanup_ring() will be called again anyway
from rxrpc_cleanup_call().  The earlier call is just an optimisation to
recycle skbuffs more quickly.

Alternative solutions include rxrpc_release_call() could try to cancel the
work item or wait for it to complete or rxrpc_cleanup_ring() could lock
when accessing the ring (which would require a bh lock).

This can produce a report like the following:

  BUG: KASAN: use-after-free in rxrpc_send_data_packet+0x19b4/0x1e70 
net/rxrpc/output.c:372
  Read of size 4 at addr 888011606e04 by task kworker/0:0/5
  ...
  Workqueue: krxrpcd rxrpc_process_call
  Call Trace:
   ...
   kasan_report.cold+0x79/0xd5 mm/kasan/report.c:413
   rxrpc_send_data_packet+0x19b4/0x1e70 net/rxrpc/output.c:372
   rxrpc_resend net/rxrpc/call_event.c:266 [inline]
   rxrpc_process_call+0x1634/0x1f60 net/rxrpc/call_event.c:412
   process_one_work+0x98d/0x15f0 kernel/workqueue.c:2275
   ...

  Allocated by task 2318:
   ...
   sock_alloc_send_pskb+0x793/0x920 net/core/sock.c:2348
   rxrpc_send_data+0xb51/0x2bf0 net/rxrpc/sendmsg.c:358
   rxrpc_do_sendmsg+0xc03/0x1350 net/rxrpc/sendmsg.c:744
   rxrpc_sendmsg+0x420/0x630 net/rxrpc/af_rxrpc.c:560
   ...

  Freed by task 2318:
   ...
   kfree_skb+0x140/0x3f0 net/core/skbuff.c:704
   rxrpc_free_skb+0x11d/0x150 net/rxrpc/skbuff.c:78
   rxrpc_cleanup_ring net/rxrpc/call_object.c:485 [inline]
   rxrpc_release_call+0x5dd/0x860 net/rxrpc/call_object.c:552
   rxrpc_release_calls_on_socket+0x21c/0x300 net/rxrpc/call_object.c:579
   rxrpc_release_sock net/rxrpc/af_rxrpc.c:885 [inline]
   rxrpc_release+0x263/0x5a0 net/rxrpc/af_rxrpc.c:916
   __sock_release+0xcd/0x280 net/socket.c:597
   ...

  The buggy address belongs to the object at 888011606dc0
   which belongs to the cache skbuff_head_cache of size 232

Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Reported-by: syzbot+174de899852504e4a...@syzkaller.appspotmail.com
Reported-by: syzbot+3d1c772efafd3c38d...@syzkaller.appspotmail.com
Signed-off-by: David Howells 
cc: Hillf Danton 
---

 net/rxrpc/call_object.c |2 --
 1 file changed, 2 deletions(-)

diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index c845594b663f..4eb91d958a48 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -548,8 +548,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct 
rxrpc_call *call)
rxrpc_disconnect_call(call);
if (call->security)
call->security->free_call_crypto(call);
-
-   rxrpc_cleanup_ring(call);
_leave("");
 }
 




Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO

2021-02-03 Thread David Howells
Xin Long  wrote:

> I saw the state of this patchset is still new, should I repost it?

It needs a fix in patch 2 (see my response to that patch).

Thanks,
David



Re: KASAN: use-after-free Read in rxrpc_send_data_packet

2021-02-01 Thread David Howells
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git 
7ef09ba11b33e371c9a8510c1f56e40aa0862c65



Re: KASAN: use-after-free Read in rxrpc_send_data_packet

2021-02-01 Thread David Howells
Hillf Danton  wrote:

> --- a/net/rxrpc/call_object.c
> +++ b/net/rxrpc/call_object.c
> @@ -549,6 +549,7 @@ void rxrpc_release_call(struct rxrpc_soc
>   if (call->security)
>   call->security->free_call_crypto(call);
>  
> + cancel_work_sync(&call->processor);
>   rxrpc_cleanup_ring(call);
>   _leave("");
>  }

It's probably better to do the cancellation before we call
->free_call_crypto().

Two other alternatives would be to lock in rxrpc_cleanup_ring() or just remove
that call of rxrpc_cleanup_ring() and leave it to rxrpc_cleanup_call() (which
calls it anyway).  The latter might be the best option as the work function
holds a ref on the call.

Clearing the ring in rxrpc_release_call() is more of an optimisation, meant to
recycle skbuffs sooner, but I would hope that the call would be destroyed
quickly after this point anyway.

David



[PATCH net] rxrpc: Fix deadlock around release of dst cached on udp tunnel

2021-01-29 Thread David Howells
AF_RXRPC sockets use UDP ports in encap mode.  This causes socket and dst
from an incoming packet to get stolen and attached to the UDP socket from
whence it is leaked when that socket is closed.

When a network namespace is removed, the wait for dst records to be cleaned
up happens before the cleanup of the rxrpc and UDP socket, meaning that the
wait never finishes.

Fix this by moving the rxrpc (and, by dependence, the afs) private
per-network namespace registrations to the device group rather than subsys
group.  This allows cached rxrpc local endpoints to be cleared and their
UDP sockets closed before we try waiting for the dst records.

The symptom is that lines looking like the following:

unregister_netdevice: waiting for lo to become free

get emitted at regular intervals after running something like the
referenced syzbot test.

Thanks to Vadim for tracking this down and work out the fix.

Reported-by: syzbot+df400f2f24a1677cd...@syzkaller.appspotmail.com
Reported-by: Vadim Fedorenko 
Fixes: 5271953cad31 ("rxrpc: Use the UDP encap_rcv hook")
Signed-off-by: David Howells 
Acked-by: Vadim Fedorenko 
---

 fs/afs/main.c|6 +++---
 net/rxrpc/af_rxrpc.c |6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/afs/main.c b/fs/afs/main.c
index accdd8970e7c..b2975256dadb 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -193,7 +193,7 @@ static int __init afs_init(void)
goto error_cache;
 #endif
 
-   ret = register_pernet_subsys(&afs_net_ops);
+   ret = register_pernet_device(&afs_net_ops);
if (ret < 0)
goto error_net;
 
@@ -213,7 +213,7 @@ static int __init afs_init(void)
 error_proc:
afs_fs_exit();
 error_fs:
-   unregister_pernet_subsys(&afs_net_ops);
+   unregister_pernet_device(&afs_net_ops);
 error_net:
 #ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
@@ -244,7 +244,7 @@ static void __exit afs_exit(void)
 
proc_remove(afs_proc_symlink);
afs_fs_exit();
-   unregister_pernet_subsys(&afs_net_ops);
+   unregister_pernet_device(&afs_net_ops);
 #ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
 #endif
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0a2f4817ec6c..41671af6b33f 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -990,7 +990,7 @@ static int __init af_rxrpc_init(void)
goto error_security;
}
 
-   ret = register_pernet_subsys(&rxrpc_net_ops);
+   ret = register_pernet_device(&rxrpc_net_ops);
if (ret)
goto error_pernet;
 
@@ -1035,7 +1035,7 @@ static int __init af_rxrpc_init(void)
 error_sock:
proto_unregister(&rxrpc_proto);
 error_proto:
-   unregister_pernet_subsys(&rxrpc_net_ops);
+   unregister_pernet_device(&rxrpc_net_ops);
 error_pernet:
rxrpc_exit_security();
 error_security:
@@ -1057,7 +1057,7 @@ static void __exit af_rxrpc_exit(void)
unregister_key_type(&key_type_rxrpc);
sock_unregister(PF_RXRPC);
proto_unregister(&rxrpc_proto);
-   unregister_pernet_subsys(&rxrpc_net_ops);
+   unregister_pernet_device(&rxrpc_net_ops);
ASSERTCMP(atomic_read(&rxrpc_n_tx_skbs), ==, 0);
ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0);
 




Re: [PATCH net] rxrpc: Fix deadlock around release of dst cached on udp tunnel

2021-01-29 Thread David Howells
Vadim Fedorenko  wrote:

> You missed the call to dst_release(sk->sk_rx_dst) in
> rxrpc_sock_destructor. Without it we are still leaking the dst.

Hmmm...  I no longer get the messages appearing with this patch.  I'll have
another look.

David



[PATCH net] rxrpc: Fix deadlock around release of dst cached on udp tunnel

2021-01-29 Thread David Howells
AF_RXRPC sockets use UDP ports in encap mode.  This causes socket and dst
from an incoming packet to get stolen and attached to the UDP socket from
whence it is leaked when that socket is closed.

When a network namespace is removed, the wait for dst records to be cleaned
up happens before the cleanup of the rxrpc and UDP socket, meaning that the
wait never finishes.

Fix this by moving the rxrpc (and, by dependence, the afs) private
per-network namespace registrations to the device group rather than subsys
group.  This allows cached rxrpc local endpoints to be cleared and their
UDP sockets closed before we try waiting for the dst records.

The symptom is that lines looking like the following:

unregister_netdevice: waiting for lo to become free

get emitted at regular intervals after running something like the
referenced syzbot test.

Thanks to Vadim for tracking this down and work out the fix.

Reported-by: syzbot+df400f2f24a1677cd...@syzkaller.appspotmail.com
Reported-by: Vadim Fedorenko 
Fixes: 5271953cad31 ("rxrpc: Use the UDP encap_rcv hook")
Signed-off-by: David Howells 
---

 fs/afs/main.c|6 +++---
 net/rxrpc/af_rxrpc.c |6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/afs/main.c b/fs/afs/main.c
index accdd8970e7c..b2975256dadb 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -193,7 +193,7 @@ static int __init afs_init(void)
goto error_cache;
 #endif
 
-   ret = register_pernet_subsys(&afs_net_ops);
+   ret = register_pernet_device(&afs_net_ops);
if (ret < 0)
goto error_net;
 
@@ -213,7 +213,7 @@ static int __init afs_init(void)
 error_proc:
afs_fs_exit();
 error_fs:
-   unregister_pernet_subsys(&afs_net_ops);
+   unregister_pernet_device(&afs_net_ops);
 error_net:
 #ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
@@ -244,7 +244,7 @@ static void __exit afs_exit(void)
 
proc_remove(afs_proc_symlink);
afs_fs_exit();
-   unregister_pernet_subsys(&afs_net_ops);
+   unregister_pernet_device(&afs_net_ops);
 #ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
 #endif
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0a2f4817ec6c..41671af6b33f 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -990,7 +990,7 @@ static int __init af_rxrpc_init(void)
goto error_security;
}
 
-   ret = register_pernet_subsys(&rxrpc_net_ops);
+   ret = register_pernet_device(&rxrpc_net_ops);
if (ret)
goto error_pernet;
 
@@ -1035,7 +1035,7 @@ static int __init af_rxrpc_init(void)
 error_sock:
proto_unregister(&rxrpc_proto);
 error_proto:
-   unregister_pernet_subsys(&rxrpc_net_ops);
+   unregister_pernet_device(&rxrpc_net_ops);
 error_pernet:
rxrpc_exit_security();
 error_security:
@@ -1057,7 +1057,7 @@ static void __exit af_rxrpc_exit(void)
unregister_key_type(&key_type_rxrpc);
sock_unregister(PF_RXRPC);
proto_unregister(&rxrpc_proto);
-   unregister_pernet_subsys(&rxrpc_net_ops);
+   unregister_pernet_device(&rxrpc_net_ops);
ASSERTCMP(atomic_read(&rxrpc_n_tx_skbs), ==, 0);
ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0);
 




[PATCH net] rxrpc: Fix memory leak in rxrpc_lookup_local

2021-01-28 Thread David Howells
From: Takeshi Misawa 

Commit 9ebeddef58c4 ("rxrpc: rxrpc_peer needs to hold a ref on the rxrpc_local 
record")
Then release ref in __rxrpc_put_peer and rxrpc_put_peer_locked.

struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t 
gfp)
-   peer->local = local;
+   peer->local = rxrpc_get_local(local);

rxrpc_discard_prealloc also need ref release in discarding.

syzbot report:
BUG: memory leak
unreferenced object 0x8881080ddc00 (size 256):
  comm "syz-executor339", pid 8462, jiffies 4294942238 (age 12.350s)
  hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 0a 00 00 00 00 c0 00 08 81 88 ff ff  
  backtrace:
[<2b6e495f>] kmalloc include/linux/slab.h:552 [inline]
[<2b6e495f>] kzalloc include/linux/slab.h:682 [inline]
[<2b6e495f>] rxrpc_alloc_local net/rxrpc/local_object.c:79 [inline]
[<2b6e495f>] rxrpc_lookup_local+0x1c1/0x760 
net/rxrpc/local_object.c:244
[<6b43a77b>] rxrpc_bind+0x174/0x240 net/rxrpc/af_rxrpc.c:149
[<fd447a55>] afs_open_socket+0xdb/0x200 fs/afs/rxrpc.c:64
[<7fd8867c>] afs_net_init+0x2b4/0x340 fs/afs/main.c:126
[<63d80ec1>] ops_init+0x4e/0x190 net/core/net_namespace.c:152
[<073c5efa>] setup_net+0xde/0x2d0 net/core/net_namespace.c:342
[<a6744d5b>] copy_net_ns+0x19f/0x3e0 net/core/net_namespace.c:483
[<17d3aec3>] create_new_namespaces+0x199/0x4f0 kernel/nsproxy.c:110
[<186271ef>] unshare_nsproxy_namespaces+0x9b/0x120 
kernel/nsproxy.c:226
[<2de7bac4>] ksys_unshare+0x2fe/0x5c0 kernel/fork.c:2957
[<349b12ba>] __do_sys_unshare kernel/fork.c:3025 [inline]
[<349b12ba>] __se_sys_unshare kernel/fork.c:3023 [inline]
[<349b12ba>] __x64_sys_unshare+0x12/0x20 kernel/fork.c:3023
[<6d178ef7>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
[<637076d4>] entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fixes: 9ebeddef58c4 ("rxrpc: rxrpc_peer needs to hold a ref on the rxrpc_local 
record")
Signed-off-by: Takeshi Misawa 
Reported-and-tested-by: syzbot+305326672fed51b20...@syzkaller.appspotmail.com
Signed-off-by: David Howells 
---

 net/rxrpc/call_accept.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 382add72c66f..1ae90fb97936 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -197,6 +197,7 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
tail = b->peer_backlog_tail;
while (CIRC_CNT(head, tail, size) > 0) {
struct rxrpc_peer *peer = b->peer_backlog[tail];
+   rxrpc_put_local(peer->local);
kfree(peer);
tail = (tail + 1) & (size - 1);
}




Re: [PATCHv4 net-next 2/2] rxrpc: call udp_tunnel_encap_enable in rxrpc_open_socket

2021-01-26 Thread David Howells
Xin Long  wrote:

> - udp_encap_enable();
> -#if IS_ENABLED(CONFIG_AF_RXRPC_IPV6)
> - if (local->srx.transport.family == AF_INET6)
> - udpv6_encap_enable();
> -#endif
> + udp_tunnel_encap_enable(local->socket);

You need this too:

--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "ar-internal.h"

With that, it seems to work still:

    Acked-and-tested-by: David Howells 

David



Re: [PATCH net] rxrpc: Call state should be read with READ_ONCE() under some circumstances

2021-01-13 Thread David Howells
Jakub Kicinski  wrote:

> On Tue, 12 Jan 2021 15:59:15 +0000 David Howells wrote:
> > From: Baptiste Lepers 
> > 
> > The call state may be changed at any time by the data-ready routine in
> > response to received packets, so if the call state is to be read and acted
> > upon several times in a function, READ_ONCE() must be used unless the call
> > state lock is held.
> > 
> > As it happens, we used READ_ONCE() to read the state a few lines above the
> > unmarked read in rxrpc_input_data(), so use that value rather than
> > re-reading it.
> > 
> > Signed-off-by: Baptiste Lepers 
> > Signed-off-by: David Howells 
> 
> Fixes: a158bdd3247b ("rxrpc: Fix call timeouts")
> 
> maybe?

Ah, yes.  I missed there wasn't a Fixes line.  Can you add that one in, or do
I need to resubmit the patch?

David



[PATCH net] rxrpc: Call state should be read with READ_ONCE() under some circumstances

2021-01-12 Thread David Howells
From: Baptiste Lepers 

The call state may be changed at any time by the data-ready routine in
response to received packets, so if the call state is to be read and acted
upon several times in a function, READ_ONCE() must be used unless the call
state lock is held.

As it happens, we used READ_ONCE() to read the state a few lines above the
unmarked read in rxrpc_input_data(), so use that value rather than
re-reading it.

Signed-off-by: Baptiste Lepers 
Signed-off-by: David Howells 
---

 net/rxrpc/input.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 667c44aa5a63..dc201363f2c4 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -430,7 +430,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, 
struct sk_buff *skb)
return;
}
 
-   if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
+   if (state == RXRPC_CALL_SERVER_RECV_REQUEST) {
unsigned long timo = READ_ONCE(call->next_req_timo);
unsigned long now, expect_req_by;
 




[PATCH net] rxrpc: Fix handling of an unsupported token type in rxrpc_read()

2021-01-12 Thread David Howells
Clang static analysis reports the following:

net/rxrpc/key.c:657:11: warning: Assigned value is garbage or undefined
toksize = toksizes[tok++];
^ ~~~

rxrpc_read() contains two consecutive loops.  The first loop calculates the
token sizes and stores the results in toksizes[] and the second one uses
the array.  When there is an error in identifying the token in the first
loop, the token is skipped, no change is made to the toksizes[] array.
When the same error happens in the second loop, the token is not skipped.
This will cause the toksizes[] array to be out of step and will overrun
past the calculated sizes.

Fix this by making both loops log a message and return an error in this
case.  This should only happen if a new token type is incompletely
implemented, so it should normally be impossible to trigger this.

Fixes: 9a059cd5ca7d ("rxrpc: Downgrade the BUG() for unsupported token type in 
rxrpc_read()")
Reported-by: Tom Rix 
Signed-off-by: David Howells 
Reviewed-by: Tom Rix 
---

 net/rxrpc/key.c |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 9631aa8543b5..8d2073e0e3da 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -598,7 +598,7 @@ static long rxrpc_read(const struct key *key,
default: /* we have a ticket we can't encode */
pr_err("Unsupported key token type (%u)\n",
   token->security_index);
-   continue;
+   return -ENOPKG;
}
 
_debug("token[%u]: toksize=%u", ntoks, toksize);
@@ -674,7 +674,9 @@ static long rxrpc_read(const struct key *key,
break;
 
default:
-   break;
+   pr_err("Unsupported key token type (%u)\n",
+  token->security_index);
+   return -ENOPKG;
}
 
ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,




Re: [PATCH] rxrpc: Call state should be read with READ_ONCE() under some circumstances

2021-01-07 Thread David Howells
Baptiste Lepers  wrote:

> The call state may be changed at any time by the data-ready routine in
> response to received packets, so if the call state is to be read and acted
> upon several times in a function, READ_ONCE() must be used unless the call
> state lock is held.

I'm going to add:

As it happens, we used READ_ONCE() to read the state a few lines above the
unmarked read in rxrpc_input_data(), so use that value rather than
re-reading it.

to the commit message, if that's okay by you.

David



Re: [PATCH] rxrpc: fix handling of an unsupported token type in rxrpc_read()

2021-01-06 Thread David Howells
Tom Rix  wrote:

> On 1/6/21 11:44 AM, David Howells wrote:
> > Tom Rix  wrote:
> >
> >> These two loops iterate over the same data, i believe returning here is all
> >> that is needed.
> > But if the first loop is made to support a new type, but the second loop is
> > missed, it will then likely oops.  Besides, the compiler should optimise 
> > both
> > paths together.
> 
> You are right, I was only considering the existing cases.

Thanks.  Can I put that down as a Reviewed-by?

David



Re: [PATCH] rxrpc: fix handling of an unsupported token type in rxrpc_read()

2021-01-06 Thread David Howells
Tom Rix  wrote:

> These two loops iterate over the same data, i believe returning here is all
> that is needed.

But if the first loop is made to support a new type, but the second loop is
missed, it will then likely oops.  Besides, the compiler should optimise both
paths together.

David



Re: [PATCH] rxrpc: fix handling of an unsupported token type in rxrpc_read()

2021-01-06 Thread David Howells
David Howells  wrote:

> How about this?
> ...
> Fix the second loop so that it doesn't encode the size and type of an
> unsupported token, but rather just ignore it as does the first loop.

Actually, a better way is probably just to error out in this case.  This
should only happen if a new token type is incompletely implemented.

David
---
commit e68ef16f59aa57564761b21e5ecb2ebbd72d1c57
Author: David Howells 
Date:   Wed Jan 6 16:21:40 2021 +

rxrpc: Fix handling of an unsupported token type in rxrpc_read()

Clang static analysis reports the following:

net/rxrpc/key.c:657:11: warning: Assigned value is garbage or undefined
toksize = toksizes[tok++];
^ ~~~

rxrpc_read() contains two consecutive loops.  The first loop calculates the
token sizes and stores the results in toksizes[] and the second one uses
the array.  When there is an error in identifying the token in the first
loop, the token is skipped, no change is made to the toksizes[] array.
When the same error happens in the second loop, the token is not skipped.
This will cause the toksizes[] array to be out of step and will overrun
past the calculated sizes.

Fix this by making both loops log a message and return an error in this
case.  This should only happen if a new token type is incompletely
implemented, so it should normally be impossible to trigger this.

Fixes: 9a059cd5ca7d ("rxrpc: Downgrade the BUG() for unsupported token type 
in rxrpc_read()")
Reported-by: Tom Rix 
Signed-off-by: David Howells 

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 9631aa8543b5..8d2073e0e3da 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -598,7 +598,7 @@ static long rxrpc_read(const struct key *key,
default: /* we have a ticket we can't encode */
pr_err("Unsupported key token type (%u)\n",
   token->security_index);
-   continue;
+   return -ENOPKG;
}
 
_debug("token[%u]: toksize=%u", ntoks, toksize);
@@ -674,7 +674,9 @@ static long rxrpc_read(const struct key *key,
break;
 
default:
-   break;
+   pr_err("Unsupported key token type (%u)\n",
+  token->security_index);
+   return -ENOPKG;
}
 
ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,



Re: [PATCH] rxrpc: fix handling of an unsupported token type in rxrpc_read()

2021-01-06 Thread David Howells
How about this?

David
---
commit 5d370a9db65a6fae82f09a009430ae40c564b0ef
Author: David Howells 
Date:   Wed Jan 6 16:21:40 2021 +

rxrpc: Fix handling of an unsupported token type in rxrpc_read()

Clang static analysis reports the following:

net/rxrpc/key.c:657:11: warning: Assigned value is garbage or undefined
toksize = toksizes[tok++];
^ ~~~

rxrpc_read() contains two consecutive loops.  The first loop calculates the
token sizes and stores the results in toksizes[] and the second one uses
the array.  When there is an error in identifying the token in the first
loop, the token is skipped, no change is made to the toksizes[] array.
When the same error happens in the second loop, the token is not skipped.
This will cause the toksizes[] array to be out of step and will overrun
past the calculated sizes.

Fix the second loop so that it doesn't encode the size and type of an
unsupported token, but rather just ignore it as does the first loop.

Fixes: 9a059cd5ca7d ("rxrpc: Downgrade the BUG() for unsupported token type 
in rxrpc_read()")
Reported-by: Tom Rix 
Signed-off-by: David Howells 

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 9631aa8543b5..c8e298c8d314 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -655,12 +655,12 @@ static long rxrpc_read(const struct key *key,
tok = 0;
for (token = key->payload.data[0]; token; token = token->next) {
toksize = toksizes[tok++];
-   ENCODE(toksize);
oldxdr = xdr;
-   ENCODE(token->security_index);
 
switch (token->security_index) {
case RXRPC_SECURITY_RXKAD:
+   ENCODE(toksize);
+   ENCODE(token->security_index);
ENCODE(token->kad->vice_id);
ENCODE(token->kad->kvno);
ENCODE_BYTES(8, token->kad->session_key);



Re: [PATCH] rxrpc: fix handling of an unsupported token type in rxrpc_read()

2021-01-04 Thread David Howells
t...@redhat.com wrote:

> - switch (token->security_index) {
> - case RXRPC_SECURITY_RXKAD:
> ...
> - switch (token->security_index) {
> - case RXRPC_SECURITY_RXKAD:

These switches need to be kept.  There's another security type on the way.
See:

https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-rxgk

for example.  I'll have a look later.

David



Re: [PATCH net-next] net: rxrpc: convert comma to semicolon

2020-12-09 Thread David Howells
Zheng Yongjun  wrote:

> Replace a comma between expression statements by a semicolon.
> 
> Signed-off-by: Zheng Yongjun 

Reviewed-by: David Howells 



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-08 Thread David Howells
Ard Biesheuvel  wrote:

> Apparently, it is permitted for gss_krb5_cts_crypt() to do a
> kmalloc(GFP_NOFS) in the context from where gss_krb5_aes_encrypt() is
> being invoked, and so I don't see why it wouldn't be possible to
> simply kmalloc() a scatterlist[] of the appropriate size, populate it
> with all the pages, bufs and whatever else gets passed into the
> skcipher, and pass it into the skcipher in one go.

I never said it wasn't possible.  But doing a pair of order-1 allocations from
there might have a significant detrimental effect on performance - in which
case Trond and co. will say "no".

Remember: to crypt 1MiB of data on a 64-bit machine requires 2 x minimum 8KiB
scatterlist arrays.  That's assuming the pages in the middle are contiguous,
which might not be the case for a direct I/O read/write.  So for the DIO case,
it could be involve an order-2 allocation (or chaining of single pages).

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-08 Thread David Howells
David Howells  wrote:

> I wonder - would it make sense to reserve two arrays of scatterlist structs
> and a mutex per CPU sufficient to map up to 1MiB of pages with each array
> while the krb5 service is in use?

Actually, simply reserving a set per CPU is probably unnecessary.  We could,
say, set a minimum and a maximum on the reservations (say 2 -> 2*nr_cpus) and
then allocate new ones when we run out.  Then let the memory shrinker clean
them up off an lru list.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-08 Thread David Howells
I wonder - would it make sense to reserve two arrays of scatterlist structs
and a mutex per CPU sufficient to map up to 1MiB of pages with each array
while the krb5 service is in use?

That way sunrpc could, say, grab the mutex, map the input and output buffers,
do the entire crypto op in one go and then release the mutex - at least for
big ops, small ops needn't use this service.

For rxrpc/afs's use case this would probably be overkill - it's doing crypto
on each packet, not on whole operations - but I could still make use of it
there.

However, that then limits the maximum size of an op to 1MiB, plus dangly bits
on either side (which can be managed with chained scatterlist structs) and
also limits the number of large simultaneous krb5 crypto ops we can do.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-08 Thread David Howells
Ard Biesheuvel  wrote:

Ard Biesheuvel  wrote:

> > > > I wonder if it would help if the input buffer and output buffer didn't
> > > > have to correspond exactly in usage - ie. the output buffer could be
> > > > used at a slower rate than the input to allow for buffering inside the
> > > > crypto algorithm.
> > >
> > > I don't follow - how could one be used at a slower rate?
> >
> > I mean that the crypto algorithm might need to buffer the last part of the
> > input until it has a block's worth before it can write to the output.
> 
> This is what is typically handled transparently by the driver. When
> you populate a scatterlist, it doesn't matter how misaligned the
> individual elements are, the scatterlist walker will always present
> the data in chunks that the crypto algorithm can manage. This is why
> using a single scatterlist for the entire input is preferable in
> general.

Yep - but the assumption currently on the part of the callers is that they
provide the input buffer and corresponding output buffer - and that the
algorithm will transfer data from one to the other, such that the same amount
of input and output bufferage will be used.

However, if we start pushing data in progressively, this would no longer hold
true unless we also require the caller to only present in block-size chunks.

For example, if I gave the encryption function 120 bytes of data and a 120
byte output buffer, but the algorithm has a 16-byte blocksize, it will,
presumably, consume 120 bytes of input, but it can only write 112 bytes of
output at this time.  So the current interface would need to evolve to
indicate separately how much input has been consumed and how much output has
been produced - in which case it can't be handled transparently.

For krb5, it's actually worse than that, since we want to be able to
insert/remove a header and a trailer (and might need to go back and update the
header after) - but I think in the krb5 case, we need to treat the header and
trailer specially and update them after the fact in the wrapping case
(unwrapping is not a problem, since we can just cache the header).

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-07 Thread David Howells
Ard Biesheuvel  wrote:

> > I wonder if it would help if the input buffer and output buffer didn't
> > have to correspond exactly in usage - ie. the output buffer could be used
> > at a slower rate than the input to allow for buffering inside the crypto
> > algorithm.
> >
> 
> I don't follow - how could one be used at a slower rate?

I mean that the crypto algorithm might need to buffer the last part of the
input until it has a block's worth before it can write to the output.

> > The hashes corresponding to the kerberos enctypes I'm supporting are:
> >
> > HMAC-SHA1 for aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
> >
> > HMAC-SHA256 for aes128-cts-hmac-sha256-128
> >
> > HMAC-SHA384 for aes256-cts-hmac-sha384-192
> >
> > CMAC-CAMELLIA for camellia128-cts-cmac and camellia256-cts-cmac
> >
> > I'm not sure you can support all of those with the instructions available.
>
> It depends on whether the caller can make use of the authenc()
> pattern, which is a type of AEAD we support.

Interesting.  I didn't realise AEAD was an API.

> There are numerous implementations of authenc(hmac(shaXXX),cbc(aes)),
> including h/w accelerated ones, but none that implement ciphertext
> stealing. So that means that, even if you manage to use the AEAD layer to
> perform both at the same time, the generic authenc() template will perform
> the cts(cbc(aes)) and hmac(shaXXX) by calling into skciphers and ahashes,
> respectively, which won't give you any benefit until accelerated
> implementations turn up that perform the whole operation in one pass over
> the input. And even then, I don't think the performance benefit will be
> worth it.

Also, the rfc8009 variants that use AES with SHA256/384 hash the ciphertext,
not the plaintext.

For the moment, it's probably not worth worrying about, then.  If I can manage
to abstract the sunrpc bits out into a krb5 library, we can improve the
library later.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-07 Thread David Howells
Ard Biesheuvel  wrote:

> > Yeah - the problem with that is that for sunrpc, we might be dealing with 
> > 1MB
> > plus bits of non-contiguous pages, requiring >8K of scatterlist elements
> > (admittedly, we can chain them, but we may have to do one or more large
> > allocations).
> >
> > > However, I would recommend against it:
> >
> > Sorry, recommend against what?
> >
> 
> Recommend against the current approach of manipulating the input like
> this and feeding it into the skcipher piecemeal.

Right.  I understand the problem, but as I mentioned above, the scatterlist
itself becomes a performance issue as it may exceed two pages in size.  Double
that as there may need to be separate input and output scatterlists.

> Herbert recently made some changes for MSG_MORE support in the AF_ALG
> code, which permits a skcipher encryption to be split into several
> invocations of the skcipher layer without the need for this complexity
> on the side of the caller. Maybe there is a way to reuse that here.
> Herbert?

I wonder if it would help if the input buffer and output buffer didn't have to
correspond exactly in usage - ie. the output buffer could be used at a slower
rate than the input to allow for buffering inside the crypto algorithm.

> > Can you also do SHA at the same time in the same loop?
> 
> SHA-1 or HMAC-SHA1? The latter could probably be modeled as an AEAD.
> The former doesn't really fit the current API so we'd have to invent
> something for it.

The hashes corresponding to the kerberos enctypes I'm supporting are:

HMAC-SHA1 for aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.

HMAC-SHA256 for aes128-cts-hmac-sha256-128

HMAC-SHA384 for aes256-cts-hmac-sha384-192

CMAC-CAMELLIA for camellia128-cts-cmac and camellia256-cts-cmac

I'm not sure you can support all of those with the instructions available.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-07 Thread David Howells
Herbert Xu  wrote:

> > Herbert recently made some changes for MSG_MORE support in the AF_ALG
> > code, which permits a skcipher encryption to be split into several
> > invocations of the skcipher layer without the need for this complexity
> > on the side of the caller. Maybe there is a way to reuse that here.
> > Herbert?
> 
> Yes this was one of the reasons I was persuing the continuation
> work.  It should allow us to kill the special case for CTS in the
> krb5 code.
> 
> Hopefully I can get some time to restart work on this soon.

In the krb5 case, we know in advance how much data we're going to be dealing
with, if that helps.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-04 Thread David Howells
Ard Biesheuvel  wrote:

> The tricky thing with CTS is that you have to ensure that the final
> full and partial blocks are presented to the crypto driver as one
> chunk, or it won't be able to perform the ciphertext stealing. This
> might be the reason for the current approach. If the sunrpc code has
> multiple disjoint chunks of data to encrypto, it is always better to
> wrap it in a single scatterlist and call into the skcipher only once.

Yeah - the problem with that is that for sunrpc, we might be dealing with 1MB
plus bits of non-contiguous pages, requiring >8K of scatterlist elements
(admittedly, we can chain them, but we may have to do one or more large
allocations).

> However, I would recommend against it:

Sorry, recommend against what?

> at least for ARM and arm64, I
> have already contributed SIMD based implementations that use SIMD
> permutation instructions and overlapping loads and stores to perform
> the ciphertext stealing, which means that there is only a single layer
> which implements CTS+CBC+AES, and this layer can consume the entire
> scatterlist in one go. We could easily do something similar in the
> AES-NI driver as well.

Can you point me at that in the sources?

Can you also do SHA at the same time in the same loop?

Note that the rfc3962 AES does the checksum over the plaintext, but rfc8009
does it over the ciphertext.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-04 Thread David Howells
Bruce Fields  wrote:

> OK, I guess I don't understand the question.  I haven't thought about
> this code in at least a decade.  What's an auxilary cipher?  Is this a
> question about why we're implementing something, or how we're
> implementing it?

That's what the Linux sunrpc implementation calls them:

struct crypto_sync_skcipher *acceptor_enc;
struct crypto_sync_skcipher *initiator_enc;
struct crypto_sync_skcipher *acceptor_enc_aux;
struct crypto_sync_skcipher *initiator_enc_aux;

Auxiliary ciphers aren't mentioned in rfc396{1,2} so it appears to be
something peculiar to that implementation.

So acceptor_enc and acceptor_enc_aux, for instance, are both based on the same
key, and the implementation seems to pass the IV from one to the other.  The
only difference is that the 'aux' cipher lacks the CTS wrapping - which only
makes a difference for the final two blocks[*] of the encryption (or
decryption) - and only if the data doesn't fully fill out the last block
(ie. it needs padding in some way so that the encryption algorithm can handle
it).

[*] Encryption cipher blocks, that is.

So I think it's purpose is twofold:

 (1) It's a way to be a bit more efficient, cutting out the CTS layer's
 indirection and additional buffering.

 (2) crypto_skcipher_encrypt() assumes that it's doing the entire crypto
 operation in one go and will always impose the final CTS bit, so you
 can't call it repeatedly to progress through a buffer (as
 xdr_process_buf() would like to do) as that would corrupt the data being
 encrypted - unless you made sure that the data was always block-size
 aligned (in which case, there's no point using CTS).

I wonder how much going through three layers of crypto modules costs.  Looking
at how AES can be implemented using, say, Intel AES intructions, it looks like
AES+CBC should be easy to do in a single module.  I wonder if we could have
optimised kerberos crypto that do the AES and the SHA together in a single
loop.

David



Re: Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-04 Thread David Howells
Bruce Fields  wrote:

> > Reading up on CTS, I'm guessing the reason it's like this is that CTS is the
> > same as the non-CTS, except for the last two blocks, but the non-CTS one is
> > more efficient.
> 
> CTS is cipher-text stealing, isn't it?  I think it was Kevin Coffman
> that did that, and I don't remember the history.  I thought it was
> required by some spec or peer implementation (maybe Windows?) but I
> really don't remember.  It may predate git.  I'll dig around and see
> what I can find.

rfc3961 and rfc3962 specify CTS-CBC with AES.

David



Why the auxiliary cipher in gss_krb5_crypto.c?

2020-12-04 Thread David Howells
Hi Chuck, Bruce,

Why is gss_krb5_crypto.c using an auxiliary cipher?  For reference, the
gss_krb5_aes_encrypt() code looks like the attached.

>From what I can tell, in AES mode, the difference between the main cipher and
the auxiliary cipher is that the latter is "cbc(aes)" whereas the former is
"cts(cbc(aes))" - but they have the same key.

Reading up on CTS, I'm guessing the reason it's like this is that CTS is the
same as the non-CTS, except for the last two blocks, but the non-CTS one is
more efficient.

David
---
nbytes = buf->len - offset - GSS_KRB5_TOK_HDR_LEN;
nblocks = (nbytes + blocksize - 1) / blocksize;
cbcbytes = 0;
if (nblocks > 2)
cbcbytes = (nblocks - 2) * blocksize;

memset(desc.iv, 0, sizeof(desc.iv));

if (cbcbytes) {
SYNC_SKCIPHER_REQUEST_ON_STACK(req, aux_cipher);

desc.pos = offset + GSS_KRB5_TOK_HDR_LEN;
desc.fragno = 0;
desc.fraglen = 0;
desc.pages = pages;
desc.outbuf = buf;
desc.req = req;

skcipher_request_set_sync_tfm(req, aux_cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);

sg_init_table(desc.infrags, 4);
sg_init_table(desc.outfrags, 4);

err = xdr_process_buf(buf, offset + GSS_KRB5_TOK_HDR_LEN,
  cbcbytes, encryptor, &desc);
skcipher_request_zero(req);
if (err)
goto out_err;
}

/* Make sure IV carries forward from any CBC results. */
err = gss_krb5_cts_crypt(cipher, buf,
 offset + GSS_KRB5_TOK_HDR_LEN + cbcbytes,
 desc.iv, pages, 1);
if (err) {
err = GSS_S_FAILURE;
goto out_err;
}



Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-12-01 Thread David Howells
Herbert Xu  wrote:

> Couldn't you just change the output sg to include the offset?

That depends on whether the caller has passed it elsewhere for some other
parallel purpose, but I think I'm going to have to go down that road and
restore it afterwards.

David



Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-12-01 Thread David Howells
Btw, would it be feasible to make it so that an extra parameter can be added
to the cipher buffer-supplying functions, e.g.:

skcipher_request_set_crypt(req, input, ciphertext_sg, esize, iv);

such that we can pass in an offset into the output sg as well?

David



Re: [PATCH net-next] net: delete __dev_getfirstbyhwtype

2020-11-30 Thread David Howells
Vladimir Oltean  wrote:

> The last user of the RTNL brother of dev_getfirstbyhwtype (the latter
> being synchronized under RCU) has been deleted in commit b4db2b35fc44
> ("afs: Use core kernel UUID generation").
> 
> Cc: Arnd Bergmann 
> Cc: David Howells 
> Cc: Eric Dumazet 
> Signed-off-by: Vladimir Oltean 

Fine by me.  I thought it had already been removed.

David



Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-11-26 Thread David Howells
Herbert Xu  wrote:

> > Here's my first cut at a generic Kerberos crypto library in the kernel so
> > that I can share code between rxrpc and sunrpc (and cifs?).
> 
> I can't find the bit where you are actually sharing this code with
> sunrpc, am I missing something?

I haven't done that yet.  Sorry, I should've been more explicit with what I
was after.  I was wanting to find out if the nfs/nfsd people are okay with
this (and if there are any gotchas I should know about - it turns out, if I
understand it correctly, the relevant code may being being rewritten a bit
anyway).

And from you, I was wanting to find out if you're okay with an interface of
this kind in crypto/ where the code is just used directly - or whether I'll
be required to wrap it up in the autoloading, module-handling mechanisms.

David



Re: [PATCH net-next 15/17] rxrpc: Organise connection security to use a union

2020-11-23 Thread David Howells
Joe Perches  wrote:

> It seems no other follow-on patch in the series uses this nameless union.

There will be a follow on series.  Either this:


https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-rxgk


or this:


https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=crypto-krb5

Depending on whether I pull the kerberos bits out into the crypto/ directory
so that it can be shared with sunrpc and maybe cifs.  Discussions are ongoing
on that.

David



[PATCH net-next 17/17] rxrpc: Ask the security class how much space to allow in a packet

2020-11-23 Thread David Howells
Ask the security class how much header and trailer space to allow for when
allocating a packet, given how much data is remaining.

This will allow the rxgk security class to stick both a trailer in as well
as a header as appropriate in the future.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 -
 net/rxrpc/conn_object.c |1 -
 net/rxrpc/insecure.c|   12 +
 net/rxrpc/rxkad.c   |   61 ---
 net/rxrpc/sendmsg.c |   41 ++--
 5 files changed, 82 insertions(+), 40 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index fda6618df1cc..7bd6f8a66a3e 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -234,6 +234,11 @@ struct rxrpc_security {
int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
 
+   /* Work out how much data we can store in a packet, given an estimate
+* of the amount of data remaining.
+*/
+   int (*how_much_data)(struct rxrpc_call *, size_t,
+size_t *, size_t *, size_t *);
 
/* impose security on a packet */
int (*secure_packet)(struct rxrpc_call *, struct sk_buff *, size_t);
@@ -467,8 +472,6 @@ struct rxrpc_connection {
atomic_tserial; /* packet serial number counter 
*/
unsigned inthi_serial;  /* highest serial number 
received */
u32 service_id; /* Service ID, possibly 
upgraded */
-   u8  size_align; /* data size alignment (for 
security) */
-   u8  security_size;  /* security header size */
u8  security_ix;/* security type */
u8  out_clientflag; /* RXRPC_CLIENT_INITIATED if we 
are client */
u8  bundle_shift;   /* Index into 
bundle->avail_chans */
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 8dd1ef25b98f..b2159dbf5412 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -49,7 +49,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
conn->security = &rxrpc_no_security;
spin_lock_init(&conn->state_lock);
conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
-   conn->size_align = 4;
conn->idle_timestamp = jiffies;
}
 
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c
index e06725e21c05..9aae99d67833 100644
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -14,6 +14,17 @@ static int none_init_connection_security(struct 
rxrpc_connection *conn,
return 0;
 }
 
+/*
+ * Work out how much data we can put in an unsecured packet.
+ */
+static int none_how_much_data(struct rxrpc_call *call, size_t remain,
+  size_t *_buf_size, size_t *_data_size, size_t 
*_offset)
+{
+   *_buf_size = *_data_size = min_t(size_t, remain, RXRPC_JUMBO_DATALEN);
+   *_offset = 0;
+   return 0;
+}
+
 static int none_secure_packet(struct rxrpc_call *call, struct sk_buff *skb,
  size_t data_size)
 {
@@ -81,6 +92,7 @@ const struct rxrpc_security rxrpc_no_security = {
.exit   = none_exit,
.init_connection_security   = none_init_connection_security,
.free_call_crypto   = none_free_call_crypto,
+   .how_much_data  = none_how_much_data,
.secure_packet  = none_secure_packet,
.verify_packet  = none_verify_packet,
.locate_data= none_locate_data,
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index e5b4bbdd0f34..e2e9e9b0a6d7 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -28,6 +28,7 @@
 #define INST_SZ40  /* size of principal's 
instance */
 #define REALM_SZ   40  /* size of principal's auth 
domain */
 #define SNAME_SZ   40  /* size of service name */
+#define RXKAD_ALIGN8
 
 struct rxkad_level1_hdr {
__be32  data_size;  /* true data size (excluding padding) */
@@ -80,7 +81,7 @@ static int rxkad_preparse_server_key(struct 
key_preparsed_payload *prep)
 
 static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep)
 {
-   
+
if (prep->payload.data[0])
crypto_free_skcipher(prep->payload.data[0]);
 }
@@ -119,14 +120,8 @@ static int rxkad_init_connection_security(struct 
rxrpc_connection *conn,
 
switch (conn->params.security_level) {
case RXRPC_SECURITY_PLAIN:
-   break;
case RXRPC_SECURITY_AUTH:
-   conn->size_align = 8;
-   

[PATCH net-next 16/17] rxrpc: rxkad: Don't use pskb_pull() to advance through the response packet

2020-11-23 Thread David Howells
In the rxkad security class, don't use pskb_pull() to advance through the
contents of the response packet.  There's no point, especially as the next
and last access to the skbuff still has to allow for the wire header in the
offset (which we didn't advance over).

Better to just add the displacement to the next offset.

Signed-off-by: David Howells 
---

 net/rxrpc/rxkad.c |4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index f3182edfcbae..e5b4bbdd0f34 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -1162,8 +1162,6 @@ static int rxkad_verify_response(struct rxrpc_connection 
*conn,
if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
  response, sizeof(*response)) < 0)
goto protocol_error;
-   if (!pskb_pull(skb, sizeof(*response)))
-   BUG();
 
version = ntohl(response->version);
ticket_len = ntohl(response->ticket_len);
@@ -1194,7 +1192,7 @@ static int rxkad_verify_response(struct rxrpc_connection 
*conn,
 
eproto = tracepoint_string("rxkad_tkt_short");
abort_code = RXKADPACKETSHORT;
-   if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
+   if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + 
sizeof(*response),
  ticket, ticket_len) < 0)
goto protocol_error_free;
 




[PATCH net-next 15/17] rxrpc: Organise connection security to use a union

2020-11-23 Thread David Howells
Organise the security information in the rxrpc_connection struct to use a
union to allow for different data for different security classes.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |   11 ---
 net/rxrpc/rxkad.c   |   40 
 2 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 742a69fb8e60..fda6618df1cc 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -448,9 +448,15 @@ struct rxrpc_connection {
struct list_headproc_link;  /* link in procfs list */
struct list_headlink;   /* link in master connection 
list */
struct sk_buff_head rx_queue;   /* received conn-level packets 
*/
+
const struct rxrpc_security *security;  /* applied security module */
-   struct crypto_sync_skcipher *cipher;/* encryption handle */
-   struct rxrpc_crypt  csum_iv;/* packet checksum base */
+   union {
+   struct {
+   struct crypto_sync_skcipher *cipher;/* encryption 
handle */
+   struct rxrpc_crypt csum_iv; /* packet checksum base 
*/
+   u32 nonce;  /* response re-use preventer */
+   } rxkad;
+   };
unsigned long   flags;
unsigned long   events;
unsigned long   idle_timestamp; /* Time at which last became 
idle */
@@ -460,7 +466,6 @@ struct rxrpc_connection {
int debug_id;   /* debug ID for printks */
atomic_tserial; /* packet serial number counter 
*/
unsigned inthi_serial;  /* highest serial number 
received */
-   u32 security_nonce; /* response re-use preventer */
u32 service_id; /* Service ID, possibly 
upgraded */
u8  size_align; /* data size alignment (for 
security) */
u8  security_size;  /* security header size */
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 37335d887570..f3182edfcbae 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -137,7 +137,7 @@ static int rxkad_init_connection_security(struct 
rxrpc_connection *conn,
if (ret < 0)
goto error_ci;
 
-   conn->cipher = ci;
+   conn->rxkad.cipher = ci;
return 0;
 
 error_ci:
@@ -191,7 +191,7 @@ static int rxkad_prime_packet_security(struct 
rxrpc_connection *conn,
crypto_skcipher_encrypt(req);
skcipher_request_free(req);
 
-   memcpy(&conn->csum_iv, tmpbuf + 2, sizeof(conn->csum_iv));
+   memcpy(&conn->rxkad.csum_iv, tmpbuf + 2, sizeof(conn->rxkad.csum_iv));
kfree(tmpbuf);
_leave(" = 0");
return 0;
@@ -203,7 +203,7 @@ static int rxkad_prime_packet_security(struct 
rxrpc_connection *conn,
  */
 static struct skcipher_request *rxkad_get_call_crypto(struct rxrpc_call *call)
 {
-   struct crypto_skcipher *tfm = &call->conn->cipher->base;
+   struct crypto_skcipher *tfm = &call->conn->rxkad.cipher->base;
struct skcipher_request *cipher_req = call->cipher_req;
 
if (!cipher_req) {
@@ -251,7 +251,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call 
*call,
memset(&iv, 0, sizeof(iv));
 
sg_init_one(&sg, skb->head, 8);
-   skcipher_request_set_sync_tfm(req, call->conn->cipher);
+   skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
crypto_skcipher_encrypt(req);
@@ -293,7 +293,7 @@ static int rxkad_secure_packet_encrypt(const struct 
rxrpc_call *call,
memcpy(&iv, token->kad->session_key, sizeof(iv));
 
sg_init_one(&sg[0], skb->head, sizeof(rxkhdr));
-   skcipher_request_set_sync_tfm(req, call->conn->cipher);
+   skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg[0], &sg[0], sizeof(rxkhdr), iv.x);
crypto_skcipher_encrypt(req);
@@ -341,7 +341,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
   call->debug_id, key_serial(call->conn->params.key),
   sp->hdr.seq, data_size);
 
-   if (!call->conn->cipher)
+   if (!call->conn->rxkad.cipher)
return 0;
 
ret = key_validate(call->conn->params.key);
@@ -353,7 +353,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
return -ENOMEM;
 
/* continue encrypting from where we left off */
-   memcpy(&iv, call->conn->

[PATCH net-next 14/17] rxrpc: Don't reserve security header in Tx DATA skbuff

2020-11-23 Thread David Howells
Insert the security header into the skbuff representing a DATA packet to be
transmitted rather than using skb_reserve() when the packet is allocated.
This makes it easier to apply crypto that spans the security header and the
data, particularly in the upcoming RxGK class where we have a common
encrypt-and-checksum function that is used in a number of circumstances.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |5 +
 net/rxrpc/insecure.c|6 ++
 net/rxrpc/rxkad.c   |   24 +---
 net/rxrpc/sendmsg.c |6 ++
 4 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 6aaa0f49dab0..742a69fb8e60 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -236,10 +236,7 @@ struct rxrpc_security {
 
 
/* impose security on a packet */
-   int (*secure_packet)(struct rxrpc_call *,
-struct sk_buff *,
-size_t,
-void *);
+   int (*secure_packet)(struct rxrpc_call *, struct sk_buff *, size_t);
 
/* verify the security on a received packet */
int (*verify_packet)(struct rxrpc_call *, struct sk_buff *,
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c
index 914e2f2e2990..e06725e21c05 100644
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -14,10 +14,8 @@ static int none_init_connection_security(struct 
rxrpc_connection *conn,
return 0;
 }
 
-static int none_secure_packet(struct rxrpc_call *call,
- struct sk_buff *skb,
- size_t data_size,
- void *sechdr)
+static int none_secure_packet(struct rxrpc_call *call, struct sk_buff *skb,
+ size_t data_size)
 {
return 0;
 }
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 301894857473..37335d887570 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -230,9 +230,7 @@ static void rxkad_free_call_crypto(struct rxrpc_call *call)
  * partially encrypt a packet (level 1 security)
  */
 static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
-   struct sk_buff *skb,
-   u32 data_size,
-   void *sechdr,
+   struct sk_buff *skb, u32 data_size,
struct skcipher_request *req)
 {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -247,12 +245,12 @@ static int rxkad_secure_packet_auth(const struct 
rxrpc_call *call,
data_size |= (u32)check << 16;
 
hdr.data_size = htonl(data_size);
-   memcpy(sechdr, &hdr, sizeof(hdr));
+   memcpy(skb->head, &hdr, sizeof(hdr));
 
/* start the encryption afresh */
memset(&iv, 0, sizeof(iv));
 
-   sg_init_one(&sg, sechdr, 8);
+   sg_init_one(&sg, skb->head, 8);
skcipher_request_set_sync_tfm(req, call->conn->cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
@@ -269,7 +267,6 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call 
*call,
 static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
   struct sk_buff *skb,
   u32 data_size,
-  void *sechdr,
   struct skcipher_request *req)
 {
const struct rxrpc_key_token *token;
@@ -289,13 +286,13 @@ static int rxkad_secure_packet_encrypt(const struct 
rxrpc_call *call,
 
rxkhdr.data_size = htonl(data_size | (u32)check << 16);
rxkhdr.checksum = 0;
-   memcpy(sechdr, &rxkhdr, sizeof(rxkhdr));
+   memcpy(skb->head, &rxkhdr, sizeof(rxkhdr));
 
/* encrypt from the session key */
token = call->conn->params.key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv));
 
-   sg_init_one(&sg[0], sechdr, sizeof(rxkhdr));
+   sg_init_one(&sg[0], skb->head, sizeof(rxkhdr));
skcipher_request_set_sync_tfm(req, call->conn->cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg[0], &sg[0], sizeof(rxkhdr), iv.x);
@@ -310,7 +307,7 @@ static int rxkad_secure_packet_encrypt(const struct 
rxrpc_call *call,
len &= ~(call->conn->size_align - 1);
 
sg_init_table(sg, ARRAY_SIZE(sg));
-   err = skb_to_sgvec(skb, sg, 0, len);
+   err = skb_to_sgvec(skb, sg, 8, len);
if (unlikely(err < 0))
goto out;
skcipher_request_set_crypt(req, sg, sg, len, iv.x);
@@ -329,8 +326,7 @@ static int rxkad_secure_packet_encrypt(const struct 
rxrpc_call

[PATCH net-next 13/17] rxrpc: Merge prime_packet_security into init_connection_security

2020-11-23 Thread David Howells
Merge the ->prime_packet_security() into the ->init_connection_security()
hook as they're always called together.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |2 --
 net/rxrpc/conn_client.c |6 --
 net/rxrpc/conn_event.c  |4 
 net/rxrpc/insecure.c|6 --
 net/rxrpc/rxkad.c   |   20 +++-
 5 files changed, 15 insertions(+), 23 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 0fb294725ff2..6aaa0f49dab0 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -234,8 +234,6 @@ struct rxrpc_security {
int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
 
-   /* prime a connection's packet security */
-   int (*prime_packet_security)(struct rxrpc_connection *);
 
/* impose security on a packet */
int (*secure_packet)(struct rxrpc_call *,
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 7e574c75be8e..dbea0bfee48e 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -180,10 +180,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, 
gfp_t gfp)
if (ret < 0)
goto error_1;
 
-   ret = conn->security->prime_packet_security(conn);
-   if (ret < 0)
-   goto error_2;
-
atomic_inc(&rxnet->nr_conns);
write_lock(&rxnet->conn_lock);
list_add_tail(&conn->proc_link, &rxnet->conn_proc_list);
@@ -203,8 +199,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, 
gfp_t gfp)
_leave(" = %p", conn);
return conn;
 
-error_2:
-   conn->security->clear(conn);
 error_1:
rxrpc_put_client_connection_id(conn);
 error_0:
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 03a482ba770f..aab069701398 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -338,10 +338,6 @@ static int rxrpc_process_event(struct rxrpc_connection 
*conn,
if (ret < 0)
return ret;
 
-   ret = conn->security->prime_packet_security(conn);
-   if (ret < 0)
-   return ret;
-
spin_lock(&conn->bundle->channel_lock);
spin_lock_bh(&conn->state_lock);
 
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c
index cf3ecffcf424..914e2f2e2990 100644
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -14,11 +14,6 @@ static int none_init_connection_security(struct 
rxrpc_connection *conn,
return 0;
 }
 
-static int none_prime_packet_security(struct rxrpc_connection *conn)
-{
-   return 0;
-}
-
 static int none_secure_packet(struct rxrpc_call *call,
  struct sk_buff *skb,
  size_t data_size,
@@ -87,7 +82,6 @@ const struct rxrpc_security rxrpc_no_security = {
.init   = none_init,
.exit   = none_exit,
.init_connection_security   = none_init_connection_security,
-   .prime_packet_security  = none_prime_packet_security,
.free_call_crypto   = none_free_call_crypto,
.secure_packet  = none_secure_packet,
.verify_packet  = none_verify_packet,
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 3057f00a6978..301894857473 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -38,6 +38,9 @@ struct rxkad_level2_hdr {
__be32  checksum;   /* decrypted data checksum */
 };
 
+static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
+  struct crypto_sync_skcipher *ci);
+
 /*
  * this holds a pinned cipher so that keventd doesn't get called by the cipher
  * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE
@@ -130,8 +133,15 @@ static int rxkad_init_connection_security(struct 
rxrpc_connection *conn,
goto error;
}
 
+   ret = rxkad_prime_packet_security(conn, ci);
+   if (ret < 0)
+   goto error_ci;
+
conn->cipher = ci;
-   ret = 0;
+   return 0;
+
+error_ci:
+   crypto_free_sync_skcipher(ci);
 error:
_leave(" = %d", ret);
return ret;
@@ -141,7 +151,8 @@ static int rxkad_init_connection_security(struct 
rxrpc_connection *conn,
  * prime the encryption state with the invariant parts of a connection's
  * description
  */
-static int rxkad_prime_packet_security(struct rxrpc_connection *conn)
+static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
+  struct crypto_sync_skcipher *ci)
 {
struct skcipher_request *req;
struct rxrpc_key_token *token;
@@ -159,7 +170,7 @@ static int rxkad_prime_packet_security(st

[PATCH net-next 12/17] rxrpc: Fix example key name in a comment

2020-11-23 Thread David Howells
Fix an example of an rxrpc key name in a comment.

Signed-off-by: David Howells 
---

 net/rxrpc/key.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 7e6d19263ce3..9631aa8543b5 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -5,7 +5,7 @@
  * Written by David Howells (dhowe...@redhat.com)
  *
  * RxRPC keys should have a description of describing their purpose:
- * "a...@cambridge.redhat.com>
+ * "a...@example.com"
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt




[PATCH net-next 09/17] rxrpc: Allow security classes to give more info on server keys

2020-11-23 Thread David Howells
Allow a security class to give more information on an rxrpc_s-type key when
it is viewed in /proc/keys.  This will allow the upcoming RxGK security
class to show the enctype name here.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |3 +++
 net/rxrpc/server_key.c  |4 
 2 files changed, 7 insertions(+)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 6682c797b878..0fb294725ff2 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -227,6 +227,9 @@ struct rxrpc_security {
/* Destroy the payload of a server key */
void (*destroy_server_key)(struct key *);
 
+   /* Describe a server key */
+   void (*describe_server_key)(const struct key *, struct seq_file *);
+
/* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
index 1a2f0b63ee1d..ead3471307ee 100644
--- a/net/rxrpc/server_key.c
+++ b/net/rxrpc/server_key.c
@@ -105,7 +105,11 @@ static void rxrpc_destroy_s(struct key *key)
 
 static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
 {
+   const struct rxrpc_security *sec = key->payload.data[1];
+
seq_puts(m, key->description);
+   if (sec && sec->describe_server_key)
+   sec->describe_server_key(key, m);
 }
 
 /*




[PATCH net-next 11/17] rxrpc: Ignore unknown tokens in key payload unless no known tokens

2020-11-23 Thread David Howells
When parsing a payload for an rxrpc-type key, ignore any tokens that are
not of a known type and don't give an error for them - unless there are no
tokens of a known type.

Signed-off-by: David Howells 
---

 net/rxrpc/key.c |   31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index a9d8f5b466be..7e6d19263ce3 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -139,7 +139,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload 
*prep)
const char *cp;
unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
size_t datalen = prep->datalen;
-   int ret;
+   int ret, ret2;
 
_enter(",{%x,%x,%x,%x},%zu",
   ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -213,6 +213,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload 
*prep)
/* okay: we're going to assume it's valid XDR format
 * - we ignore the cellname, relying on the key to be correctly named
 */
+   ret = -EPROTONOSUPPORT;
do {
toklen = ntohl(*xdr++);
token = xdr;
@@ -225,27 +226,37 @@ static int rxrpc_preparse_xdr(struct 
key_preparsed_payload *prep)
 
switch (sec_ix) {
case RXRPC_SECURITY_RXKAD:
-   ret = rxrpc_preparse_xdr_rxkad(prep, datalen, token, 
toklen);
-   if (ret != 0)
-   goto error;
+   ret2 = rxrpc_preparse_xdr_rxkad(prep, datalen, token, 
toklen);
+   break;
+   default:
+   ret2 = -EPROTONOSUPPORT;
break;
+   }
 
+   switch (ret2) {
+   case 0:
+   ret = 0;
+   break;
+   case -EPROTONOSUPPORT:
+   break;
+   case -ENOPKG:
+   if (ret != 0)
+   ret = -ENOPKG;
+   break;
default:
-   ret = -EPROTONOSUPPORT;
+   ret = ret2;
goto error;
}
 
} while (--ntoken > 0);
 
-   _leave(" = 0");
-   return 0;
+error:
+   _leave(" = %d", ret);
+   return ret;
 
 not_xdr:
_leave(" = -EPROTO");
return -EPROTO;
-error:
-   _leave(" = %d", ret);
-   return ret;
 }
 
 /*




[PATCH net-next 10/17] rxrpc: Make the parsing of xdr payloads more coherent

2020-11-23 Thread David Howells
Make the parsing of xdr-encoded payloads, as passed to add_key, more
coherent.  Shuttling back and forth between various variables was a bit
hard to follow.

Signed-off-by: David Howells 
---

 net/rxrpc/key.c |   21 +++--
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index ed29ec01237b..a9d8f5b466be 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -135,7 +135,7 @@ static int rxrpc_preparse_xdr_rxkad(struct 
key_preparsed_payload *prep,
  */
 static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
 {
-   const __be32 *xdr = prep->data, *token;
+   const __be32 *xdr = prep->data, *token, *p;
const char *cp;
unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
size_t datalen = prep->datalen;
@@ -189,20 +189,20 @@ static int rxrpc_preparse_xdr(struct 
key_preparsed_payload *prep)
goto not_xdr;
 
/* check each token wrapper */
-   token = xdr;
+   p = xdr;
loop = ntoken;
do {
if (datalen < 8)
goto not_xdr;
-   toklen = ntohl(*xdr++);
-   sec_ix = ntohl(*xdr);
+   toklen = ntohl(*p++);
+   sec_ix = ntohl(*p);
datalen -= 4;
_debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
paddedlen = (toklen + 3) & ~3;
if (toklen < 20 || toklen > datalen || paddedlen > datalen)
goto not_xdr;
datalen -= paddedlen;
-   xdr += paddedlen >> 2;
+   p += paddedlen >> 2;
 
} while (--loop > 0);
 
@@ -214,17 +214,18 @@ static int rxrpc_preparse_xdr(struct 
key_preparsed_payload *prep)
 * - we ignore the cellname, relying on the key to be correctly named
 */
do {
-   xdr = token;
toklen = ntohl(*xdr++);
-   token = xdr + ((toklen + 3) >> 2);
-   sec_ix = ntohl(*xdr++);
+   token = xdr;
+   xdr += (toklen + 3) / 4;
+
+   sec_ix = ntohl(*token++);
toklen -= 4;
 
-   _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
+   _debug("TOKEN type=%x len=%x", sec_ix, toklen);
 
switch (sec_ix) {
case RXRPC_SECURITY_RXKAD:
-   ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, 
toklen);
+   ret = rxrpc_preparse_xdr_rxkad(prep, datalen, token, 
toklen);
if (ret != 0)
goto error;
break;




[PATCH net-next 07/17] rxrpc: Hand server key parsing off to the security class

2020-11-23 Thread David Howells
Hand responsibility for parsing a server key off to the security class.  We
can determine which class from the description.  This is necessary as rxgk
server keys have different lookup requirements and different content
requirements (dependent on crypto type) to those of rxkad server keys.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |   11 +
 net/rxrpc/rxkad.c   |   47 +++
 net/rxrpc/security.c|2 +-
 net/rxrpc/server_key.c  |   56 +++
 4 files changed, 86 insertions(+), 30 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 6427bcfb4df5..6682c797b878 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -35,6 +35,7 @@ struct rxrpc_crypt {
 #define rxrpc_queue_delayed_work(WS,D) \
queue_delayed_work(rxrpc_workqueue, (WS), (D))
 
+struct key_preparsed_payload;
 struct rxrpc_connection;
 
 /*
@@ -217,6 +218,15 @@ struct rxrpc_security {
/* Clean up a security service */
void (*exit)(void);
 
+   /* Parse the information from a server key */
+   int (*preparse_server_key)(struct key_preparsed_payload *);
+
+   /* Clean up the preparse buffer after parsing a server key */
+   void (*free_preparse_server_key)(struct key_preparsed_payload *);
+
+   /* Destroy the payload of a server key */
+   void (*destroy_server_key)(struct key *);
+
/* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
@@ -1050,6 +1060,7 @@ extern const struct rxrpc_security rxkad;
  * security.c
  */
 int __init rxrpc_init_security(void);
+const struct rxrpc_security *rxrpc_security_lookup(u8);
 void rxrpc_exit_security(void);
 int rxrpc_init_client_conn_security(struct rxrpc_connection *);
 const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 0d21935dac27..3057f00a6978 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -46,6 +47,49 @@ static struct crypto_sync_skcipher *rxkad_ci;
 static struct skcipher_request *rxkad_ci_req;
 static DEFINE_MUTEX(rxkad_ci_mutex);
 
+/*
+ * Parse the information from a server key
+ *
+ * The data should be the 8-byte secret key.
+ */
+static int rxkad_preparse_server_key(struct key_preparsed_payload *prep)
+{
+   struct crypto_skcipher *ci;
+
+   if (prep->datalen != 8)
+   return -EINVAL;
+
+   memcpy(&prep->payload.data[2], prep->data, 8);
+
+   ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
+   if (IS_ERR(ci)) {
+   _leave(" = %ld", PTR_ERR(ci));
+   return PTR_ERR(ci);
+   }
+
+   if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
+   BUG();
+
+   prep->payload.data[0] = ci;
+   _leave(" = 0");
+   return 0;
+}
+
+static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep)
+{
+   
+   if (prep->payload.data[0])
+   crypto_free_skcipher(prep->payload.data[0]);
+}
+
+static void rxkad_destroy_server_key(struct key *key)
+{
+   if (key->payload.data[0]) {
+   crypto_free_skcipher(key->payload.data[0]);
+   key->payload.data[0] = NULL;
+   }
+}
+
 /*
  * initialise connection security
  */
@@ -1302,6 +1346,9 @@ const struct rxrpc_security rxkad = {
.no_key_abort   = RXKADUNKNOWNKEY,
.init   = rxkad_init,
.exit   = rxkad_exit,
+   .preparse_server_key= rxkad_preparse_server_key,
+   .free_preparse_server_key   = rxkad_free_preparse_server_key,
+   .destroy_server_key = rxkad_destroy_server_key,
.init_connection_security   = rxkad_init_connection_security,
.prime_packet_security  = rxkad_prime_packet_security,
.secure_packet  = rxkad_secure_packet,
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c
index bef9971e15cd..50cb5f1ee0c0 100644
--- a/net/rxrpc/security.c
+++ b/net/rxrpc/security.c
@@ -55,7 +55,7 @@ void rxrpc_exit_security(void)
 /*
  * look up an rxrpc security module
  */
-static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
+const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
 {
if (security_index >= ARRAY_SIZE(rxrpc_security_types))
return NULL;
diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
index b75bda05120d..1a2f0b63ee1d 100644
--- a/net/rxrpc/server_key.c
+++ b/net/rxrpc/server_key.c
@@ -30,8 +30,8 @@ static void rxrpc_destroy_s(struct key *);
 static void rxrpc_descri

[PATCH net-next 08/17] rxrpc: Don't leak the service-side session key to userspace

2020-11-23 Thread David Howells
Don't let someone reading a service-side rxrpc-type key get access to the
session key that was exchanged with the client.  The server application
will, at some point, need to be able to read the information in the ticket,
but this probably shouldn't include the key material.

Signed-off-by: David Howells 
---

 include/keys/rxrpc-type.h |1 +
 net/rxrpc/key.c   |8 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
index 8e4ced9b4ecf..333c0f49a9cd 100644
--- a/include/keys/rxrpc-type.h
+++ b/include/keys/rxrpc-type.h
@@ -36,6 +36,7 @@ struct rxkad_key {
  */
 struct rxrpc_key_token {
u16 security_index; /* RxRPC header security index */
+   boolno_leak_key;/* Don't copy the key to userspace */
struct rxrpc_key_token *next;   /* the next token in the list */
union {
struct rxkad_key *kad;
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 3bd7b9d48d27..ed29ec01237b 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -579,7 +579,8 @@ static long rxrpc_read(const struct key *key,
case RXRPC_SECURITY_RXKAD:
toksize += 8 * 4;   /* viceid, kvno, key*2, begin,
 * end, primary, tktlen */
-   toksize += RND(token->kad->ticket_len);
+   if (!token->no_leak_key)
+   toksize += RND(token->kad->ticket_len);
break;
 
default: /* we have a ticket we can't encode */
@@ -654,7 +655,10 @@ static long rxrpc_read(const struct key *key,
ENCODE(token->kad->start);
ENCODE(token->kad->expiry);
ENCODE(token->kad->primary_flag);
-   ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
+   if (token->no_leak_key)
+   ENCODE(0);
+   else
+   ENCODE_DATA(token->kad->ticket_len, 
token->kad->ticket);
break;
 
default:




[PATCH net-next 06/17] rxrpc: Split the server key type (rxrpc_s) into its own file

2020-11-23 Thread David Howells
Split the server private key type (rxrpc_s) out into its own file rather
than mingling it with the authentication/client key type (rxrpc) since they
don't really bear any relation.

Signed-off-by: David Howells 
---

 net/rxrpc/Makefile  |1 
 net/rxrpc/ar-internal.h |9 ++-
 net/rxrpc/key.c |  125 --
 net/rxrpc/server_key.c  |  141 +++
 4 files changed, 149 insertions(+), 127 deletions(-)
 create mode 100644 net/rxrpc/server_key.c

diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile
index ddd0f95713a9..b11281bed2a4 100644
--- a/net/rxrpc/Makefile
+++ b/net/rxrpc/Makefile
@@ -28,6 +28,7 @@ rxrpc-y := \
rtt.o \
security.o \
sendmsg.o \
+   server_key.o \
skbuff.o \
utils.o
 
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index db6e754743fb..6427bcfb4df5 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -906,10 +906,8 @@ extern const struct rxrpc_security rxrpc_no_security;
  * key.c
  */
 extern struct key_type key_type_rxrpc;
-extern struct key_type key_type_rxrpc_s;
 
 int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int);
-int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
 int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, 
time64_t,
  u32);
 
@@ -1064,6 +1062,13 @@ struct key *rxrpc_look_up_server_security(struct 
rxrpc_connection *,
  */
 int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
 
+/*
+ * server_key.c
+ */
+extern struct key_type key_type_rxrpc_s;
+
+int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
+
 /*
  * skbuff.c
  */
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 197b4cf46b64..3bd7b9d48d27 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -23,15 +23,10 @@
 #include 
 #include "ar-internal.h"
 
-static int rxrpc_vet_description_s(const char *);
 static int rxrpc_preparse(struct key_preparsed_payload *);
-static int rxrpc_preparse_s(struct key_preparsed_payload *);
 static void rxrpc_free_preparse(struct key_preparsed_payload *);
-static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
 static void rxrpc_destroy(struct key *);
-static void rxrpc_destroy_s(struct key *);
 static void rxrpc_describe(const struct key *, struct seq_file *);
-static void rxrpc_describe_s(const struct key *, struct seq_file *);
 static long rxrpc_read(const struct key *, char *, size_t);
 
 /*
@@ -50,38 +45,6 @@ struct key_type key_type_rxrpc = {
 };
 EXPORT_SYMBOL(key_type_rxrpc);
 
-/*
- * rxrpc server defined keys take ":" as the
- * description and an 8-byte decryption key as the payload
- */
-struct key_type key_type_rxrpc_s = {
-   .name   = "rxrpc_s",
-   .flags  = KEY_TYPE_NET_DOMAIN,
-   .vet_description = rxrpc_vet_description_s,
-   .preparse   = rxrpc_preparse_s,
-   .free_preparse  = rxrpc_free_preparse_s,
-   .instantiate= generic_key_instantiate,
-   .destroy= rxrpc_destroy_s,
-   .describe   = rxrpc_describe_s,
-};
-
-/*
- * Vet the description for an RxRPC server key
- */
-static int rxrpc_vet_description_s(const char *desc)
-{
-   unsigned long num;
-   char *p;
-
-   num = simple_strtoul(desc, &p, 10);
-   if (*p != ':' || num > 65535)
-   return -EINVAL;
-   num = simple_strtoul(p + 1, &p, 10);
-   if (*p || num < 1 || num > 255)
-   return -EINVAL;
-   return 0;
-}
-
 /*
  * parse an RxKAD type XDR format token
  * - the caller guarantees we have at least 4 words
@@ -433,45 +396,6 @@ static void rxrpc_free_preparse(struct 
key_preparsed_payload *prep)
rxrpc_free_token_list(prep->payload.data[0]);
 }
 
-/*
- * Preparse a server secret key.
- *
- * The data should be the 8-byte secret key.
- */
-static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
-{
-   struct crypto_skcipher *ci;
-
-   _enter("%zu", prep->datalen);
-
-   if (prep->datalen != 8)
-   return -EINVAL;
-
-   memcpy(&prep->payload.data[2], prep->data, 8);
-
-   ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
-   if (IS_ERR(ci)) {
-   _leave(" = %ld", PTR_ERR(ci));
-   return PTR_ERR(ci);
-   }
-
-   if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
-   BUG();
-
-   prep->payload.data[0] = ci;
-   _leave(" = 0");
-   return 0;
-}
-
-/*
- * Clean up preparse data.
- */
-static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
-{
-   if (prep->payload.data[0])
-   crypto_free_skcipher(prep->payload.data[0]);
-}
-
 /*
  * dispose of the data dangling from the corpse of a rxrpc key
  */
@@ -480,17 +404,6 @@ static void rxrpc_destroy(st

[PATCH net-next 05/17] rxrpc: Don't retain the server key in the connection

2020-11-23 Thread David Howells
Don't retain a pointer to the server key in the connection, but rather get
it on demand when the server has to deal with a response packet.

This is necessary to implement RxGK (GSSAPI-mediated transport class),
where we can't know which key we'll need until we've challenged the client
and got back the response.

This also means that we don't need to do a key search in the accept path in
softirq mode.

Also, whilst we're at it, allow the security class to ask for a kvno and
encoding-type variant of a server key as RxGK needs different keys for
different encoding types.  Keys of this type have an extra bit in the
description:

    ":::"

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h  |   11 +++---
 net/rxrpc/call_accept.c  |   14 
 net/rxrpc/conn_event.c   |1 -
 net/rxrpc/conn_object.c  |1 -
 net/rxrpc/conn_service.c |2 -
 net/rxrpc/rxkad.c|   57 ++--
 net/rxrpc/security.c |   81 --
 7 files changed, 100 insertions(+), 67 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 3c417ec94e4c..db6e754743fb 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -441,7 +441,6 @@ struct rxrpc_connection {
struct list_headlink;   /* link in master connection 
list */
struct sk_buff_head rx_queue;   /* received conn-level packets 
*/
const struct rxrpc_security *security;  /* applied security module */
-   struct key  *server_key;/* security for this service */
struct crypto_sync_skcipher *cipher;/* encryption handle */
struct rxrpc_crypt  csum_iv;/* packet checksum base */
unsigned long   flags;
@@ -890,8 +889,7 @@ struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct 
rxrpc_peer *,
 struct sk_buff *);
 struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, 
gfp_t);
 void rxrpc_new_incoming_connection(struct rxrpc_sock *, struct 
rxrpc_connection *,
-  const struct rxrpc_security *, struct key *,
-  struct sk_buff *);
+  const struct rxrpc_security *, struct 
sk_buff *);
 void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
 
 /*
@@ -1056,9 +1054,10 @@ extern const struct rxrpc_security rxkad;
 int __init rxrpc_init_security(void);
 void rxrpc_exit_security(void);
 int rxrpc_init_client_conn_security(struct rxrpc_connection *);
-bool rxrpc_look_up_server_security(struct rxrpc_local *, struct rxrpc_sock *,
-  const struct rxrpc_security **, struct key 
**,
-  struct sk_buff *);
+const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
+struct sk_buff *);
+struct key *rxrpc_look_up_server_security(struct rxrpc_connection *,
+ struct sk_buff *, u32, u32);
 
 /*
  * sendmsg.c
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 8df1964db333..382add72c66f 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -261,7 +261,6 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct 
rxrpc_sock *rx,
struct rxrpc_peer *peer,
struct rxrpc_connection 
*conn,
const struct rxrpc_security 
*sec,
-   struct key *key,
struct sk_buff *skb)
 {
struct rxrpc_backlog *b = rx->backlog;
@@ -309,7 +308,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct 
rxrpc_sock *rx,
conn->params.local = rxrpc_get_local(local);
conn->params.peer = peer;
rxrpc_see_connection(conn);
-   rxrpc_new_incoming_connection(rx, conn, sec, key, skb);
+   rxrpc_new_incoming_connection(rx, conn, sec, skb);
} else {
rxrpc_get_connection(conn);
}
@@ -353,7 +352,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct 
rxrpc_local *local,
struct rxrpc_connection *conn;
struct rxrpc_peer *peer = NULL;
struct rxrpc_call *call = NULL;
-   struct key *key = NULL;
 
_enter("");
 
@@ -374,11 +372,13 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct 
rxrpc_local *local,
 */
conn = rxrpc_find_connection_rcu(local, skb, &peer);
 
-   if (!conn && !rxrpc_look_up_server_security(local, rx, &sec, &key, skb))
-   goto no_call;
+   if (!conn) {
+   sec = rxrpc_get_incoming_se

[PATCH net-next 04/17] rxrpc: Support keys with multiple authentication tokens

2020-11-23 Thread David Howells
rxrpc-type keys can have multiple tokens attached for different security
classes.  Currently, rxrpc always picks the first one, whether or not the
security class it indicates is supported.

Add preliminary support for choosing which security class will be used
(this will need to be directed from a higher layer) and go through the
tokens to find one that's supported.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |4 +++-
 net/rxrpc/conn_event.c  |3 ++-
 net/rxrpc/insecure.c|3 ++-
 net/rxrpc/rxkad.c   |5 ++---
 net/rxrpc/security.c|   15 ---
 5 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index dce48162f6c2..3c417ec94e4c 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "protocol.h"
 
 #if 0
@@ -217,7 +218,8 @@ struct rxrpc_security {
void (*exit)(void);
 
/* initialise a connection's security */
-   int (*init_connection_security)(struct rxrpc_connection *);
+   int (*init_connection_security)(struct rxrpc_connection *,
+   struct rxrpc_key_token *);
 
/* prime a connection's packet security */
int (*prime_packet_security)(struct rxrpc_connection *);
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index aff184145ffa..bbf86203ed25 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -333,7 +333,8 @@ static int rxrpc_process_event(struct rxrpc_connection 
*conn,
if (ret < 0)
return ret;
 
-   ret = conn->security->init_connection_security(conn);
+   ret = conn->security->init_connection_security(
+   conn, conn->params.key->payload.data[0]);
if (ret < 0)
return ret;
 
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c
index f6c59f5fae9d..cf3ecffcf424 100644
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -8,7 +8,8 @@
 #include 
 #include "ar-internal.h"
 
-static int none_init_connection_security(struct rxrpc_connection *conn)
+static int none_init_connection_security(struct rxrpc_connection *conn,
+struct rxrpc_key_token *token)
 {
return 0;
 }
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index f114dc2af5cf..404d1323c239 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -49,15 +49,14 @@ static DEFINE_MUTEX(rxkad_ci_mutex);
 /*
  * initialise connection security
  */
-static int rxkad_init_connection_security(struct rxrpc_connection *conn)
+static int rxkad_init_connection_security(struct rxrpc_connection *conn,
+ struct rxrpc_key_token *token)
 {
struct crypto_sync_skcipher *ci;
-   struct rxrpc_key_token *token;
int ret;
 
_enter("{%d},{%x}", conn->debug_id, key_serial(conn->params.key));
 
-   token = conn->params.key->payload.data[0];
conn->security_ix = token->security_index;
 
ci = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c
index 9b1fb9ed0717..0c5168f52bd6 100644
--- a/net/rxrpc/security.c
+++ b/net/rxrpc/security.c
@@ -81,16 +81,17 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection 
*conn)
if (ret < 0)
return ret;
 
-   token = key->payload.data[0];
-   if (!token)
-   return -EKEYREJECTED;
+   for (token = key->payload.data[0]; token; token = token->next) {
+   sec = rxrpc_security_lookup(token->security_index);
+   if (sec)
+   goto found;
+   }
+   return -EKEYREJECTED;
 
-   sec = rxrpc_security_lookup(token->security_index);
-   if (!sec)
-   return -EKEYREJECTED;
+found:
conn->security = sec;
 
-   ret = conn->security->init_connection_security(conn);
+   ret = conn->security->init_connection_security(conn, token);
if (ret < 0) {
conn->security = &rxrpc_no_security;
return ret;




[PATCH net-next 03/17] rxrpc: List the held token types in the key description in /proc/keys

2020-11-23 Thread David Howells
When viewing an rxrpc-type key through /proc/keys, display a list of held
token types.

Signed-off-by: David Howells 
---

 net/rxrpc/key.c |   29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index fb4d2a2fca02..197b4cf46b64 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -31,6 +31,7 @@ static void rxrpc_free_preparse_s(struct 
key_preparsed_payload *);
 static void rxrpc_destroy(struct key *);
 static void rxrpc_destroy_s(struct key *);
 static void rxrpc_describe(const struct key *, struct seq_file *);
+static void rxrpc_describe_s(const struct key *, struct seq_file *);
 static long rxrpc_read(const struct key *, char *, size_t);
 
 /*
@@ -61,7 +62,7 @@ struct key_type key_type_rxrpc_s = {
.free_preparse  = rxrpc_free_preparse_s,
.instantiate= generic_key_instantiate,
.destroy= rxrpc_destroy_s,
-   .describe   = rxrpc_describe,
+   .describe   = rxrpc_describe_s,
 };
 
 /*
@@ -494,6 +495,32 @@ static void rxrpc_destroy_s(struct key *key)
  * describe the rxrpc key
  */
 static void rxrpc_describe(const struct key *key, struct seq_file *m)
+{
+   const struct rxrpc_key_token *token;
+   const char *sep = ": ";
+
+   seq_puts(m, key->description);
+
+   for (token = key->payload.data[0]; token; token = token->next) {
+   seq_puts(m, sep);
+
+   switch (token->security_index) {
+   case RXRPC_SECURITY_RXKAD:
+   seq_puts(m, "ka");
+   break;
+   default: /* we have a ticket we can't encode */
+   seq_printf(m, "%u", token->security_index);
+   break;
+   }
+
+   sep = " ";
+   }
+}
+
+/*
+ * describe the rxrpc server key
+ */
+static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
 {
seq_puts(m, key->description);
 }




[PATCH net-next 02/17] rxrpc: Remove the rxk5 security class as it's now defunct

2020-11-23 Thread David Howells
Remove the rxrpc rxk5 security class as it's now defunct and nothing uses
it anymore.

Signed-off-by: David Howells 
---

 include/keys/rxrpc-type.h |   55 -
 net/rxrpc/key.c   |  468 -
 2 files changed, 523 deletions(-)

diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
index 2b0b15a71228..8e4ced9b4ecf 100644
--- a/include/keys/rxrpc-type.h
+++ b/include/keys/rxrpc-type.h
@@ -31,54 +31,6 @@ struct rxkad_key {
u8  ticket[];   /* the encrypted ticket */
 };
 
-/*
- * Kerberos 5 principal
- * name/name/name@realm
- */
-struct krb5_principal {
-   u8  n_name_parts;   /* N of parts of the name part of the 
principal */
-   char**name_parts;   /* parts of the name part of the 
principal */
-   char*realm; /* parts of the realm part of the 
principal */
-};
-
-/*
- * Kerberos 5 tagged data
- */
-struct krb5_tagged_data {
-   /* for tag value, see /usr/include/krb5/krb5.h
-* - KRB5_AUTHDATA_* for auth data
-* -
-*/
-   s32 tag;
-   u32 data_len;
-   u8  *data;
-};
-
-/*
- * RxRPC key for Kerberos V (type-5 security)
- */
-struct rxk5_key {
-   u64 authtime;   /* time at which auth token 
generated */
-   u64 starttime;  /* time at which auth token 
starts */
-   u64 endtime;/* time at which auth token 
expired */
-   u64 renew_till; /* time to which auth token can 
be renewed */
-   s32 is_skey;/* T if ticket is encrypted in 
another ticket's
-* skey */
-   s32 flags;  /* mask of TKT_FLG_* bits 
(krb5/krb5.h) */
-   struct krb5_principal   client; /* client principal name */
-   struct krb5_principal   server; /* server principal name */
-   u16 ticket_len; /* length of ticket */
-   u16 ticket2_len;/* length of second ticket */
-   u8  n_authdata; /* number of authorisation data 
elements */
-   u8  n_addresses;/* number of addresses */
-   struct krb5_tagged_data session;/* session data; tag is enctype 
*/
-   struct krb5_tagged_data *addresses; /* addresses */
-   u8  *ticket;/* krb5 ticket */
-   u8  *ticket2;   /* second krb5 ticket, if 
related to ticket (via
-* DUPLICATE-SKEY or 
ENC-TKT-IN-SKEY) */
-   struct krb5_tagged_data *authdata;  /* authorisation data */
-};
-
 /*
  * list of tokens attached to an rxrpc key
  */
@@ -87,7 +39,6 @@ struct rxrpc_key_token {
struct rxrpc_key_token *next;   /* the next token in the list */
union {
struct rxkad_key *kad;
-   struct rxk5_key *k5;
};
 };
 
@@ -116,12 +67,6 @@ struct rxrpc_key_data_v1 {
 #define AFSTOKEN_RK_TIX_MAX12000   /* max RxKAD ticket size */
 #define AFSTOKEN_GK_KEY_MAX64  /* max GSSAPI key size */
 #define AFSTOKEN_GK_TOKEN_MAX  16384   /* max GSSAPI token size */
-#define AFSTOKEN_K5_COMPONENTS_MAX 16  /* max K5 components */
-#define AFSTOKEN_K5_NAME_MAX   128 /* max K5 name length */
-#define AFSTOKEN_K5_REALM_MAX  64  /* max K5 realm name length */
-#define AFSTOKEN_K5_TIX_MAX16384   /* max K5 ticket size */
-#define AFSTOKEN_K5_ADDRESSES_MAX  16  /* max K5 addresses */
-#define AFSTOKEN_K5_AUTHDATA_MAX   16  /* max K5 pieces of auth data */
 
 /*
  * Truncate a time64_t to the range from 1970 to 2106 as in the network
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 2e8bd3b97301..fb4d2a2fca02 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -165,391 +165,6 @@ static int rxrpc_preparse_xdr_rxkad(struct 
key_preparsed_payload *prep,
return 0;
 }
 
-static void rxrpc_free_krb5_principal(struct krb5_principal *princ)
-{
-   int loop;
-
-   if (princ->name_parts) {
-   for (loop = princ->n_name_parts - 1; loop >= 0; loop--)
-   kfree(princ->name_parts[loop]);
-   kfree(princ->name_parts);
-   }
-   kfree(princ->realm);
-}
-
-static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td)
-{
-   kfree(td->data);
-}
-
-/*
- * free up an RxK5 token
- */
-static void rxrpc_rxk5_free(struct rxk5_key *rxk5)
-{
-   int loop;
-
-   rxrpc_free_krb5_principal(&rxk5->client);
-   rxrpc_free_krb5_principal(&rxk5->server);
-   rxrpc_free_krb5_tagged(&rxk5->session);
-
-   if (rxk5->addresses) {
-  

[PATCH net 00/17] rxrpc: Prelude to gssapi support

2020-11-23 Thread David Howells



Here are some patches that do some reorganisation of the security class
handling in rxrpc to allow implementation of the RxGK security class that
will allow AF_RXRPC to use GSSAPI-negotiated tokens and better crypto.  The
RxGK security class is not included in this patchset.

It does the following things:

 (1) Add a keyrings patch to provide the original key description, as
 provided to add_key(), to the payload preparser so that it can
 interpret the content on that basis.  Unfortunately, the rxrpc_s key
 type wasn't written to interpret its payload as anything other than a
 string of bytes comprising a key, but for RxGK, more information is
 required as multiple Kerberos enctypes are supported.

 (2) Remove the rxk5 security class key parsing.  The rxk5 class never got
 rolled out in OpenAFS and got replaced with rxgk.

 (3) Support the creation of rxrpc keys with multiple tokens of different
 types.  If some types are not supported, the ENOPKG error is
 suppressed if at least one other token's type is supported.

 (4) Punt the handling of server keys (rxrpc_s type) to the appropriate
 security class.

 (5) Organise the security bits in the rxrpc_connection struct into a
 union to make it easier to override for other classes.

 (6) Move some bits from core code into rxkad that won't be appropriate to
 rxgk.

The patches are tagged here:

git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
rxrpc-next-20201123

and can also be found on the following branch:


http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-next

David
---
David Howells (17):
  keys: Provide the original description to the key preparser
  rxrpc: Remove the rxk5 security class as it's now defunct
  rxrpc: List the held token types in the key description in /proc/keys
  rxrpc: Support keys with multiple authentication tokens
  rxrpc: Don't retain the server key in the connection
  rxrpc: Split the server key type (rxrpc_s) into its own file
  rxrpc: Hand server key parsing off to the security class
  rxrpc: Don't leak the service-side session key to userspace
  rxrpc: Allow security classes to give more info on server keys
  rxrpc: Make the parsing of xdr payloads more coherent
  rxrpc: Ignore unknown tokens in key payload unless no known tokens
  rxrpc: Fix example key name in a comment
  rxrpc: Merge prime_packet_security into init_connection_security
  rxrpc: Don't reserve security header in Tx DATA skbuff
  rxrpc: Organise connection security to use a union
  rxrpc: rxkad: Don't use pskb_pull() to advance through the response packet
  rxrpc: Ask the security class how much space to allow in a packet


 include/keys/rxrpc-type.h |  56 +---
 net/rxrpc/Makefile|   1 +
 net/rxrpc/ar-internal.h   |  63 ++--
 net/rxrpc/call_accept.c   |  14 +-
 net/rxrpc/conn_client.c   |   6 -
 net/rxrpc/conn_event.c|   8 +-
 net/rxrpc/conn_object.c   |   2 -
 net/rxrpc/conn_service.c  |   2 -
 net/rxrpc/insecure.c  |  19 +-
 net/rxrpc/key.c   | 658 --
 net/rxrpc/rxkad.c | 256 ++-
 net/rxrpc/security.c  |  98 --
 net/rxrpc/sendmsg.c   |  45 +--
 net/rxrpc/server_key.c| 143 +
 14 files changed, 519 insertions(+), 852 deletions(-)
 create mode 100644 net/rxrpc/server_key.c




[PATCH net-next 01/17] keys: Provide the original description to the key preparser

2020-11-23 Thread David Howells
Provide the proposed description (add key) or the original description
(update/instantiate key) when preparsing a key so that the key type can
validate it against the data.

This is important for rxrpc server keys as we need to check that they have
the right amount of key material present - and it's better to do that when
the key is loaded rather than deep in trying to process a response packet.

Signed-off-by: David Howells 
cc: Jarkko Sakkinen 
cc: keyri...@vger.kernel.org
---

 include/linux/key-type.h |1 +
 security/keys/key.c  |2 ++
 2 files changed, 3 insertions(+)

diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 2ab2d6d6aeab..7d985a1dfe4a 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -29,6 +29,7 @@ struct kernel_pkey_params;
  * clear the contents.
  */
 struct key_preparsed_payload {
+   const char  *orig_description; /* Actual or proposed description 
(maybe NULL) */
char*description;   /* Proposed key description (or NULL) */
union key_payload payload;  /* Proposed payload */
const void  *data;  /* Raw data */
diff --git a/security/keys/key.c b/security/keys/key.c
index e282c6179b21..ebe752b137aa 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -504,6 +504,7 @@ int key_instantiate_and_link(struct key *key,
int ret;
 
memset(&prep, 0, sizeof(prep));
+   prep.orig_description = key->description;
prep.data = data;
prep.datalen = datalen;
prep.quotalen = key->type->def_datalen;
@@ -854,6 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
goto error_put_type;
 
memset(&prep, 0, sizeof(prep));
+   prep.orig_description = description;
prep.data = payload;
prep.datalen = plen;
prep.quotalen = index_key.type->def_datalen;




Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-11-12 Thread David Howells
Chuck Lever  wrote:

> Really? My understanding of the Linux kernel SUNRPC implementation is
> that it uses asynchronous, even for small data items. Maybe I'm using
> the terminology incorrectly.

Seems to be synchronous, at least in its use of skcipher:

grep -e skcipher *
gss_krb5_crypto.c:#include 
gss_krb5_crypto.c:  struct crypto_sync_skcipher *tfm,
gss_krb5_crypto.c:  if (length % crypto_sync_skcipher_blocksize(tfm) != 0)
gss_krb5_crypto.c:  if (crypto_sync_skcipher_ivsize(tfm) > 
GSS_KRB5_MAX_BLOCKSIZE) {
gss_krb5_crypto.c:  crypto_sync_skcipher_ivsize(tfm));
gss_krb5_crypto.c:  memcpy(local_iv, iv, 
crypto_sync_skcipher_ivsize(tfm));
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, tfm);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, NULL);
gss_krb5_crypto.c:  skcipher_request_set_crypt(req, sg, sg, length, 
local_iv);
gss_krb5_crypto.c:  ret = crypto_skcipher_encrypt(req);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c: struct crypto_sync_skcipher *tfm,
gss_krb5_crypto.c:  if (length % crypto_sync_skcipher_blocksize(tfm) != 0)
gss_krb5_crypto.c:  if (crypto_sync_skcipher_ivsize(tfm) > 
GSS_KRB5_MAX_BLOCKSIZE) {
gss_krb5_crypto.c:  crypto_sync_skcipher_ivsize(tfm));
gss_krb5_crypto.c:  memcpy(local_iv, iv, 
crypto_sync_skcipher_ivsize(tfm));
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, tfm);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, NULL);
gss_krb5_crypto.c:  skcipher_request_set_crypt(req, sg, sg, length, 
local_iv);
gss_krb5_crypto.c:  ret = crypto_skcipher_decrypt(req);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c:  struct skcipher_request *req;
gss_krb5_crypto.c:  struct crypto_sync_skcipher *tfm =
gss_krb5_crypto.c:  crypto_sync_skcipher_reqtfm(desc->req);
gss_krb5_crypto.c:  fraglen = thislen & 
(crypto_sync_skcipher_blocksize(tfm) - 1);
gss_krb5_crypto.c:  skcipher_request_set_crypt(desc->req, desc->infrags, 
desc->outfrags,
gss_krb5_crypto.c:  ret = crypto_skcipher_encrypt(desc->req);
gss_krb5_crypto.c:gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct 
xdr_buf *buf,
gss_krb5_crypto.c:  BUG_ON((buf->len - offset) % 
crypto_sync_skcipher_blocksize(tfm) != 0);
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, tfm);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, NULL);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c:  struct skcipher_request *req;
gss_krb5_crypto.c:  struct crypto_sync_skcipher *tfm =
gss_krb5_crypto.c:  crypto_sync_skcipher_reqtfm(desc->req);
gss_krb5_crypto.c:  fraglen = thislen & 
(crypto_sync_skcipher_blocksize(tfm) - 1);
gss_krb5_crypto.c:  skcipher_request_set_crypt(desc->req, desc->frags, 
desc->frags,
gss_krb5_crypto.c:  ret = crypto_skcipher_decrypt(desc->req);
gss_krb5_crypto.c:gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct 
xdr_buf *buf,
gss_krb5_crypto.c:  BUG_ON((buf->len - offset) % 
crypto_sync_skcipher_blocksize(tfm) != 0);
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, tfm);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, NULL);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c:gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, 
struct xdr_buf *buf,
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, cipher);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, NULL);
gss_krb5_crypto.c:  skcipher_request_set_crypt(req, sg, sg, len, iv);
gss_krb5_crypto.c:  ret = crypto_skcipher_encrypt(req);
gss_krb5_crypto.c:  ret = crypto_skcipher_decrypt(req);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c:  struct crypto_sync_skcipher *cipher, *aux_cipher;
gss_krb5_crypto.c:  blocksize = crypto_sync_skcipher_blocksize(cipher);
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, aux_cipher);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, 
NULL);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_crypto.c:  struct crypto_sync_skcipher *cipher, *aux_cipher;
gss_krb5_crypto.c:  blocksize = crypto_sync_skcipher_blocksize(cipher);
gss_krb5_crypto.c:  skcipher_request_set_sync_tfm(req, aux_cipher);
gss_krb5_crypto.c:  skcipher_request_set_callback(req, 0, NULL, 
NULL);
gss_krb5_crypto.c:  skcipher_request_zero(req);
gss_krb5_keys.c:#include 
gss_krb5_keys.c:struct crypto_sync_skcipher *cipher;
gss_krb5_keys.c:cipher = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 
0, 0);
gss_krb5_keys.c:if (crypto_sync_skcipher_setkey(cipher, inkey->data, 
inkey->len))
gss_krb5_keys.c:crypto_free_sync_skcipher(cipher);
gss_krb5_mech.c:#include 
gss_krb5_mech.c:

Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-11-12 Thread David Howells
Chuck Lever  wrote:

> > There are three main interfaces to it:
> > 
> > (*) I/O crypto: encrypt, decrypt, get_mic and verify_mic.
> > 
> > These all do in-place crypto, using an sglist to define the buffer
> > with the data in it.  Is it necessary to make it able to take separate
> > input and output buffers?
> 
> Hi David, Wondering if these "I/O" APIs use synchronous or async
> crypto under the covers. For small data items like MICs, synchronous
> might be a better choice, especially if asynchronous crypto could
> result in incoming requests getting re-ordered and falling out of
> the GSS sequence number window.
> 
> What say ye?

For the moment I'm using synchronous APIs as that's what sunrpc is using (I
borrowed the basic code from there).

It would be interesting to consider using async, but there's a potential
issue.  For the simplified profile, encryption and integrity checksum
generation can be done simultaneously, but decryption and verification can't.
For the AES-2 profile, the reverse is true.

For my purposes in rxrpc, async mode isn't actually that useful since I'm only
doing the contents of a UDP packet at a time.  Either I'm encrypting with the
intention of immediate transmission or decrypting with the intention of
immediately using the data, so I'm in a context where I can wait anyway.

What might get me more of a boost would be to encrypt the app data directly
into a UDP packet and decrypt the UDP packet directly into the app buffers.
This is easier said than done, though, as there's typically security metadata
inserted into the packet inside the encrypted region.

David



Re: [RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-11-12 Thread David Howells
Would it be possible/practical to make the skcipher encrypt functions take an
offset into the scatterlist rather than always starting at the beginning?

David



[PATCH 18/18] rxgk: Support OpenAFS's rxgk implementation

2020-11-12 Thread David Howells


---

 net/rxrpc/ar-internal.h |1 
 net/rxrpc/key.c |  136 +++
 net/rxrpc/rxgk.c|   25 +
 net/rxrpc/rxgk_app.c|  135 +++
 net/rxrpc/rxgk_common.h |2 +
 net/rxrpc/security.c|3 +
 6 files changed, 302 insertions(+)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 3f2469714422..ed44ceeeab68 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1070,6 +1070,7 @@ void rxrpc_peer_init_rtt(struct rxrpc_peer *);
 /*
  * rxgk.c
  */
+extern const struct rxrpc_security rxgk_openafs;
 extern const struct rxrpc_security rxgk_yfs;
 
 /*
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index b7f154701d97..3479ef285980 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -147,6 +147,135 @@ static time64_t rxrpc_s64_to_time64(s64 time_in_100ns)
return neg ? -tmp : tmp;
 }
 
+/*
+ * Parse an OpenAFS RxGK type XDR format token
+ * - the caller guarantees we have at least 4 words
+ *
+ * struct token_rxgk {
+ * afs_int64   0 gk_viceid;
+ * afs_int32   2 gk_enctype;
+ * afs_int32   3 gk_level;
+ * afs_uint32  4 gk_lifetime;
+ * afs_uint32  5 gk_bytelife;
+ * afs_int64   6 gk_expiration;
+ * opaque  8 gk_token;
+ * opaque  9 gk_k0;
+ * };
+ */
+static int rxrpc_preparse_xdr_rxgk(struct key_preparsed_payload *prep,
+  size_t datalen,
+  const __be32 *xdr, unsigned int toklen)
+{
+   struct rxrpc_key_token *token, **pptoken;
+   time64_t expiry;
+   size_t plen;
+   const __be32 *ticket, *key;
+   u32 tktlen, keylen;
+
+   _enter(",{%x,%x,%x,%x},%x",
+  ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
+  toklen);
+
+   if (toklen / 4 < 10)
+   goto reject;
+
+   ticket = xdr + 9;
+   tktlen = ntohl(ticket[-1]);
+   _debug("tktlen: %x", tktlen);
+   tktlen = round_up(tktlen, 4);
+   if (toklen < 10 * 4 + tktlen)
+   goto reject;
+
+   key = ticket + (tktlen / 4) + 1;
+   keylen = ntohl(key[-1]);
+   _debug("keylen: %x", keylen);
+   keylen = round_up(keylen, 4);
+   if (10 * 4 + tktlen + keylen != toklen) {
+   kleave(" = -EKEYREJECTED [%x!=%x, %x,%x]",
+  10 * 4 + tktlen + keylen, toklen, tktlen, keylen);
+   goto reject;
+   }
+
+   plen = sizeof(*token) + sizeof(*token->rxgk) + tktlen + keylen;
+   prep->quotalen = datalen + plen;
+
+   plen -= sizeof(*token);
+   token = kzalloc(sizeof(*token), GFP_KERNEL);
+   if (!token)
+   goto nomem;
+
+   token->rxgk = kzalloc(sizeof(struct rxgk_key) + keylen, GFP_KERNEL);
+   if (!token->rxgk)
+   goto nomem_token;
+
+   token->security_index   = RXRPC_SECURITY_RXGK;
+   token->rxgk->begintime  = 0;
+   token->rxgk->endtime= xdr_dec64(xdr + 6);
+   token->rxgk->level  = ntohl(xdr[3]);
+   if (token->rxgk->level > RXRPC_SECURITY_ENCRYPT)
+   goto reject_token;
+   token->rxgk->lifetime   = ntohl(xdr[4]);
+   token->rxgk->bytelife   = ntohl(xdr[5]);
+   token->rxgk->enctype= ntohl(xdr[2]);
+   token->rxgk->key.len= ntohl(key[-1]);
+   token->rxgk->key.data   = token->rxgk->_key;
+   token->rxgk->ticket.len = ntohl(ticket[-1]);
+
+   expiry = rxrpc_s64_to_time64(token->rxgk->endtime);
+   if (expiry < 0)
+   goto expired;
+   if (expiry < prep->expiry)
+   prep->expiry = expiry;
+
+   memcpy(token->rxgk->key.data, key, token->rxgk->key.len);
+
+   /* Pad the ticket so that we can use it directly in XDR */
+   token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
+  GFP_KERNEL);
+   if (!token->rxgk->ticket.data)
+   goto nomem_yrxgk;
+   memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
+
+   _debug("SCIX: %u",  token->security_index);
+   _debug("LIFE: %llx",token->rxgk->lifetime);
+   _debug("BYTE: %llx",token->rxgk->bytelife);
+   _debug("ENC : %u",  token->rxgk->enctype);
+   _debug("LEVL: %u",  token->rxgk->level);
+   _debug("KLEN: %u",  token->rxgk->key.len);
+   _debug("TLEN: %u",  token->rxgk->ticket.len);
+   _debug("KEY0: %*phN",   token->rxgk->key.len, token->rxgk->key.data);
+   _debug("TICK: %*phN",
+  min_t(u32, token->rxgk->ticket.len, 32), 
token->rxgk->ticket.data);
+
+   /* count the number of tokens attached */
+   prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 
1);
+
+   /* attach the data */
+   for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
+*pptoken;
+pptoken = &(*p

[PATCH 17/18] rxrpc: rxgk: Implement connection rekeying

2020-11-12 Thread David Howells
Implement rekeying of connections with the RxGK security class.  This
involves regenerating the keys with a different key number as part of the
input data after a certain amount of time or a certain amount of bytes
encrypted.  Rekeying may be triggered by either end.

The LSW of the key number is inserted into the security-specific field in
the RX header, and we try and expand it to 32-bits to make it last longer.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |6 ++
 net/rxrpc/conn_object.c |2 +
 net/rxrpc/rxgk.c|  156 +--
 3 files changed, 157 insertions(+), 7 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index efdb3334ad88..3f2469714422 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -462,11 +462,15 @@ struct rxrpc_connection {
u32 nonce;  /* response re-use preventer */
} rxkad;
struct {
-   struct rxgk_context *keys[1];
+   struct rxgk_context *keys[4]; /* (Re-)keying buffer */
u64 start_time; /* The start time for TK 
derivation */
u8  nonce[20];  /* Response re-use preventer */
+   u32 key_number; /* Current key number */
} rxgk;
};
+   rwlock_tsecurity_lock;  /* Lock allowing modification 
of security */
+   struct mutexrekeying_lock;  /* Lock allowing rekeying */
+
unsigned long   flags;
unsigned long   events;
unsigned long   idle_timestamp; /* Time at which last became 
idle */
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 8dd1ef25b98f..ff60526d0e0f 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -47,6 +47,8 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
INIT_LIST_HEAD(&conn->link);
skb_queue_head_init(&conn->rx_queue);
conn->security = &rxrpc_no_security;
+   rwlock_init(&conn->security_lock);
+   mutex_init(&conn->rekeying_lock);
spin_lock_init(&conn->state_lock);
conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
conn->size_align = 4;
diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
index 703e46e8b508..0aa6da93b8d4 100644
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -90,11 +90,153 @@ static void rxgk_describe_server_key(const struct key 
*key, struct seq_file *m)
seq_printf(m, ": %s", krb5->name);
 }
 
+/*
+ * Handle rekeying the connection when the we see our limits overrun or when
+ * the far side decided to rekey.
+ *
+ * Returns a ref on the context if successful or -ESTALE if the key is out of
+ * date.
+ */
+static struct rxgk_context *rxgk_rekey(struct rxrpc_connection *conn,
+  const u16 *specific_key_number)
+{
+   struct rxgk_context *gk, *dead = NULL;
+   unsigned int key_number, current_key, mask = 
ARRAY_SIZE(conn->rxgk.keys) - 1;
+   bool crank = false;
+
+   _enter("%d", specific_key_number ? *specific_key_number : -1);
+
+   mutex_lock(&conn->rekeying_lock);
+
+   current_key = conn->rxgk.key_number;
+   if (!specific_key_number) {
+   key_number = current_key;
+   } else {
+   if (*specific_key_number == (u16)current_key)
+   key_number = current_key;
+   else if (*specific_key_number == (u16)(current_key - 1))
+   key_number = current_key - 1;
+   else if (*specific_key_number == (u16)(current_key + 1))
+   goto crank_window;
+   else
+   goto bad_key;
+   }
+
+   gk = conn->rxgk.keys[key_number & mask];
+   if (!gk)
+   goto generate_key;
+   if (!specific_key_number &&
+   test_bit(RXGK_TK_NEEDS_REKEY, &gk->flags))
+   goto crank_window;
+
+grab:
+   refcount_inc(&gk->usage);
+   mutex_unlock(&conn->rekeying_lock);
+   rxgk_put(dead);
+   return gk;
+
+crank_window:
+   if (current_key == UINT_MAX)
+   goto bad_key;
+   if (current_key + 1 == UINT_MAX)
+   set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
+
+   key_number = current_key + 1;
+   if (WARN_ON(conn->rxgk.keys[key_number & mask]))
+   goto bad_key;
+   crank = true;
+
+generate_key:
+   gk = conn->rxgk.keys[current_key & mask];
+   gk = rxgk_generate_transport_key(conn, gk->key, key_number, GFP_NOFS);
+   if (IS_ERR(gk)) {
+   mutex_unlock(&conn->rekeying_lock);
+   return gk;
+ 

[PATCH 07/18] crypto/krb5: Implement the AES enctypes from rfc3962

2020-11-12 Thread David Howells
Implement the aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96 enctypes
from rfc3962, using the rfc3961 kerberos 5 simplified crypto scheme.

Signed-off-by: David Howells 
---

 crypto/krb5/Makefile  |3 +
 crypto/krb5/internal.h|6 ++
 crypto/krb5/main.c|2 +
 crypto/krb5/rfc3962_aes.c |  140 +
 4 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 crypto/krb5/rfc3962_aes.c

diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index 67824c44aac3..b81e2efac3c8 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -6,6 +6,7 @@
 krb5-y += \
kdf.o \
main.o \
-   rfc3961_simplified.o
+   rfc3961_simplified.o \
+   rfc3962_aes.o
 
 obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index 20b506327491..5d55a574536e 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -120,3 +120,9 @@ int rfc3961_verify_mic(const struct krb5_enctype *krb5,
   struct scatterlist *sg, unsigned nr_sg,
   size_t *_offset, size_t *_len,
   int *_error_code);
+
+/*
+ * rfc3962_aes.c
+ */
+extern const struct krb5_enctype krb5_aes128_cts_hmac_sha1_96;
+extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96;
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index 97b28e40f6d7..bce47580c33f 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -18,6 +18,8 @@ MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
 static const struct krb5_enctype *const krb5_supported_enctypes[] = {
+   &krb5_aes128_cts_hmac_sha1_96,
+   &krb5_aes256_cts_hmac_sha1_96,
 };
 
 /**
diff --git a/crypto/krb5/rfc3962_aes.c b/crypto/krb5/rfc3962_aes.c
new file mode 100644
index ..99297a698178
--- /dev/null
+++ b/crypto/krb5/rfc3962_aes.c
@@ -0,0 +1,140 @@
+/* rfc3962 Advanced Encryption Standard (AES) Encryption for Kerberos 5
+ *
+ * Parts borrowed from net/sunrpc/auth_gss/.
+ */
+/*
+ * COPYRIGHT (c) 2008
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * RxGK bits:
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "inte

[PATCH 03/18] crypto/krb5: Provide infrastructure and key derivation

2020-11-12 Thread David Howells
Provide key derivation interface functions and a helper to implement the
PRF+ function from rfc4402.

Signed-off-by: David Howells 
---

 crypto/krb5/Makefile  |1 
 crypto/krb5/kdf.c |  223 +
 include/crypto/krb5.h |   29 ++
 3 files changed, 253 insertions(+)
 create mode 100644 crypto/krb5/kdf.c

diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index 071ce2ff82e5..b764c4d09bf2 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -4,6 +4,7 @@
 #
 
 krb5-y += \
+   kdf.o \
main.o
 
 obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
diff --git a/crypto/krb5/kdf.c b/crypto/krb5/kdf.c
new file mode 100644
index ..8ef7ea31ee8a
--- /dev/null
+++ b/crypto/krb5/kdf.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Kerberos key derivation.
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include "internal.h"
+
+/**
+ * crypto_krb5_free_enc_keys - Free an encryption keypair
+ * @e: The key pair to free.
+ */
+void crypto_krb5_free_enc_keys(struct krb5_enc_keys *e)
+{
+   if (e->Ke)
+   crypto_free_sync_skcipher(e->Ke);
+   if (e->Ki)
+   crypto_free_shash(e->Ki);
+   e->Ke = NULL;
+   e->Ki = NULL;
+}
+EXPORT_SYMBOL(crypto_krb5_free_enc_keys);
+
+/**
+ * crypto_krb5_calc_PRFplus - Calculate PRF+ [RFC4402]
+ * @krb5: The encryption type to use
+ * @K: The protocol key for the pseudo-random function
+ * @L: The length of the output
+ * @S: The input octet string
+ * @result: Result buffer, sized to krb5->prf_len
+ * @gfp: Allocation restrictions
+ *
+ * Calculate the kerberos pseudo-random function, PRF+() by the following
+ * method:
+ *
+ *  PRF+(K, L, S) = truncate(L, T1 || T2 || .. || Tn)
+ *  Tn = PRF(K, n || S)
+ *  [rfc4402 sec 2]
+ */
+int crypto_krb5_calc_PRFplus(const struct krb5_enctype *krb5,
+const struct krb5_buffer *K,
+unsigned int L,
+const struct krb5_buffer *S,
+struct krb5_buffer *result,
+gfp_t gfp)
+{
+   struct krb5_buffer T_series, Tn, n_S;
+   void *buffer;
+   int ret, n = 1;
+
+   Tn.len = krb5->prf_len;
+   T_series.len = 0;
+   n_S.len = 4 + S->len;
+
+   buffer = kzalloc(round16(L + Tn.len) + round16(n_S.len), gfp);
+   if (!buffer)
+   return -ENOMEM;
+
+   T_series.data = buffer;
+   n_S.data = buffer + round16(L + Tn.len);
+   memcpy(n_S.data + 4, S->data, S->len);
+
+   while (T_series.len < L) {
+   *(__be32 *)(n_S.data) = htonl(n);
+   Tn.data = T_series.data + Tn.len * (n - 1);
+   ret = krb5->profile->calc_PRF(krb5, K, &n_S, &Tn, gfp);
+   if (ret < 0)
+   goto err;
+   T_series.len += Tn.len;
+   n++;
+   }
+
+   /* Truncate to L */
+   memcpy(result->data, T_series.data, L);
+   ret = 0;
+
+err:
+   kfree_sensitive(buffer);
+   return ret;
+}
+EXPORT_SYMBOL(crypto_krb5_calc_PRFplus);
+
+/**
+ * crypto_krb5_get_Kc - Derive key Kc and install into a hash
+ * @krb5: The encryption type to use
+ * @TK: The base key
+ * @usage: The key usage number
+ * @key: Prepped buffer to store the key into
+ * @_shash: Where to put the hash (or NULL if not wanted)
+ * @gfp: Allocation restrictions
+ *
+ * Derive the Kerberos Kc checksumming key and, optionally, allocate a hash and
+ * install the key into it, returning the hash.  The key is stored into the
+ * prepared buffer.
+ */
+int crypto_krb5_get_Kc(const struct krb5_enctype *krb5,
+  const struct krb5_buffer *TK,
+  u32 usage,
+  struct krb5_buffer *key,
+  struct crypto_shash **_shash,
+  gfp_t gfp)
+{
+   struct crypto_shash *shash;
+   int ret;
+   u8 buf[CRYPTO_MINALIGN] __aligned(CRYPTO_MINALIGN);
+   struct krb5_buffer usage_constant = { .len = 5, .data = buf };
+
+   *(__be32 *)buf = cpu_to_be32(usage);
+   buf[4] = KEY_USAGE_SEED_CHECKSUM;
+
+   key->len = krb5->Kc_len;
+   ret = krb5->profile->calc_Kc(krb5, TK, &usage_constant, key, gfp);
+   if (ret < 0)
+   return ret;
+
+   if (_shash) {
+   shash = crypto_alloc_shash(krb5->cksum_name, 0, 0);
+   if (IS_ERR(shash))
+   return (PTR_ERR(shash) == -ENOENT) ? -ENOPKG : 
PTR_ERR(shash);
+   *_shash = shash;
+   ret = crypto_shash_setkey(shash, key->data, key->len);
+   }
+
+   return ret;
+}
+EXPORT_SYMBOL(crypto_krb5_get_K

[PATCH 16/18] rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)

2020-11-12 Thread David Howells
Implement the basic parts of the yfs-rxgk security class (security index 6)
to support GSSAPI-negotiated security.

Signed-off-by: David Howells 
---

 include/trace/events/rxrpc.h |4 
 net/rxrpc/Makefile   |2 
 net/rxrpc/ar-internal.h  |   12 
 net/rxrpc/rxgk.c | 1063 ++
 net/rxrpc/rxgk_app.c |  289 +++
 net/rxrpc/rxgk_common.h  |  118 +
 net/rxrpc/security.c |3 
 7 files changed, 1491 insertions(+)
 create mode 100644 net/rxrpc/rxgk.c
 create mode 100644 net/rxrpc/rxgk_app.c

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index e70c90116eda..dd541c6d5ea3 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -210,6 +210,8 @@ enum rxrpc_tx_point {
rxrpc_tx_point_call_data_nofrag,
rxrpc_tx_point_call_final_resend,
rxrpc_tx_point_conn_abort,
+   rxrpc_tx_point_rxgk_challenge,
+   rxrpc_tx_point_rxgk_response,
rxrpc_tx_point_rxkad_challenge,
rxrpc_tx_point_rxkad_response,
rxrpc_tx_point_reject,
@@ -440,6 +442,8 @@ enum rxrpc_tx_point {
EM(rxrpc_tx_point_call_final_resend,"CallFinalResend") \
EM(rxrpc_tx_point_conn_abort,   "ConnAbort") \
EM(rxrpc_tx_point_reject,   "Reject") \
+   EM(rxrpc_tx_point_rxgk_challenge,   "RxGKChall") \
+   EM(rxrpc_tx_point_rxgk_response,"RxGKResp") \
EM(rxrpc_tx_point_rxkad_challenge,  "RxkadChall") \
EM(rxrpc_tx_point_rxkad_response,   "RxkadResp") \
EM(rxrpc_tx_point_version_keepalive,"VerKeepalive") \
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile
index 08636858e77f..4be98775dc7f 100644
--- a/net/rxrpc/Makefile
+++ b/net/rxrpc/Makefile
@@ -37,4 +37,6 @@ rxrpc-$(CONFIG_RXKAD) += rxkad.o
 rxrpc-$(CONFIG_SYSCTL) += sysctl.o
 
 rxrpc-$(CONFIG_RXGK) += \
+   rxgk.o \
+   rxgk_app.o \
rxgk_kdf.o
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 4e0766b4a714..efdb3334ad88 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -37,6 +37,7 @@ struct rxrpc_crypt {
 
 struct key_preparsed_payload;
 struct rxrpc_connection;
+struct rxgk_context;
 
 /*
  * Mark applied to socket buffers in skb->mark.  skb->priority is used
@@ -264,6 +265,10 @@ struct rxrpc_security {
 
/* clear connection security */
void (*clear)(struct rxrpc_connection *);
+
+   /* Default ticket -> key decoder */
+   int (*default_decode_ticket)(struct sk_buff *, unsigned int, unsigned 
int,
+u32 *, struct key **);
 };
 
 /*
@@ -457,7 +462,9 @@ struct rxrpc_connection {
u32 nonce;  /* response re-use preventer */
} rxkad;
struct {
+   struct rxgk_context *keys[1];
u64 start_time; /* The start time for TK 
derivation */
+   u8  nonce[20];  /* Response re-use preventer */
} rxgk;
};
unsigned long   flags;
@@ -1056,6 +1063,11 @@ void rxrpc_peer_add_rtt(struct rxrpc_call *, enum 
rxrpc_rtt_rx_trace, int,
 unsigned long rxrpc_get_rto_backoff(struct rxrpc_peer *, bool);
 void rxrpc_peer_init_rtt(struct rxrpc_peer *);
 
+/*
+ * rxgk.c
+ */
+extern const struct rxrpc_security rxgk_yfs;
+
 /*
  * rxkad.c
  */
diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
new file mode 100644
index ..703e46e8b508
--- /dev/null
+++ b/net/rxrpc/rxgk.c
@@ -0,0 +1,1063 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* GSSAPI-based RxRPC security
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include "ar-internal.h"
+#include "rxgk_common.h"
+
+struct rxgk_header {
+   __be32  epoch;
+   __be32  cid;
+   __be32  call_number;
+   __be32  seq;
+   __be32  sec_index;
+   __be32  data_len;
+} __packed;
+
+struct rxgk_response {
+   __be64  start_time;
+   __be32  token_len;
+} __packed;
+
+/*
+ * Parse the information from a server key
+ */
+static int rxgk_preparse_server_key(struct key_preparsed_payload *prep)
+{
+   const struct krb5_enctype *krb5;
+   struct krb5_buffer *server_key = (void *)&prep->payload.data[2];
+   unsigned int service, sec_class, kvno, enctype;
+   int n = 0;
+
+   _enter("%zu", prep->datalen);
+
+   if (sscanf(prep->orig_description, "%u:%u:%u:%u%n",
+  &service, &sec_class, &kvno, &enctype, &n) != 4)
+   return -EINVAL;
+
+   if (prep->orig_description[n])
+ 

[PATCH 15/18] rxrpc: rxgk: Provide infrastructure and key derivation

2020-11-12 Thread David Howells
Provide some infrastructure for implementing the RxGK transport security
class:

 (1) A definition of an encoding type, including:

- Relevant crypto-layer names
- Lengths of the crypto keys and checksums involved
- Crypto functions specific to the encoding type
- Crypto scheme used for that type

 (2) A definition of a crypto scheme, including:

- Underlying crypto handlers
- The pseudo-random function, PRF, used in base key derivation
- Functions for deriving usage keys Kc, Ke and Ki
- Functions for en/decrypting parts of an sk_buff

 (3) A key context, with the usage keys required for a derivative of a
 transport key for a specific key number.  This includes keys for
 securing packets for transmission, extracting received packets and
 dealing with response packets.

 (3) A function to look up an encoding type by number.

 (4) A function to set up a key context and derive the keys.

 (5) A function to set up the keys required to extract the ticket obtained
 from the GSS negotiation in the server.

 (6) Miscellaneous functions for context handling.

The keys and key derivation functions are described in:

tools.ietf.org/html/draft-wilkinson-afs3-rxgk-11

Signed-off-by: David Howells 
---

 net/rxrpc/Kconfig   |   10 ++
 net/rxrpc/Makefile  |3 +
 net/rxrpc/ar-internal.h |3 +
 net/rxrpc/rxgk_common.h |   44 
 net/rxrpc/rxgk_kdf.c|  271 +++
 5 files changed, 331 insertions(+)
 create mode 100644 net/rxrpc/rxgk_common.h
 create mode 100644 net/rxrpc/rxgk_kdf.c

diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig
index d706bb408365..62ff4b373d03 100644
--- a/net/rxrpc/Kconfig
+++ b/net/rxrpc/Kconfig
@@ -57,3 +57,13 @@ config RXKAD
  through the use of the key retention service.
 
  See Documentation/networking/rxrpc.rst.
+
+config RXGK
+   bool "RxRPC GSSAPI security"
+   depends on AF_RXRPC
+   depends on CRYPTO_KRB5
+   help
+ Provide the GSSAPI-based RxGK security class for AFS.  Keys are added
+ with add_key().
+
+ See Documentation/networking/rxrpc.rst.
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile
index b11281bed2a4..08636858e77f 100644
--- a/net/rxrpc/Makefile
+++ b/net/rxrpc/Makefile
@@ -35,3 +35,6 @@ rxrpc-y := \
 rxrpc-$(CONFIG_PROC_FS) += proc.o
 rxrpc-$(CONFIG_RXKAD) += rxkad.o
 rxrpc-$(CONFIG_SYSCTL) += sysctl.o
+
+rxrpc-$(CONFIG_RXGK) += \
+   rxgk_kdf.o
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index a3091a10b7c5..4e0766b4a714 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -456,6 +456,9 @@ struct rxrpc_connection {
struct rxrpc_crypt csum_iv; /* packet checksum base 
*/
u32 nonce;  /* response re-use preventer */
} rxkad;
+   struct {
+   u64 start_time; /* The start time for TK 
derivation */
+   } rxgk;
};
unsigned long   flags;
unsigned long   events;
diff --git a/net/rxrpc/rxgk_common.h b/net/rxrpc/rxgk_common.h
new file mode 100644
index ..3047ad531877
--- /dev/null
+++ b/net/rxrpc/rxgk_common.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* rxgk common bits
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#include 
+#include 
+#include 
+
+/*
+ * Per-key number context.  This is replaced when the connection is rekeyed.
+ */
+struct rxgk_context {
+   refcount_t  usage;
+   unsigned intkey_number; /* Rekeying number (goes in the 
rx header) */
+   unsigned long   flags;
+#define RXGK_TK_NEEDS_REKEY0   /* Set if this needs rekeying */
+   unsigned long   expiry; /* Expiration time of this key 
*/
+   long long   bytes_remaining; /* Remaining Tx lifetime of 
this key */
+   const struct krb5_enctype *krb5;/* RxGK encryption type */
+   const struct rxgk_key   *key;
+
+   /* We need up to 7 keys derived from the transport key, but we don't
+* actually need the transport key.  Each key is derived by
+* DK(TK,constant).
+*/
+   struct krb5_enc_keystx_enc; /* Transmission key */
+   struct krb5_enc_keysrx_enc; /* Reception key */
+   struct crypto_shash *tx_Kc; /* Transmission checksum key */
+   struct crypto_shash *rx_Kc; /* Reception checksum key */
+   struct krb5_enc_keysresp_enc;   /* Response packet enc key */
+};
+
+/*
+ * rxgk_kdf.c
+ */
+struct rxgk_context *rxgk_generate_transport_key(struct rxrpc_connection *,
+const struct rxgk_key *, 
unsigned in

[PATCH 12/18] crypto/krb5: Implement the Camellia enctypes from rfc6803

2020-11-12 Thread David Howells
Implement the camellia128-cts-cmac and camellia256-cts-cmac enctypes from
rfc6803.

Note that the test vectors in rfc6803 for encryption are incomplete,
lacking the key usage number needed to derive Ke and Ki, and there are
errata for this:

https://www.rfc-editor.org/errata_search.php?rfc=6803

Signed-off-by: David Howells 
---

 crypto/krb5/Kconfig|3 
 crypto/krb5/Makefile   |3 
 crypto/krb5/internal.h |6 +
 crypto/krb5/main.c |2 
 crypto/krb5/rfc6803_camellia.c |  249 
 crypto/krb5/selftest_data.c|  135 ++
 include/crypto/krb5.h  |4 +
 7 files changed, 401 insertions(+), 1 deletion(-)
 create mode 100644 crypto/krb5/rfc6803_camellia.c

diff --git a/crypto/krb5/Kconfig b/crypto/krb5/Kconfig
index 5607c0c81049..6c0edf659c8f 100644
--- a/crypto/krb5/Kconfig
+++ b/crypto/krb5/Kconfig
@@ -3,12 +3,15 @@ config CRYPTO_KRB5
select CRYPTO_MANAGER
select CRYPTO_SKCIPHER
select CRYPTO_HASH_INFO
+   select CRYPTO_HMAC
+   select CRYPTO_CMAC
select CRYPTO_SHA1
select CRYPTO_SHA256
select CRYPTO_SHA512
select CRYPTO_CBC
select CRYPTO_CTS
select CRYPTO_AES
+   select CRYPTO_CAMELLIA
help
  Provide Kerberos-5-based security.
 
diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index 85763131f7b6..974e0bcef91d 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -8,7 +8,8 @@ krb5-y += \
main.o \
rfc3961_simplified.o \
rfc3962_aes.o \
-   rfc8009_aes2.o
+   rfc8009_aes2.o \
+   rfc6803_camellia.o
 
 krb5-$(CONFIG_CRYPTO_KRB5_SELFTESTS) += \
selftest.o \
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index e64f5e58199f..83662abc0765 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -158,6 +158,12 @@ int rfc3961_verify_mic(const struct krb5_enctype *krb5,
 extern const struct krb5_enctype krb5_aes128_cts_hmac_sha1_96;
 extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96;
 
+/*
+ * rfc6803_camellia.c
+ */
+extern const struct krb5_enctype krb5_camellia128_cts_cmac;
+extern const struct krb5_enctype krb5_camellia256_cts_cmac;
+
 /*
  * rfc8009_aes2.c
  */
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index 9914d3417c21..b531eafb6db2 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -22,6 +22,8 @@ static const struct krb5_enctype *const 
krb5_supported_enctypes[] = {
&krb5_aes256_cts_hmac_sha1_96,
&krb5_aes128_cts_hmac_sha256_128,
&krb5_aes256_cts_hmac_sha384_192,
+   &krb5_camellia128_cts_cmac,
+   &krb5_camellia256_cts_cmac,
 };
 
 /**
diff --git a/crypto/krb5/rfc6803_camellia.c b/crypto/krb5/rfc6803_camellia.c
new file mode 100644
index ..adcb9c6481a3
--- /dev/null
+++ b/crypto/krb5/rfc6803_camellia.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* rfc6803 Camellia Encryption for Kerberos 5
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include "internal.h"
+
+/*
+ * Calculate the key derivation function KDF-FEEDBACK_CMAC(key, constant)
+ *
+ * n = ceiling(k / 128)
+ * K(0) = zeros
+ * K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k)
+ * DR(key, constant) = k-truncate(K(1) | K(2) | ... | K(n))
+ * KDF-FEEDBACK-CMAC(key, constant) = random-to-key(DR(key, constant))
+ *
+ * [rfc6803 sec 3]
+ */
+static int rfc6803_calc_KDF_FEEDBACK_CMAC(const struct krb5_enctype *krb5,
+ const struct krb5_buffer *key,
+ const struct krb5_buffer *constant,
+ struct krb5_buffer *result,
+ gfp_t gfp)
+{
+   struct crypto_shash *shash;
+   struct krb5_buffer K, data;
+   struct shash_desc *desc;
+   __be32 tmp;
+   size_t bsize, offset, seg;
+   void *buffer;
+   u32 i = 0, k = result->len * 8;
+   u8 *p;
+   int ret = -ENOMEM;
+
+   shash = crypto_alloc_shash(krb5->cksum_name, 0, 0);
+   if (IS_ERR(shash))
+   return (PTR_ERR(shash) == -ENOENT) ? -ENOPKG : PTR_ERR(shash);
+   ret = crypto_shash_setkey(shash, key->data, key->len);
+   if (ret < 0)
+   goto error_shash;
+
+   ret = -ENOMEM;
+   K.len = crypto_shash_digestsize(shash);
+   data.len = K.len + 4 + constant->len + 1 + 4;
+   bsize = krb5_shash_size(shash) +
+   krb5_digest_size(shash) +
+   crypto_roundup(K.len) +
+   crypto_roundup(data.len);
+   buffer = kzalloc(bsize, GFP_NOFS);
+   if (!buffer)
+   goto error_shash;
+
+   

[PATCH 14/18] rxrpc: Add YFS RxGK (GSSAPI) security class

2020-11-12 Thread David Howells
Add support for the YFS-variant RxGK security class to support
GSSAPI-derived authentication.  This also allows the use of better crypto
over the rxkad security class.

The key payload is XDR encoded of the form:

typedef int64_t opr_time;

const AFSTOKEN_RK_TIX_MAX = 12000;  /* Matches entry in rxkad.h */

struct token_rxkad {
afs_int32 viceid;
afs_int32 kvno;
afs_int64 key;
afs_int32 begintime;
afs_int32 endtime;
afs_int32 primary_flag;
opaque ticket;
};

struct token_rxgk {
opr_time begintime;
opr_time endtime;
afs_int64 level;
afs_int64 lifetime;
afs_int64 bytelife;
afs_int64 enctype;
opaque key<>;
opaque ticket<>;
};

const AFSTOKEN_UNION_NOAUTH = 0;
const AFSTOKEN_UNION_KAD = 2;
const AFSTOKEN_UNION_YFSGK = 6;

union ktc_tokenUnion switch (afs_int32 type) {
case AFSTOKEN_UNION_KAD:
token_rxkad kad;
case AFSTOKEN_UNION_YFSGK:
token_rxgk  gk;
};

const AFSTOKEN_LENGTH_MAX = 16384;
typedef opaque token_opaque;

const AFSTOKEN_MAX = 8;
const AFSTOKEN_CELL_MAX = 64;

struct ktc_setTokenData {
afs_int32 flags;
string cell;
token_opaque tokens;
};

The parser for the basic token struct is already present, as is the rxkad
token type.  This adds a parser for the rxgk token type.

Signed-off-by: David Howells 
---

 include/keys/rxrpc-type.h |   17 
 net/rxrpc/key.c   |  183 +
 2 files changed, 200 insertions(+)

diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
index 333c0f49a9cd..0ddbe197a261 100644
--- a/include/keys/rxrpc-type.h
+++ b/include/keys/rxrpc-type.h
@@ -9,6 +9,7 @@
 #define _KEYS_RXRPC_TYPE_H
 
 #include 
+#include 
 
 /*
  * key type for AF_RXRPC keys
@@ -31,6 +32,21 @@ struct rxkad_key {
u8  ticket[];   /* the encrypted ticket */
 };
 
+/*
+ * RxRPC key for YFS-RxGK (type-6 security)
+ */
+struct rxgk_key {
+   s64 begintime;  /* Time at which the ticket starts */
+   s64 endtime;/* Time at which the ticket ends */
+   u64 lifetime;   /* Maximum lifespan of a connection 
(seconds) */
+   u64 bytelife;   /* Maximum number of bytes on a 
connection */
+   unsigned intenctype;/* Encoding type */
+   s8  level;  /* Negotiated security 
RXRPC_SECURITY_PLAIN/AUTH/ENCRYPT */
+   struct krb5_buffer key; /* Master key, K0 */
+   struct krb5_buffer ticket;  /* Ticket to be passed to server */
+   u8  _key[]; /* Key storage */
+};
+
 /*
  * list of tokens attached to an rxrpc key
  */
@@ -40,6 +56,7 @@ struct rxrpc_key_token {
struct rxrpc_key_token *next;   /* the next token in the list */
union {
struct rxkad_key *kad;
+   struct rxgk_key *rxgk;
};
 };
 
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 9631aa8543b5..b7f154701d97 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -129,6 +129,158 @@ static int rxrpc_preparse_xdr_rxkad(struct 
key_preparsed_payload *prep,
return 0;
 }
 
+static u64 xdr_dec64(const __be32 *xdr)
+{
+   return (u64)ntohl(xdr[0]) << 32 | (u64)ntohl(xdr[1]);
+}
+
+static time64_t rxrpc_s64_to_time64(s64 time_in_100ns)
+{
+   bool neg = false;
+   u64 tmp = time_in_100ns;
+
+   if (time_in_100ns < 0) {
+   tmp = -time_in_100ns;
+   neg = true;
+   }
+   do_div(tmp, 1000);
+   return neg ? -tmp : tmp;
+}
+
+/*
+ * Parse a YFS-RxGK type XDR format token
+ * - the caller guarantees we have at least 4 words
+ *
+ * struct token_rxgk {
+ * opr_time begintime;
+ * opr_time endtime;
+ * afs_int64 level;
+ * afs_int64 lifetime;
+ * afs_int64 bytelife;
+ * afs_int64 enctype;
+ * opaque key<>;
+ * opaque ticket<>;
+ * };
+ */
+static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
+  size_t datalen,
+  const __be32 *xdr, unsigned int toklen)
+{
+   struct rxrpc_key_token *token, **pptoken;
+   time64_t expiry;
+   size_t plen;
+   const __be32 *ticket, *key;
+   s64 tmp;
+   u32 tktlen, keylen;
+
+   _enter(",{%x,%x,%x,%x},%x",
+  ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
+  toklen);
+
+   if (6 * 2 + 2 > toklen / 4)
+   goto reject;
+
+   key = xdr + (6 * 2 + 1);
+   keylen = ntohl(key[-1]);
+   _debug("keylen: %x", keylen);
+   keylen = round_up(keylen, 4);
+   if ((6 * 2 + 2) * 4 + keylen > toklen)
+   goto reject;
+
+   ticket = xdr + (6 * 

[PATCH 13/18] rxrpc: Add the security index for yfs-rxgk

2020-11-12 Thread David Howells
Add the security index for the YFS variant of rxgk.

Signed-off-by: David Howells 
---

 fs/afs/misc.c  |   13 +
 include/uapi/linux/rxrpc.h |   17 +
 2 files changed, 30 insertions(+)

diff --git a/fs/afs/misc.c b/fs/afs/misc.c
index 1d1a8debe472..796783774e36 100644
--- a/fs/afs/misc.c
+++ b/fs/afs/misc.c
@@ -102,6 +102,19 @@ int afs_abort_to_error(u32 abort_code)
case RXKADDATALEN:  return -EKEYREJECTED;
case RXKADILLEGALLEVEL: return -EKEYREJECTED;
 
+   case RXGK_INCONSISTENCY:return -EPROTO;
+   case RXGK_PACKETSHORT:  return -EPROTO;
+   case RXGK_BADCHALLENGE: return -EPROTO;
+   case RXGK_BADETYPE: return -ENOPKG;
+   case RXGK_BADLEVEL: return -EKEYREJECTED;
+   case RXGK_BADKEYNO: return -EKEYREJECTED;
+   case RXGK_EXPIRED:  return -EKEYEXPIRED;
+   case RXGK_NOTAUTH:  return -EKEYREJECTED;
+   case RXGK_BAD_TOKEN:return -EKEYREJECTED;
+   case RXGK_SEALED_INCON: return -EKEYREJECTED;
+   case RXGK_DATA_LEN: return -EPROTO;
+   case RXGK_BAD_QOP:  return -EKEYREJECTED;
+
case RXGEN_OPCODE:  return -ENOTSUPP;
 
default:return -EREMOTEIO;
diff --git a/include/uapi/linux/rxrpc.h b/include/uapi/linux/rxrpc.h
index 8f8dc7a937a4..0e296d219191 100644
--- a/include/uapi/linux/rxrpc.h
+++ b/include/uapi/linux/rxrpc.h
@@ -73,6 +73,7 @@ enum rxrpc_cmsg_type {
 #define RXRPC_SECURITY_RXKAD   2   /* kaserver or kerberos 4 */
 #define RXRPC_SECURITY_RXGK4   /* gssapi-based */
 #define RXRPC_SECURITY_RXK55   /* kerberos 5 */
+#define RXRPC_SECURITY_YFS_RXGK6   /* YFS gssapi-based */
 
 /*
  * RxRPC-level abort codes
@@ -118,4 +119,20 @@ enum rxrpc_cmsg_type {
 #define RXKADDATALEN   19270411/* user data too long */
 #define RXKADILLEGALLEVEL  19270412/* caller not authorised to use 
encrypted conns */
 
+/*
+ * RxGK GSSAPI security abort codes.
+ */
+#define RXGK_INCONSISTENCY 1233242880  /* Security module structure 
inconsistent */
+#define RXGK_PACKETSHORT   1233242881  /* Packet too short for 
security challenge */
+#define RXGK_BADCHALLENGE  1233242882  /* Invalid security challenge */
+#define RXGK_BADETYPE  1233242883  /* Invalid or impermissible 
encryption type */
+#define RXGK_BADLEVEL  1233242884  /* Invalid or impermissible 
security level */
+#define RXGK_BADKEYNO  1233242885  /* Key version number not found 
*/
+#define RXGK_EXPIRED   1233242886  /* Token has expired */
+#define RXGK_NOTAUTH   1233242887  /* Caller not authorized */
+#define RXGK_BAD_TOKEN 1233242888  /* Security object was passed a 
bad token */
+#define RXGK_SEALED_INCON  1233242889  /* Sealed data inconsistent */
+#define RXGK_DATA_LEN  1233242890  /* User data too long */
+#define RXGK_BAD_QOP   1233242891  /* Inadequate quality of 
protection available */
+
 #endif /* _UAPI_LINUX_RXRPC_H */




[PATCH 11/18] crypto/krb5: Add the AES self-testing data from rfc8009

2020-11-12 Thread David Howells
Add the self-testing data from rfc8009 to test AES + HMAC-SHA2.

Signed-off-by: David Howells 
---

 crypto/krb5/selftest_data.c |  116 +++
 1 file changed, 116 insertions(+)

diff --git a/crypto/krb5/selftest_data.c b/crypto/krb5/selftest_data.c
index 9085723b730b..00c3b38c01d8 100644
--- a/crypto/krb5/selftest_data.c
+++ b/crypto/krb5/selftest_data.c
@@ -13,6 +13,20 @@
  * Pseudo-random function tests.
  */
 const struct krb5_prf_test krb5_prf_tests[] = {
+   /* rfc8009 Appendix A */
+   {
+   .krb5   = &krb5_aes128_cts_hmac_sha256_128,
+   .name   = "prf",
+   .key= "3705D96080C17728A0E800EAB6E0D23C",
+   .octet  = "74657374",
+   .prf= 
"9D188616F63852FE86915BB840B4A886FF3E6BB0F819B49B893393D393854295",
+   }, {
+   .krb5   = &krb5_aes256_cts_hmac_sha384_192,
+   .name   = "prf",
+   .key= 
"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52",
+   .octet  = "74657374",
+   .prf= 
"9801F69A368C2BF675E59521E177D9A07F67EFE1CFDE8D3C8D6F6A0256E3B17DB3C1B62AD1B8553360D17367EB1514D2",
+   },
{/* END */}
 };
 
@@ -20,6 +34,28 @@ const struct krb5_prf_test krb5_prf_tests[] = {
  * Key derivation tests.
  */
 const struct krb5_key_test krb5_key_tests[] = {
+   /* rfc8009 Appendix A */
+   {
+   .krb5   = &krb5_aes128_cts_hmac_sha256_128,
+   .name   = "key",
+   .key= "3705D96080C17728A0E800EAB6E0D23C",
+   .Kc.use = 0x0002,
+   .Kc.key = "B31A018A48F54776F403E9A396325DC3",
+   .Ke.use = 0x0002,
+   .Ke.key = "9B197DD1E8C5609D6E67C3E37C62C72E",
+   .Ki.use = 0x0002,
+   .Ki.key = "9FDA0E56AB2D85E1569A688696C26A6C",
+   }, {
+   .krb5   = &krb5_aes256_cts_hmac_sha384_192,
+   .name   = "key",
+   .key= 
"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52",
+   .Kc.use = 0x0002,
+   .Kc.key = "EF5718BE86CC84963D8BBB5031E9F5C4BA41F28FAF69E73D",
+   .Ke.use = 0x0002,
+   .Ke.key = 
"56AB22BEE63D82D7BC5227F6773F8EA7A5EB1C825160C38312980C442E5C7E49",
+   .Ki.use = 0x0002,
+   .Ki.key = "69B16514E3CD8E56B82010D5C73012B622C4D00FFC23ED1F",
+   },
{/* END */}
 };
 
@@ -27,6 +63,72 @@ const struct krb5_key_test krb5_key_tests[] = {
  * Encryption tests.
  */
 const struct krb5_enc_test krb5_enc_tests[] = {
+   /* rfc8009 Appendix A */
+   {
+   .krb5   = &krb5_aes128_cts_hmac_sha256_128,
+   .name   = "enc no plain",
+   .plain  = "",
+   .conf   = "7E5895EAF2672435BAD817F545A37148",
+   .Ke = "9B197DD1E8C5609D6E67C3E37C62C72E",
+   .Ki = "9FDA0E56AB2D85E1569A688696C26A6C",
+   .ct = 
"EF85FB890BB8472F4DAB20394DCA781DAD877EDA39D50C870C0D5A0A8E48C718",
+   }, {
+   .krb5   = &krb5_aes128_cts_hmac_sha256_128,
+   .name   = "enc plain

[PATCH 09/18] crypto/krb5: Implement the AES enctypes from rfc8009

2020-11-12 Thread David Howells
Implement the aes128-cts-hmac-sha256-128 and aes256-cts-hmac-sha384-192
enctypes from rfc8009, overriding the rfc3961 kerberos 5 simplified crypto
scheme.

Signed-off-by: David Howells 
---

 crypto/krb5/Kconfig|2 
 crypto/krb5/Makefile   |3 -
 crypto/krb5/internal.h |6 +
 crypto/krb5/main.c |2 
 crypto/krb5/rfc8009_aes2.c |  239 
 include/crypto/krb5.h  |4 +
 6 files changed, 255 insertions(+), 1 deletion(-)
 create mode 100644 crypto/krb5/rfc8009_aes2.c

diff --git a/crypto/krb5/Kconfig b/crypto/krb5/Kconfig
index e2eba1d689ab..5607c0c81049 100644
--- a/crypto/krb5/Kconfig
+++ b/crypto/krb5/Kconfig
@@ -4,6 +4,8 @@ config CRYPTO_KRB5
select CRYPTO_SKCIPHER
select CRYPTO_HASH_INFO
select CRYPTO_SHA1
+   select CRYPTO_SHA256
+   select CRYPTO_SHA512
select CRYPTO_CBC
select CRYPTO_CTS
select CRYPTO_AES
diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index b7da03cae6d1..85763131f7b6 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -7,7 +7,8 @@ krb5-y += \
kdf.o \
main.o \
rfc3961_simplified.o \
-   rfc3962_aes.o
+   rfc3962_aes.o \
+   rfc8009_aes2.o
 
 krb5-$(CONFIG_CRYPTO_KRB5_SELFTESTS) += \
selftest.o \
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index 47424b433778..e64f5e58199f 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -158,6 +158,12 @@ int rfc3961_verify_mic(const struct krb5_enctype *krb5,
 extern const struct krb5_enctype krb5_aes128_cts_hmac_sha1_96;
 extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96;
 
+/*
+ * rfc8009_aes2.c
+ */
+extern const struct krb5_enctype krb5_aes128_cts_hmac_sha256_128;
+extern const struct krb5_enctype krb5_aes256_cts_hmac_sha384_192;
+
 /*
  * selftest.c
  */
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index b79127027551..9914d3417c21 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -20,6 +20,8 @@ MODULE_LICENSE("GPL");
 static const struct krb5_enctype *const krb5_supported_enctypes[] = {
&krb5_aes128_cts_hmac_sha1_96,
&krb5_aes256_cts_hmac_sha1_96,
+   &krb5_aes128_cts_hmac_sha256_128,
+   &krb5_aes256_cts_hmac_sha384_192,
 };
 
 /**
diff --git a/crypto/krb5/rfc8009_aes2.c b/crypto/krb5/rfc8009_aes2.c
new file mode 100644
index ..9f0f0f410d91
--- /dev/null
+++ b/crypto/krb5/rfc8009_aes2.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* rfc8009 AES Encryption with HMAC-SHA2 for Kerberos 5
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include "internal.h"
+
+static const struct krb5_buffer rfc8009_no_context = { .len = 0, .data = "" };
+
+/*
+ * Calculate the key derivation function KDF-HMAC-SHA2(key, label, [context,] 
k)
+ *
+ * KDF-HMAC-SHA2(key, label, [context,] k) = k-truncate(K1)
+ *
+ * Using the appropriate one of:
+ * K1 = HMAC-SHA-256(key, 0x0001 | label | 0x00 | k)
+ * K1 = HMAC-SHA-384(key, 0x0001 | label | 0x00 | k)
+ * K1 = HMAC-SHA-256(key, 0x0001 | label | 0x00 | context | k)
+ * K1 = HMAC-SHA-384(key, 0x0001 | label | 0x00 | context | k)
+ * [rfc8009 sec 3]
+ */
+static int rfc8009_calc_KDF_HMAC_SHA2(const struct krb5_enctype *krb5,
+ const struct krb5_buffer *key,
+ const struct krb5_buffer *label,
+ const struct krb5_buffer *context,
+ unsigned int k,
+ struct krb5_buffer *result,
+ gfp_t gfp)
+{
+   struct crypto_shash *shash;
+   struct krb5_buffer K1, data;
+   struct shash_desc *desc;
+   __be32 tmp;
+   size_t bsize;
+   void *buffer;
+   u8 *p;
+   int ret = -ENOMEM;
+
+   if (WARN_ON(result->len != k / 8))
+   return -EINVAL;
+
+   shash = crypto_alloc_shash(krb5->cksum_name, 0, 0);
+   if (IS_ERR(shash))
+   return (PTR_ERR(shash) == -ENOENT) ? -ENOPKG : PTR_ERR(shash);
+   ret = crypto_shash_setkey(shash, key->data, key->len);
+   if (ret < 0)
+   goto error_shash;
+
+   ret = -EINVAL;
+   if (WARN_ON(crypto_shash_digestsize(shash) * 8 < k))
+   goto error_shash;
+
+   ret = -ENOMEM;
+   data.len = 4 + label->len + 1 + context->len + 4;
+   bsize = krb5_shash_size(shash) +
+   krb5_digest_size(shash) +
+   crypto_roundup(data.len);
+   buffer = kzalloc(bsize, GFP_NOFS);
+   if (!buffer)
+   goto error_shash;
+
+ 

[PATCH 08/18] crypto/krb5: Implement crypto self-testing

2020-11-12 Thread David Howells
Implement self-testing infrastructure to test the pseudo-random function,
key derivation, encryption and checksumming.

Signed-off-by: David Howells 
---

 crypto/krb5/Kconfig |4 
 crypto/krb5/Makefile|4 
 crypto/krb5/internal.h  |   48 
 crypto/krb5/main.c  |   12 +
 crypto/krb5/selftest.c  |  543 +++
 crypto/krb5/selftest_data.c |   38 +++
 6 files changed, 649 insertions(+)
 create mode 100644 crypto/krb5/selftest.c
 create mode 100644 crypto/krb5/selftest_data.c

diff --git a/crypto/krb5/Kconfig b/crypto/krb5/Kconfig
index 881754500732..e2eba1d689ab 100644
--- a/crypto/krb5/Kconfig
+++ b/crypto/krb5/Kconfig
@@ -9,3 +9,7 @@ config CRYPTO_KRB5
select CRYPTO_AES
help
  Provide Kerberos-5-based security.
+
+config CRYPTO_KRB5_SELFTESTS
+   bool "Kerberos 5 crypto selftests"
+   depends on CRYPTO_KRB5
diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index b81e2efac3c8..b7da03cae6d1 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -9,4 +9,8 @@ krb5-y += \
rfc3961_simplified.o \
rfc3962_aes.o
 
+krb5-$(CONFIG_CRYPTO_KRB5_SELFTESTS) += \
+   selftest.o \
+   selftest_data.o
+
 obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index 5d55a574536e..47424b433778 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -88,6 +88,37 @@ struct krb5_crypto_profile {
crypto_roundup(crypto_sync_skcipher_ivsize(TFM))
 #define round16(x) (((x) + 15) & ~15)
 
+/*
+ * Self-testing data.
+ */
+struct krb5_prf_test {
+   const struct krb5_enctype *krb5;
+   const char *name, *key, *octet, *prf;
+};
+
+struct krb5_key_test_one {
+   u32 use;
+   const char *key;
+};
+
+struct krb5_key_test {
+   const struct krb5_enctype *krb5;
+   const char *name, *key;
+   struct krb5_key_test_one Kc, Ke, Ki;
+};
+
+struct krb5_enc_test {
+   const struct krb5_enctype *krb5;
+   const char *name, *plain, *conf, *K0, *Ke, *Ki, *ct;
+   __be32 usage;
+};
+
+struct krb5_mic_test {
+   const struct krb5_enctype *krb5;
+   const char *name, *plain, *K0, *Kc, *mic;
+   __be32 usage;
+};
+
 /*
  * main.c
  */
@@ -126,3 +157,20 @@ int rfc3961_verify_mic(const struct krb5_enctype *krb5,
  */
 extern const struct krb5_enctype krb5_aes128_cts_hmac_sha1_96;
 extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96;
+
+/*
+ * selftest.c
+ */
+#ifdef CONFIG_CRYPTO_KRB5_SELFTESTS
+void krb5_selftest(void);
+#else
+static inline void krb5_selftest(void) {}
+#endif
+
+/*
+ * selftest_data.c
+ */
+extern const struct krb5_prf_test krb5_prf_tests[];
+extern const struct krb5_key_test krb5_key_tests[];
+extern const struct krb5_enc_test krb5_enc_tests[];
+extern const struct krb5_mic_test krb5_mic_tests[];
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index bce47580c33f..b79127027551 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -214,3 +214,15 @@ int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
 _offset, _len, _error_code);
 }
 EXPORT_SYMBOL(crypto_krb5_verify_mic);
+
+static int __init crypto_krb5_init(void)
+{
+   krb5_selftest();
+   return 0;
+}
+module_init(crypto_krb5_init);
+
+static void __exit crypto_krb5_exit(void)
+{
+}
+module_exit(crypto_krb5_exit);
diff --git a/crypto/krb5/selftest.c b/crypto/krb5/selftest.c
new file mode 100644
index ..df57ab24cc6e
--- /dev/null
+++ b/crypto/krb5/selftest.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* RxGK self-testing
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include "internal.h"
+
+#define VALID(X) \
+   ({  \
+   bool __x = (X); \
+   if (__x) {  \
+   pr_warn("!!! TESTINVAL %s:%u\n", __FILE__, __LINE__); \
+   }   \
+   __x;\
+   })
+
+#define CHECK(X) \
+   ({  \
+   bool __x = (X); \
+   if (__x) {  \
+   pr_warn("!!! TESTFAIL %s:%u\n", __FILE__, __LINE__); \
+   }   \
+   __x;\
+   })
+
+enum which_key {
+   TEST_KC, TEST_KE, TEST_KI,
+};
+
+static int 

[PATCH 10/18] crypto/krb5: Implement the AES encrypt/decrypt from rfc8009

2020-11-12 Thread David Howells
Implement encryption and decryption functions for AES + HMAC-SHA2 as
described in rfc8009 sec 5.

Signed-off-by: David Howells 
---

 crypto/krb5/rfc8009_aes2.c |  205 
 1 file changed, 203 insertions(+), 2 deletions(-)

diff --git a/crypto/krb5/rfc8009_aes2.c b/crypto/krb5/rfc8009_aes2.c
index 9f0f0f410d91..df517435be73 100644
--- a/crypto/krb5/rfc8009_aes2.c
+++ b/crypto/krb5/rfc8009_aes2.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "internal.h"
 
 static const struct krb5_buffer rfc8009_no_context = { .len = 0, .data = "" };
@@ -183,13 +184,213 @@ static int rfc8009_random_to_key(const struct 
krb5_enctype *krb5,
return 0;
 }
 
+/*
+ * Apply encryption and checksumming functions to part of an skbuff.
+ */
+static ssize_t rfc8009_encrypt(const struct krb5_enctype *krb5,
+  struct krb5_enc_keys *keys,
+  struct scatterlist *sg, unsigned nr_sg, size_t 
sg_len,
+  size_t data_offset, size_t data_len,
+  bool preconfounded)
+{
+   struct skcipher_request *req;
+   struct shash_desc *desc;
+   ssize_t ret, done;
+   size_t bsize, base_len, secure_offset, secure_len, pad_len, 
cksum_offset;
+   void *buffer;
+   u8 *cksum, *iv;
+
+   if (WARN_ON(data_offset != krb5->conf_len))
+   return -EINVAL; /* Can't set offset on skcipher */
+
+   base_len   = krb5->conf_len + data_len;
+   secure_len = base_len;
+   pad_len= secure_len - base_len;
+   secure_offset = 0;
+   cksum_offset = secure_offset + secure_len;
+
+   bsize = krb5_shash_size(keys->Ki) +
+   krb5_digest_size(keys->Ki) +
+   krb5_sync_skcipher_size(keys->Ke) +
+   krb5_sync_skcipher_ivsize(keys->Ke);
+   bsize = max_t(size_t, bsize, krb5->conf_len);
+   bsize = max_t(size_t, bsize, krb5->block_len);
+   buffer = kzalloc(bsize, GFP_NOFS);
+   if (!buffer)
+   return -ENOMEM;
+
+   /* Insert the confounder into the skb */
+   ret = -EFAULT;
+   if (!preconfounded) {
+   get_random_bytes(buffer, krb5->conf_len);
+   done = sg_pcopy_to_buffer(sg, nr_sg, buffer, krb5->conf_len,
+ secure_offset);
+   if (done != krb5->conf_len)
+   goto error;
+   }
+
+   /* We need to pad out to the crypto blocksize. */
+   if (pad_len) {
+   done = sg_zero_buffer(sg, nr_sg, pad_len, data_offset + 
data_len);
+   if (done != pad_len)
+   goto error;
+   }
+
+   /* Encrypt the secure region with key Ke. */
+   req = buffer +
+   krb5_shash_size(keys->Ki) +
+   krb5_digest_size(keys->Ki);
+   iv = buffer +
+   krb5_shash_size(keys->Ki) +
+   krb5_digest_size(keys->Ki) +
+   krb5_sync_skcipher_size(keys->Ke);
+
+   skcipher_request_set_sync_tfm(req, keys->Ke);
+   skcipher_request_set_callback(req, 0, NULL, NULL);
+   skcipher_request_set_crypt(req, sg, sg, secure_len, iv);
+   ret = crypto_skcipher_encrypt(req);
+   if (ret < 0)
+   goto error;
+
+   /* Calculate the checksum using key Ki */
+   cksum = buffer + krb5_shash_size(keys->Ki);
+
+   desc = buffer;
+   desc->tfm = keys->Ki;
+   ret = crypto_shash_init(desc);
+   if (ret < 0)
+   goto error;
+
+   memset(iv, 0, crypto_sync_skcipher_ivsize(keys->Ke));
+   ret = crypto_shash_update(desc, iv, 
crypto_sync_skcipher_ivsize(keys->Ke));
+   if (ret < 0)
+   goto error;
+
+   ret = crypto_shash_update_sg(desc, sg, secure_offset, secure_len);
+   if (ret < 0)
+   goto error;
+
+   ret = crypto_shash_final(desc, cksum);
+   if (ret < 0)
+   goto error;
+
+   /* Append the checksum into the buffer. */
+   ret = -EFAULT;
+   sg_zero_buffer(sg, nr_sg, 3, cksum_offset);
+   done = sg_pcopy_from_buffer(sg, nr_sg, cksum, krb5->cksum_len, 
cksum_offset);
+   if (done != krb5->cksum_len)
+   goto error;
+
+   ret = secure_len + krb5->cksum_len;
+
+error:
+   kfree_sensitive(buffer);
+   return ret;
+}
+
+/*
+ * Apply decryption and checksumming functions to part of an skbuff.  The
+ * offset and length are updated to reflect the actual content of the encrypted
+ * region.
+ */
+static int rfc8009_decrypt(const struct krb5_enctype *krb5,
+  struct krb5_enc_keys *keys,
+  struct scatterlist *sg, unsigned nr_sg,
+  size_t *_offset, size_t *_len,
+  int *_error_code)
+{
+   struct skcipher_reque

[PATCH 04/18] crypto/krb5: Implement the Kerberos5 rfc3961 key derivation

2020-11-12 Thread David Howells
Implement the simplified crypto profile for Kerberos 5 rfc3961 with the
pseudo-random function, PRF(), from section 5.3 and the key derivation
function, DK() from section 5.1.

Signed-off-by: David Howells 
---

 crypto/krb5/Makefile |3 
 crypto/krb5/internal.h   |6 +
 crypto/krb5/rfc3961_simplified.c |  394 ++
 3 files changed, 402 insertions(+), 1 deletion(-)
 create mode 100644 crypto/krb5/rfc3961_simplified.c

diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
index b764c4d09bf2..67824c44aac3 100644
--- a/crypto/krb5/Makefile
+++ b/crypto/krb5/Makefile
@@ -5,6 +5,7 @@
 
 krb5-y += \
kdf.o \
-   main.o
+   main.o \
+   rfc3961_simplified.o
 
 obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index d2e3da7f101e..874dddada713 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -5,6 +5,7 @@
  * Written by David Howells (dhowe...@redhat.com)
  */
 
+#include 
 #include 
 
 /*
@@ -85,3 +86,8 @@ struct krb5_crypto_profile {
 #define krb5_sync_skcipher_ivsize(TFM) \
crypto_roundup(crypto_sync_skcipher_ivsize(TFM))
 #define round16(x) (((x) + 15) & ~15)
+
+/*
+ * rfc3961_simplified.c
+ */
+extern const struct krb5_crypto_profile rfc3961_simplified_profile;
diff --git a/crypto/krb5/rfc3961_simplified.c b/crypto/krb5/rfc3961_simplified.c
new file mode 100644
index ..0a5c689f6354
--- /dev/null
+++ b/crypto/krb5/rfc3961_simplified.c
@@ -0,0 +1,394 @@
+/* rfc3961 Kerberos 5 simplified crypto profile.
+ *
+ * Parts borrowed from net/sunrpc/auth_gss/.
+ */
+/*
+ * COPYRIGHT (c) 2008
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include "internal.h"
+
+/* Maximum blocksize for the supported crypto algorithms */
+#define KRB5_MAX_BLOCKSIZE  (16)
+
+static int rfc3961_do_encrypt(struct crypto_sync_skcipher *tfm, void *iv,
+ const struct krb5_buffer *in, struct krb5_buffer 
*out)
+{
+   struct scatterlist sg[1];
+   u8 local_iv[KRB5_MAX_BLOCKSIZE] __aligned(KRB5_MAX_BLOCKSIZE) = {0};
+   SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
+   int ret;
+
+   if (WARN_ON(in->l

[PATCH 06/18] crypto/krb5: Implement the Kerberos5 rfc3961 get_mic and verify_mic

2020-11-12 Thread David Howells
Add functions that sign and verify a piece of an skbuff according to
rfc3961 sec 5.4, using Kc to generate a checksum and insert it into the MIC
field in the skbuff in the sign phase then checksum the data and compare it
to the MIC in the verify phase.

Signed-off-by: David Howells 
---

 crypto/krb5/internal.h   |   11 +++
 crypto/krb5/main.c   |   70 
 crypto/krb5/rfc3961_simplified.c |  134 ++
 include/crypto/krb5.h|   12 +++
 4 files changed, 227 insertions(+)

diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index ce07decf19f0..20b506327491 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -109,3 +109,14 @@ int rfc3961_decrypt(const struct krb5_enctype *krb5,
struct scatterlist *sg, unsigned nr_sg,
size_t *_offset, size_t *_len,
int *_error_code);
+ssize_t rfc3961_get_mic(const struct krb5_enctype *krb5,
+   struct crypto_shash *shash,
+   const struct krb5_buffer *metadata,
+   struct scatterlist *sg, unsigned nr_sg, size_t sg_len,
+   size_t data_offset, size_t data_len);
+int rfc3961_verify_mic(const struct krb5_enctype *krb5,
+  struct crypto_shash *shash,
+  const struct krb5_buffer *metadata,
+  struct scatterlist *sg, unsigned nr_sg,
+  size_t *_offset, size_t *_len,
+  int *_error_code);
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index db3fc34be272..97b28e40f6d7 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -142,3 +142,73 @@ int crypto_krb5_decrypt(const struct krb5_enctype *krb5,
  _offset, _len, _error_code);
 }
 EXPORT_SYMBOL(crypto_krb5_decrypt);
+
+/**
+ * crypto_krb5_get_mic - Apply Kerberos integrity checksum.
+ * @krb5: The encoding to use.
+ * @shash: The keyed hash to use.
+ * @metadata: Metadata to add into the hash before adding the data.
+ * @sg: Scatterlist defining the crypto buffer.
+ * @nr_sg: The number of elements in @sg.
+ * @sg_len: The size of the buffer.
+ * @data_offset: The offset of the data in the @sg buffer.
+ * @data_len: The length of the data.
+ *
+ * Using the specified Kerberos encoding, calculate and insert an integrity
+ * checksum into the buffer.
+ *
+ * The buffer must include space for the checksum at the front.
+ *
+ * Returns the size of the secure blob if successful, -ENOMEM on an allocation
+ * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the gap for
+ * the checksum is too short.  Other errors may also be returned from the
+ * crypto layer.
+ */
+ssize_t crypto_krb5_get_mic(const struct krb5_enctype *krb5,
+   struct crypto_shash *shash,
+   const struct krb5_buffer *metadata,
+   struct scatterlist *sg, unsigned nr_sg, size_t 
sg_len,
+   size_t data_offset, size_t data_len)
+{
+   if (WARN_ON(data_offset > sg_len ||
+   data_len > sg_len ||
+   data_offset > sg_len - data_len))
+   return -EMSGSIZE;
+   return krb5->profile->get_mic(krb5, shash, metadata, sg, nr_sg, sg_len,
+ data_offset, data_len);
+}
+EXPORT_SYMBOL(crypto_krb5_get_mic);
+
+/**
+ * crypto_krb5_verify_mic - Validate and remove Kerberos integrity checksum.
+ * @krb5: The encoding to use.
+ * @shash: The keyed hash to use.
+ * @metadata: Metadata to add into the hash before adding the data.
+ * @sg: Scatterlist defining the crypto buffer.
+ * @nr_sg: The number of elements in @sg.
+ * @_offset: Offset of the secure blob in the buffer; updated to data offset.
+ * @_len: The length of the secure blob; updated to data length.
+ * @_error_code: Set to a Kerberos error code for parsing/validation errors.
+ *
+ * Using the specified Kerberos encoding, check and remove the integrity
+ * checksum.
+ *
+ * If successful, @_offset and @_len are updated to outline the region in which
+ * the data is stored.
+ *
+ * Returns the 0 if successful, -ENOMEM on an allocation failure; sets
+ * *_error_code and returns -EPROTO if the data cannot be parsed or if the
+ * integrity checksum doesn't match).  Other errors may also be returned from
+ * the crypto layer.
+ */
+int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
+  struct crypto_shash *shash,
+  const struct krb5_buffer *metadata,
+  struct scatterlist *sg, unsigned nr_sg,
+  size_t *_offset, size_t *_len,
+  int *_error_code)
+{
+   return krb5->profile->verify_mic(krb5, shash, metadata, sg, nr_sg,
+_offset, _len, _erro

[PATCH 05/18] crypto/krb5: Implement the Kerberos5 rfc3961 encrypt and decrypt functions

2020-11-12 Thread David Howells
Add functions that encrypt and decrypt a piece of an skbuff according to
rfc3961 sec 5.3, using Ki to checksum the data to be secured and Ke to
encrypt it during the encryption phase, then decrypting with Ke and
verifying the checksum with Ki in the decryption phase.

Signed-off-by: David Howells 
---

 crypto/krb5/internal.h   |   18 +++
 crypto/krb5/main.c   |  102 +++
 crypto/krb5/rfc3961_simplified.c |  204 ++
 include/crypto/krb5.h|   12 ++
 4 files changed, 336 insertions(+)

diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
index 874dddada713..ce07decf19f0 100644
--- a/crypto/krb5/internal.h
+++ b/crypto/krb5/internal.h
@@ -7,6 +7,7 @@
 
 #include 
 #include 
+#include 
 
 /*
  * Profile used for key derivation and encryption.
@@ -87,7 +88,24 @@ struct krb5_crypto_profile {
crypto_roundup(crypto_sync_skcipher_ivsize(TFM))
 #define round16(x) (((x) + 15) & ~15)
 
+/*
+ * main.c
+ */
+int crypto_shash_update_sg(struct shash_desc *desc, struct scatterlist *sg,
+  size_t offset, size_t len);
+
 /*
  * rfc3961_simplified.c
  */
 extern const struct krb5_crypto_profile rfc3961_simplified_profile;
+
+ssize_t rfc3961_encrypt(const struct krb5_enctype *krb5,
+   struct krb5_enc_keys *keys,
+   struct scatterlist *sg, unsigned nr_sg, size_t sg_len,
+   size_t data_offset, size_t data_len,
+   bool preconfounded);
+int rfc3961_decrypt(const struct krb5_enctype *krb5,
+   struct krb5_enc_keys *keys,
+   struct scatterlist *sg, unsigned nr_sg,
+   size_t *_offset, size_t *_len,
+   int *_error_code);
diff --git a/crypto/krb5/main.c b/crypto/krb5/main.c
index 58d40252adc9..db3fc34be272 100644
--- a/crypto/krb5/main.c
+++ b/crypto/krb5/main.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "internal.h"
 
 MODULE_DESCRIPTION("Kerberos 5 crypto");
@@ -40,3 +41,104 @@ const struct krb5_enctype *crypto_krb5_find_enctype(u32 
enctype)
return NULL;
 }
 EXPORT_SYMBOL(crypto_krb5_find_enctype);
+
+int crypto_shash_update_sg(struct shash_desc *desc, struct scatterlist *sg,
+  size_t offset, size_t len)
+{
+   for (;; sg++) {
+   int ret;
+
+   if (offset < sg->length) {
+   struct page *page = sg_page(sg);
+   void *p = kmap_atomic(page);
+   size_t seg = min_t(size_t, len, sg->length - offset);
+
+   ret = crypto_shash_update(desc, p + sg->offset + 
offset, seg);
+   kunmap_atomic(p);
+   if (ret < 0)
+   return ret;
+   len -= seg;
+   offset = 0;
+   } else {
+   offset -= sg->length;
+   }
+   if (sg_is_last(sg) || len > 0)
+   break;
+   }
+
+   return 0;
+}
+
+/**
+ * crypto_krb5_encrypt - Apply Kerberos encryption and integrity.
+ * @krb5: The encoding to use.
+ * @keys: The encryption and integrity keys to use.
+ * @sg: Scatterlist defining the crypto buffer.
+ * @nr_sg: The number of elements in @sg.
+ * @sg_len: The size of the buffer.
+ * @data_offset: The offset of the data in the @sg buffer.
+ * @data_len: The length of the data.
+ * @preconfounded: True if the confounder is already inserted.
+ *
+ * Using the specified Kerberos encoding, insert a confounder and padding as
+ * needed, encrypt this and the data in place and insert an integrity checksum
+ * into the buffer.
+ *
+ * The buffer must include space for the confounder, the checksum and any
+ * padding required.  The caller can preinsert the confounder into the buffer
+ * (for testing, for example).
+ *
+ * The resulting secured blob may be less than the size of the buffer.
+ *
+ * Returns the size of the secure blob if successful, -ENOMEM on an allocation
+ * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the confounder
+ * is too short or the data is misaligned.  Other errors may also be returned
+ * from the crypto layer.
+ */
+ssize_t crypto_krb5_encrypt(const struct krb5_enctype *krb5,
+   struct krb5_enc_keys *keys,
+   struct scatterlist *sg, unsigned nr_sg, size_t 
sg_len,
+   size_t data_offset, size_t data_len,
+   bool preconfounded)
+{
+   if (WARN_ON(data_offset > sg_len ||
+   data_len > sg_len ||
+   data_offset > sg_len - data_len))
+   return -EMSGSIZE;
+   return krb5->profile->encrypt(krb5, keys, sg, nr_sg, sg_len,
+ data_offset, dat

[PATCH 02/18] crypto/krb5: Add some constants out of sunrpc headers

2020-11-12 Thread David Howells
Add some constants from the sunrpc headers.

Signed-off-by: David Howells 
---

 include/crypto/krb5.h |   39 +++
 1 file changed, 39 insertions(+)

diff --git a/include/crypto/krb5.h b/include/crypto/krb5.h
index 2bd6cfe50b85..a7e4ab4e1348 100644
--- a/include/crypto/krb5.h
+++ b/include/crypto/krb5.h
@@ -15,6 +15,45 @@
 struct crypto_shash;
 struct scatterlist;
 
+/* per Kerberos v5 protocol spec crypto types from the wire.
+ * these get mapped to linux kernel crypto routines.
+ */
+#define KRB5_ENCTYPE_NULL  0x
+#define KRB5_ENCTYPE_DES_CBC_CRC   0x0001  /* DES cbc mode with 
CRC-32 */
+#define KRB5_ENCTYPE_DES_CBC_MD4   0x0002  /* DES cbc mode with 
RSA-MD4 */
+#define KRB5_ENCTYPE_DES_CBC_MD5   0x0003  /* DES cbc mode with 
RSA-MD5 */
+#define KRB5_ENCTYPE_DES_CBC_RAW   0x0004  /* DES cbc mode raw */
+/* XXX deprecated? */
+#define KRB5_ENCTYPE_DES3_CBC_SHA  0x0005  /* DES-3 cbc mode with 
NIST-SHA */
+#define KRB5_ENCTYPE_DES3_CBC_RAW  0x0006  /* DES-3 cbc mode raw */
+#define KRB5_ENCTYPE_DES_HMAC_SHA1 0x0008
+#define KRB5_ENCTYPE_DES3_CBC_SHA1 0x0010
+#define KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96   0x0011
+#define KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96   0x0012
+#define KRB5_ENCTYPE_ARCFOUR_HMAC  0x0017
+#define KRB5_ENCTYPE_ARCFOUR_HMAC_EXP  0x0018
+#define KRB5_ENCTYPE_UNKNOWN   0x01ff
+
+#define KRB5_CKSUMTYPE_CRC32   0x0001
+#define KRB5_CKSUMTYPE_RSA_MD4 0x0002
+#define KRB5_CKSUMTYPE_RSA_MD4_DES 0x0003
+#define KRB5_CKSUMTYPE_DESCBC  0x0004
+#define KRB5_CKSUMTYPE_RSA_MD5 0x0007
+#define KRB5_CKSUMTYPE_RSA_MD5_DES 0x0008
+#define KRB5_CKSUMTYPE_NIST_SHA0x0009
+#define KRB5_CKSUMTYPE_HMAC_SHA1_DES3  0x000c
+#define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f
+#define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010
+#define KRB5_CKSUMTYPE_HMAC_MD5_ARCFOUR-138 /* Microsoft md5 
hmac cksumtype */
+
+/*
+ * Constants used for key derivation
+ */
+/* from rfc3961 */
+#define KEY_USAGE_SEED_CHECKSUM (0x99)
+#define KEY_USAGE_SEED_ENCRYPTION   (0xAA)
+#define KEY_USAGE_SEED_INTEGRITY(0x55)
+
 struct krb5_buffer {
unsigned intlen;
void*data;




[PATCH 01/18] crypto/krb5: Implement Kerberos crypto core

2020-11-12 Thread David Howells
Provide core structures, an encoding-type registry and basic module and
config bits for a generic Kerberos crypto library.

Signed-off-by: David Howells 
---

 crypto/Kconfig |1 +
 crypto/Makefile|1 +
 crypto/krb5/Kconfig|   11 ++
 crypto/krb5/Makefile   |9 +
 crypto/krb5/internal.h |   87 
 crypto/krb5/main.c |   42 +++
 include/crypto/krb5.h  |   67 +
 7 files changed, 218 insertions(+)
 create mode 100644 crypto/krb5/Kconfig
 create mode 100644 crypto/krb5/Makefile
 create mode 100644 crypto/krb5/internal.h
 create mode 100644 crypto/krb5/main.c
 create mode 100644 include/crypto/krb5.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 094ef56ab7b4..0d5ca023bb77 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1940,5 +1940,6 @@ source "lib/crypto/Kconfig"
 source "drivers/crypto/Kconfig"
 source "crypto/asymmetric_keys/Kconfig"
 source "certs/Kconfig"
+source "crypto/krb5/Kconfig"
 
 endif  # if CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index b279483fba50..732467ed3c94 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -197,3 +197,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
 obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
 crypto_simd-y := simd.o
 obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o
+obj-$(CONFIG_CRYPTO_KRB5) += krb5/
diff --git a/crypto/krb5/Kconfig b/crypto/krb5/Kconfig
new file mode 100644
index ..881754500732
--- /dev/null
+++ b/crypto/krb5/Kconfig
@@ -0,0 +1,11 @@
+config CRYPTO_KRB5
+   tristate "Kerberos 5 crypto"
+   select CRYPTO_MANAGER
+   select CRYPTO_SKCIPHER
+   select CRYPTO_HASH_INFO
+   select CRYPTO_SHA1
+   select CRYPTO_CBC
+   select CRYPTO_CTS
+   select CRYPTO_AES
+   help
+ Provide Kerberos-5-based security.
diff --git a/crypto/krb5/Makefile b/crypto/krb5/Makefile
new file mode 100644
index ..071ce2ff82e5
--- /dev/null
+++ b/crypto/krb5/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for asymmetric cryptographic keys
+#
+
+krb5-y += \
+   main.o
+
+obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
diff --git a/crypto/krb5/internal.h b/crypto/krb5/internal.h
new file mode 100644
index ..d2e3da7f101e
--- /dev/null
+++ b/crypto/krb5/internal.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Kerberos5 crypto internals
+ *
+ * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#include 
+
+/*
+ * Profile used for key derivation and encryption.
+ */
+struct krb5_crypto_profile {
+/* Pseudo-random function */
+   int (*calc_PRF)(const struct krb5_enctype *krb5,
+   const struct krb5_buffer *protocol_key,
+   const struct krb5_buffer *octet_string,
+   struct krb5_buffer *result,
+   gfp_t gfp);
+
+   /* Checksum key derivation */
+   int (*calc_Kc)(const struct krb5_enctype *krb5,
+  const struct krb5_buffer *TK,
+  const struct krb5_buffer *usage_constant,
+  struct krb5_buffer *Kc,
+  gfp_t gfp);
+
+   /* Encryption key derivation */
+   int (*calc_Ke)(const struct krb5_enctype *krb5,
+  const struct krb5_buffer *TK,
+  const struct krb5_buffer *usage_constant,
+  struct krb5_buffer *Ke,
+  gfp_t gfp);
+
+/* Integrity key derivation */
+   int (*calc_Ki)(const struct krb5_enctype *krb5,
+  const struct krb5_buffer *TK,
+  const struct krb5_buffer *usage_constant,
+  struct krb5_buffer *Ki,
+  gfp_t gfp);
+
+   /* Encrypt data in-place, inserting confounder and checksum. */
+   ssize_t (*encrypt)(const struct krb5_enctype *krb5,
+  struct krb5_enc_keys *keys,
+  struct scatterlist *sg, unsigned nr_sg, size_t 
sg_len,
+  size_t data_offset, size_t data_len,
+  bool preconfounded);
+
+   /* Decrypt data in-place, removing confounder and checksum */
+   int (*decrypt)(const struct krb5_enctype *krb5,
+  struct krb5_enc_keys *keys,
+  struct scatterlist *sg, unsigned nr_sg,
+  size_t *_offset, size_t *_len,
+  int *_error_code);
+
+   /* Generate a MIC on part of a packet, inserting the checksum */
+   ssize_t (*get_mic)(const struct krb5_enctype *krb5,
+  struct crypto_shash *shash,
+  const struct krb5_buffer *metadata,
+

[RFC][PATCH 00/18] crypto: Add generic Kerberos library

2020-11-12 Thread David Howells


Hi Herbert, Bruce,

Here's my first cut at a generic Kerberos crypto library in the kernel so
that I can share code between rxrpc and sunrpc (and cifs?).

I derived some of the parts from the sunrpc gss library and added more
advanced AES and Camellia crypto.  I haven't ported across the DES-based
crypto yet - I figure that can wait a bit till the interface is sorted.

Whilst I have put it into a directory under crypto/, I haven't made an
interface that goes and loads it (analogous to crypto_alloc_skcipher,
say).  Instead, you call:

const struct krb5_enctype *crypto_krb5_find_enctype(u32 enctype);

to go and get a handler table and then use a bunch of accessor functions to
jump through the hoops.  This is basically the way the sunrpc gsslib does
things.  It might be worth making it so you do something like:

struct crypto_mech *ctx = crypto_mech_alloc("krb5(18)");

to get enctype 18, but I'm not sure if it's worth the effort.  Also, I'm
not sure if there are any alternatives to kerberos we will need to support.

There are three main interfaces to it:

 (*) I/O crypto: encrypt, decrypt, get_mic and verify_mic.

 These all do in-place crypto, using an sglist to define the buffer
 with the data in it.  Is it necessary to make it able to take separate
 input and output buffers?

 (*) PRF+ calculation for key derivation.
 (*) Kc, Ke, Ki derivation.

 These use krb5_buffer structs to pass objects around.  This is akin to
 the xdr_netobj, but has a void* instead of a u8* data pointer.

In terms of rxrpc's rxgk, there's another step in key derivation that isn't
part of the kerberos standard, but uses the PRF+ function to generate a key
that is then used to generate Kc, Ke and Ki.  Is it worth putting this into
the directory or maybe having a callout to insert an intermediate step in
key derivation?

Note that, for purposes of illustration, I've included some rxrpc patches
that use this interface to implement the rxgk Rx security class.  The
branch also is based on some rxrpc patches that are a prerequisite for
this, but the crypto patches don't need it.

---
The patches can be found here also:


http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=crypto-krb5

David
---
David Howells (18):
  crypto/krb5: Implement Kerberos crypto core
  crypto/krb5: Add some constants out of sunrpc headers
  crypto/krb5: Provide infrastructure and key derivation
  crypto/krb5: Implement the Kerberos5 rfc3961 key derivation
  crypto/krb5: Implement the Kerberos5 rfc3961 encrypt and decrypt functions
  crypto/krb5: Implement the Kerberos5 rfc3961 get_mic and verify_mic
  crypto/krb5: Implement the AES enctypes from rfc3962
  crypto/krb5: Implement crypto self-testing
  crypto/krb5: Implement the AES enctypes from rfc8009
  crypto/krb5: Implement the AES encrypt/decrypt from rfc8009
  crypto/krb5: Add the AES self-testing data from rfc8009
  crypto/krb5: Implement the Camellia enctypes from rfc6803
  rxrpc: Add the security index for yfs-rxgk
  rxrpc: Add YFS RxGK (GSSAPI) security class
  rxrpc: rxgk: Provide infrastructure and key derivation
  rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)
  rxrpc: rxgk: Implement connection rekeying
  rxgk: Support OpenAFS's rxgk implementation


 crypto/krb5/Kconfig  |9 +
 crypto/krb5/Makefile |   11 +-
 crypto/krb5/internal.h   |  101 +++
 crypto/krb5/kdf.c|  223 ++
 crypto/krb5/main.c   |  190 +
 crypto/krb5/rfc3961_simplified.c |  732 ++
 crypto/krb5/rfc3962_aes.c|  140 
 crypto/krb5/rfc6803_camellia.c   |  249 ++
 crypto/krb5/rfc8009_aes2.c   |  440 +++
 crypto/krb5/selftest.c   |  543 +
 crypto/krb5/selftest_data.c  |  289 +++
 fs/afs/misc.c|   13 +
 include/crypto/krb5.h|  100 +++
 include/keys/rxrpc-type.h|   17 +
 include/trace/events/rxrpc.h |4 +
 include/uapi/linux/rxrpc.h   |   17 +
 net/rxrpc/Kconfig|   10 +
 net/rxrpc/Makefile   |5 +
 net/rxrpc/ar-internal.h  |   20 +
 net/rxrpc/conn_object.c  |2 +
 net/rxrpc/key.c  |  319 
 net/rxrpc/rxgk.c | 1232 ++
 net/rxrpc/rxgk_app.c |  424 ++
 net/rxrpc/rxgk_common.h  |  164 
 net/rxrpc/rxgk_kdf.c |  271 +++
 net/rxrpc/security.c |6 +
 26 files changed, 5530 insertions(+), 1 deletion(-)
 create mode 100644 crypto/krb5/kdf.c
 create mode 100644 crypto/krb5/rfc3961_simplified.c
 create mode 100644 crypto/krb5/rfc3962_aes.c
 create mode 100644 crypto/krb5/rfc6803_camellia.c
 create mode 100644 crypto/krb5/rfc8009_aes2.c
 create mode 100644 crypto/krb5/s

Re: INFO: rcu detected stall in security_file_open (3)

2020-11-06 Thread David Howells
#syz fix: afs: Fix cell removal



Re: INFO: rcu detected stall in ip_list_rcv

2020-11-06 Thread David Howells
#syz fix: afs: Fix cell removal



gssapi, crypto and afs/rxrpc

2020-10-16 Thread David Howells
Hi Herbert, Dave, Trond,

I've written basic gssapi-derived security support for AF_RXRPC:


https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-rxgk

I've borrowed some bits from net/sunrpc/auth_gss/ but there's a lot in there
that is quite specific to the sunrpc module that makes it hard to use for
rxrpc (dprintk, struct xdr_buf).

Further, I've implemented some more enctypes that aren't supported yet by
gssapi (AES with sha256/sha384 and Camellia), and that requires some changes
to the handling as AES with sha384 has a 24-byte checksum size and a 24-byte
calculated key size for Kc and Ki but a 32-byte Ke.

Should I pull the core out and try to make it common?  If so, should I move it
to crypto/ or lib/, or perhaps put it in net/gssapi/?

There are two components to it:

 (1) Key derivation steps.

 My thought is to use xdr_netobj or something similar for to communicate
 between the steps (though I'd prefer to change .data to be a void* rather
 than u8*).

 (2) Encryption/checksumming.

 My thought is to make this interface use scattergather lists[*] since
 that's what the crypto encryption API requires (though not the hash API).

If I do this, should I create a "kerberos" crypto API for the data wrapping
functions?  I'm not sure that it quite matches the existing APIs because the
size of the input data will likely not match the size of the output data and
it's "one shot" as it needs to deal with a checksum.

Or I can just keep my implementation separate inside net/rxrpc/.

David

[*] That said, I'm not exactly sure how the sunrpc stuff works, so this might
not work for that.



Re: WARNING: proc registration bug in afs_manage_cell

2020-10-16 Thread David Howells
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git 
7530d3eb3dcf1a30750e8e7f1f88b782b96b72b8



[PATCH net-next 1/2] rxrpc: Fix bundle counting for exclusive connections

2020-10-15 Thread David Howells
Fix rxrpc_unbundle_conn() to not drop the bundle usage count when cleaning
up an exclusive connection.

Based on the suggested fix from Hillf Danton.

Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager")
Reported-by: syzbot+d57aaf84dd8a550e6...@syzkaller.appspotmail.com
Signed-off-by: David Howells 
cc: Hillf Danton 
---

 net/rxrpc/conn_client.c |5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 78c845a4f1ad..5d9adfd4c84f 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -901,7 +901,7 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection 
*conn)
struct rxrpc_bundle *bundle = conn->bundle;
struct rxrpc_local *local = bundle->params.local;
unsigned int bindex;
-   bool need_drop = false;
+   bool need_drop = false, need_put = false;
int i;
 
_enter("C=%x", conn->debug_id);
@@ -928,10 +928,11 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection 
*conn)
if (i == ARRAY_SIZE(bundle->conns) && 
!bundle->params.exclusive) {
_debug("erase bundle");
rb_erase(&bundle->local_node, &local->client_bundles);
+   need_put = true;
}
 
spin_unlock(&local->client_bundles_lock);
-   if (i == ARRAY_SIZE(bundle->conns))
+   if (need_put)
rxrpc_put_bundle(bundle);
}
 




[PATCH net-next 2/2] rxrpc: Fix loss of final ack on shutdown

2020-10-15 Thread David Howells
Fix the loss of transmission of a call's final ack when a socket gets shut
down.  This means that the server will retransmit the last data packet or
send a ping ack and then get an ICMP indicating the port got closed.  The
server will then view this as a failure.

Fixes: 3136ef49a14c ("rxrpc: Delay terminal ACK transmission on a client call")
Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |1 +
 net/rxrpc/conn_client.c |3 +++
 net/rxrpc/conn_event.c  |6 +++---
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index c9287b6551df..dce48162f6c2 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -831,6 +831,7 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *);
  * conn_event.c
  */
 void rxrpc_process_connection(struct work_struct *);
+void rxrpc_process_delayed_final_acks(struct rxrpc_connection *, bool);
 
 /*
  * conn_object.c
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 5d9adfd4c84f..7e574c75be8e 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -906,6 +906,9 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection 
*conn)
 
_enter("C=%x", conn->debug_id);
 
+   if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
+   rxrpc_process_delayed_final_acks(conn, true);
+
spin_lock(&bundle->channel_lock);
bindex = conn->bundle_shift / RXRPC_MAXCALLS;
if (bundle->conns[bindex] == conn) {
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 6b7c6f4a82e3..aff184145ffa 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -397,7 +397,7 @@ static void rxrpc_secure_connection(struct rxrpc_connection 
*conn)
 /*
  * Process delayed final ACKs that we haven't subsumed into a subsequent call.
  */
-static void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn)
+void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool 
force)
 {
unsigned long j = jiffies, next_j;
unsigned int channel;
@@ -416,7 +416,7 @@ static void rxrpc_process_delayed_final_acks(struct 
rxrpc_connection *conn)
smp_rmb(); /* vs rxrpc_disconnect_client_call */
ack_at = READ_ONCE(chan->final_ack_at);
 
-   if (time_before(j, ack_at)) {
+   if (time_before(j, ack_at) && !force) {
if (time_before(ack_at, next_j)) {
next_j = ack_at;
set = true;
@@ -450,7 +450,7 @@ static void rxrpc_do_process_connection(struct 
rxrpc_connection *conn)
 
/* Process delayed ACKs whose time has come. */
if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
-   rxrpc_process_delayed_final_acks(conn);
+   rxrpc_process_delayed_final_acks(conn, false);
 
/* go through the conn-level event packets, releasing the ref on this
 * connection that each one has when we've finished with it */




[PATCH net-next 0/2] rxrpc: Fixes

2020-10-15 Thread David Howells



Here are a couple of fixes that need to be applied on top of rxrpc patches
in net-next:

 (1) Fix a bug in the connection bundle changes in the net-next tree.

 (2) Fix the loss of final ACK on socket shutdown.

The patches are tagged here:

git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
rxrpc-next-20201015

David
---
David Howells (2):
  rxrpc: Fix bundle counting for exclusive connections
  rxrpc: Fix loss of final ack on shutdown


 net/rxrpc/ar-internal.h | 1 +
 net/rxrpc/conn_client.c | 3 +++
 net/rxrpc/conn_event.c  | 6 +++---
 3 files changed, 7 insertions(+), 3 deletions(-)




Re: [PATCH 1/5] rxrpc: use semicolons rather than commas to separate statements

2020-10-12 Thread David Howells
Julia Lawall  wrote:

> - call->completion = compl,
> + call->completion = compl;

Looks good.  Do you want me to pick up the patch or send it yourself?

If the latter:

Acked-by: David Howells 



Re: [PATCH net 0/6] rxrpc: Miscellaneous fixes

2020-10-06 Thread David Howells
David Miller  wrote:

> I think the ".txt" at the end of the branch name is a mistake.

Sigh.  That's the name of the file with the cover message in it (named for the
tag).  I need to adjust my script yet more to check not only that the tag name
is in there, but that it also doesn't have any bits on the end.

David



[PATCH net 5/6] rxrpc: The server keyring isn't network-namespaced

2020-10-05 Thread David Howells
The keyring containing the server's tokens isn't network-namespaced, so it
shouldn't be looked up with a network namespace.  It is expected to be
owned specifically by the server, so namespacing is unnecessary.

Fixes: a58946c158a0 ("keys: Pass the network namespace into request_key 
mechanism")
Signed-off-by: David Howells 
---

 net/rxrpc/key.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index c668e4b7dbff..75e84ed4fa63 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -940,7 +940,7 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t 
optval, int optlen)
if (IS_ERR(description))
return PTR_ERR(description);
 
-   key = request_key_net(&key_type_keyring, description, 
sock_net(&rx->sk), NULL);
+   key = request_key(&key_type_keyring, description, NULL);
if (IS_ERR(key)) {
kfree(description);
_leave(" = %ld", PTR_ERR(key));




[PATCH net 4/6] rxrpc: Fix accept on a connection that need securing

2020-10-05 Thread David Howells
When a new incoming call arrives at an userspace rxrpc socket on a new
connection that has a security class set, the code currently pushes it onto
the accept queue to hold a ref on it for the socket.  This doesn't work,
however, as recvmsg() pops it off, notices that it's in the SERVER_SECURING
state and discards the ref.  This means that the call runs out of refs too
early and the kernel oopses.

By contrast, a kernel rxrpc socket manually pre-charges the incoming call
pool with calls that already have user call IDs assigned, so they are ref'd
by the call tree on the socket.

Change the mode of operation for userspace rxrpc server sockets to work
like this too.  Although this is a UAPI change, server sockets aren't
currently functional.

Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Signed-off-by: David Howells 
---

 include/uapi/linux/rxrpc.h |2 
 net/rxrpc/ar-internal.h|7 -
 net/rxrpc/call_accept.c|  263 ++--
 net/rxrpc/call_object.c|5 -
 net/rxrpc/conn_event.c |2 
 net/rxrpc/recvmsg.c|   36 --
 net/rxrpc/sendmsg.c|   15 +--
 7 files changed, 49 insertions(+), 281 deletions(-)

diff --git a/include/uapi/linux/rxrpc.h b/include/uapi/linux/rxrpc.h
index 4accfa7e266d..8f8dc7a937a4 100644
--- a/include/uapi/linux/rxrpc.h
+++ b/include/uapi/linux/rxrpc.h
@@ -51,11 +51,11 @@ enum rxrpc_cmsg_type {
RXRPC_BUSY  = 6,/* -r: server busy received [terminal] 
*/
RXRPC_LOCAL_ERROR   = 7,/* -r: local error generated [terminal] 
*/
RXRPC_NEW_CALL  = 8,/* -r: [Service] new incoming call 
notification */
-   RXRPC_ACCEPT= 9,/* s-: [Service] accept request */
RXRPC_EXCLUSIVE_CALL= 10,   /* s-: Call should be on exclusive 
connection */
RXRPC_UPGRADE_SERVICE   = 11,   /* s-: Request service upgrade for 
client call */
RXRPC_TX_LENGTH = 12,   /* s-: Total length of Tx data */
RXRPC_SET_CALL_TIMEOUT  = 13,   /* s-: Set one or more call timeouts */
+   RXRPC_CHARGE_ACCEPT = 14,   /* s-: Charge the accept pool with a 
user call ID */
RXRPC__SUPPORTED
 };
 
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 884cff7bb169..97aebb5d19db 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -518,7 +518,6 @@ enum rxrpc_call_state {
RXRPC_CALL_CLIENT_RECV_REPLY,   /* - client receiving reply phase */
RXRPC_CALL_SERVER_PREALLOC, /* - service preallocation */
RXRPC_CALL_SERVER_SECURING, /* - server securing request connection 
*/
-   RXRPC_CALL_SERVER_ACCEPTING,/* - server accepting request */
RXRPC_CALL_SERVER_RECV_REQUEST, /* - server receiving request */
RXRPC_CALL_SERVER_ACK_REQUEST,  /* - server pending ACK of request */
RXRPC_CALL_SERVER_SEND_REPLY,   /* - server sending reply */
@@ -714,8 +713,8 @@ struct rxrpc_ack_summary {
 enum rxrpc_command {
RXRPC_CMD_SEND_DATA,/* send data message */
RXRPC_CMD_SEND_ABORT,   /* request abort generation */
-   RXRPC_CMD_ACCEPT,   /* [server] accept incoming call */
RXRPC_CMD_REJECT_BUSY,  /* [server] reject a call as busy */
+   RXRPC_CMD_CHARGE_ACCEPT,/* [server] charge accept preallocation 
*/
 };
 
 struct rxrpc_call_params {
@@ -755,9 +754,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct 
rxrpc_local *,
   struct rxrpc_sock *,
   struct sk_buff *);
 void rxrpc_accept_incoming_calls(struct rxrpc_local *);
-struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *, unsigned long,
-rxrpc_notify_rx_t);
-int rxrpc_reject_call(struct rxrpc_sock *);
+int rxrpc_user_charge_accept(struct rxrpc_sock *, unsigned long);
 
 /*
  * call_event.c
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index ef160566aa9a..8df1964db333 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -39,8 +39,9 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
  unsigned int debug_id)
 {
const void *here = __builtin_return_address(0);
-   struct rxrpc_call *call;
+   struct rxrpc_call *call, *xcall;
struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
+   struct rb_node *parent, **pp;
int max, tmp;
unsigned int size = RXRPC_BACKLOG_MAX;
unsigned int head, tail, call_head, call_tail;
@@ -94,7 +95,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
}
 
/* Now it gets complicated, because calls get registered with the
-* socket here, particularly if a user ID is preassigned by the user.
+* socket here, with a user ID preassigned by the user.
 */
call

[PATCH net 6/6] rxrpc: Fix server keyring leak

2020-10-05 Thread David Howells
If someone calls setsockopt() twice to set a server key keyring, the first
keyring is leaked.

Fix it to return an error instead if the server key keyring is already set.

Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by 
userspace and kernel both")
Signed-off-by: David Howells 
---

 net/rxrpc/key.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 75e84ed4fa63..2e8bd3b97301 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -903,7 +903,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t 
optval, int optlen)
 
_enter("");
 
-   if (optlen <= 0 || optlen > PAGE_SIZE - 1)
+   if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
return -EINVAL;
 
description = memdup_sockptr_nul(optval, optlen);




[PATCH net 3/6] rxrpc: Fix some missing _bh annotations on locking conn->state_lock

2020-10-05 Thread David Howells
conn->state_lock may be taken in softirq mode, but a previous patch
replaced an outer lock in the response-packet event handling code, and lost
the _bh from that when doing so.

Fix this by applying the _bh annotation to the state_lock locking.

Fixes: a1399f8bb033 ("rxrpc: Call channels should have separate call number 
spaces")
Signed-off-by: David Howells 
---

 net/rxrpc/conn_event.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 447f55ca6886..6e972b4823ef 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -340,18 +340,18 @@ static int rxrpc_process_event(struct rxrpc_connection 
*conn,
return ret;
 
spin_lock(&conn->channel_lock);
-   spin_lock(&conn->state_lock);
+   spin_lock_bh(&conn->state_lock);
 
if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
conn->state = RXRPC_CONN_SERVICE;
-   spin_unlock(&conn->state_lock);
+   spin_unlock_bh(&conn->state_lock);
for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
rxrpc_call_is_secure(
rcu_dereference_protected(
conn->channels[loop].call,

lockdep_is_held(&conn->channel_lock)));
} else {
-   spin_unlock(&conn->state_lock);
+   spin_unlock_bh(&conn->state_lock);
}
 
spin_unlock(&conn->channel_lock);




[PATCH net 2/6] rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()

2020-10-05 Thread David Howells
If rxrpc_read() (which allows KEYCTL_READ to read a key), sees a token of a
type it doesn't recognise, it can BUG in a couple of places, which is
unnecessary as it can easily get back to userspace.

Fix this to print an error message instead.

Fixes: 99455153d067 ("RxRPC: Parse security index 5 keys (Kerberos 5)")
Signed-off-by: David Howells 
---

 net/rxrpc/key.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 8f7d7a6187db..c668e4b7dbff 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -1107,7 +1107,8 @@ static long rxrpc_read(const struct key *key,
break;
 
default: /* we have a ticket we can't encode */
-   BUG();
+   pr_err("Unsupported key token type (%u)\n",
+  token->security_index);
continue;
}
 
@@ -1223,7 +1224,6 @@ static long rxrpc_read(const struct key *key,
break;
 
default:
-   BUG();
break;
}
 




[PATCH net 0/6] rxrpc: Miscellaneous fixes

2020-10-05 Thread David Howells


Here are some miscellaneous rxrpc fixes:

 (1) Fix the xdr encoding of the contents read from an rxrpc key.

 (2) Fix a BUG() for a unsupported encoding type.

 (3) Fix missing _bh lock annotations.

 (4) Fix acceptance handling for an incoming call where the incoming call
 is encrypted.

 (5) The server token keyring isn't network namespaced - it belongs to the
 server, so there's no need.  Namespacing it means that request_key()
 fails to find it.

 (6) Fix a leak of the server keyring.

The patches are tagged here:

git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
rxrpc-fixes-20201005.txt

and can also be found on the following branch:


http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes

David
---
David Howells (5):
  rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
  rxrpc: Fix some missing _bh annotations on locking conn->state_lock
  rxrpc: Fix accept on a connection that need securing
  rxrpc: The server keyring isn't network-namespaced
  rxrpc: Fix server keyring leak

Marc Dionne (1):
  rxrpc: Fix rxkad token xdr encoding


 include/uapi/linux/rxrpc.h |   2 +-
 net/rxrpc/ar-internal.h|   7 +-
 net/rxrpc/call_accept.c| 263 ++---
 net/rxrpc/call_object.c|   5 +-
 net/rxrpc/conn_event.c |   8 +-
 net/rxrpc/key.c|   8 +-
 net/rxrpc/recvmsg.c|  36 +
 net/rxrpc/sendmsg.c|  15 +--
 8 files changed, 56 insertions(+), 288 deletions(-)




[PATCH net 1/6] rxrpc: Fix rxkad token xdr encoding

2020-10-05 Thread David Howells
From: Marc Dionne 

The session key should be encoded with just the 8 data bytes and
no length; ENCODE_DATA precedes it with a 4 byte length, which
confuses some existing tools that try to parse this format.

Add an ENCODE_BYTES macro that does not include a length, and use
it for the key.  Also adjust the expected length.

Note that commit 774521f353e1d ("rxrpc: Fix an assertion in
rxrpc_read()") had fixed a BUG by changing the length rather than
fixing the encoding.  The original length was correct.

Fixes: 99455153d067 ("RxRPC: Parse security index 5 keys (Kerberos 5)")
Signed-off-by: Marc Dionne 
Signed-off-by: David Howells 
---

 net/rxrpc/key.c |   12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 94c3df392651..8f7d7a6187db 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -1072,7 +1072,7 @@ static long rxrpc_read(const struct key *key,
 
switch (token->security_index) {
case RXRPC_SECURITY_RXKAD:
-   toksize += 9 * 4;   /* viceid, kvno, key*2 + len, 
begin,
+   toksize += 8 * 4;   /* viceid, kvno, key*2, begin,
 * end, primary, tktlen */
toksize += RND(token->kad->ticket_len);
break;
@@ -1138,6 +1138,14 @@ static long rxrpc_read(const struct key *key,
memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));\
xdr += (_l + 3) >> 2;   \
} while(0)
+#define ENCODE_BYTES(l, s) \
+   do {\
+   u32 _l = (l);   \
+   memcpy(xdr, (s), _l);   \
+   if (_l & 3) \
+   memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));\
+   xdr += (_l + 3) >> 2;   \
+   } while(0)
 #define ENCODE64(x)\
do {\
__be64 y = cpu_to_be64(x);  \
@@ -1165,7 +1173,7 @@ static long rxrpc_read(const struct key *key,
case RXRPC_SECURITY_RXKAD:
ENCODE(token->kad->vice_id);
ENCODE(token->kad->kvno);
-   ENCODE_DATA(8, token->kad->session_key);
+   ENCODE_BYTES(8, token->kad->session_key);
ENCODE(token->kad->start);
ENCODE(token->kad->expiry);
ENCODE(token->kad->primary_flag);




  1   2   3   4   5   6   7   8   9   10   >