diff options
author | David Howells <dhowells@redhat.com> | 2020-09-16 02:34:39 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2020-11-23 20:53:11 +0100 |
commit | d7d775b1ffb15408a60ec12dc9d02d4751e6b10a (patch) | |
tree | fd5ec2fd330a6857061784d970495ccae899157c /net/rxrpc/rxkad.c | |
parent | rxrpc: rxkad: Don't use pskb_pull() to advance through the response packet (diff) | |
download | linux-d7d775b1ffb15408a60ec12dc9d02d4751e6b10a.tar.xz linux-d7d775b1ffb15408a60ec12dc9d02d4751e6b10a.zip |
rxrpc: Ask the security class how much space to allow in a packet
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 <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/rxkad.c')
-rw-r--r-- | net/rxrpc/rxkad.c | 61 |
1 files changed, 52 insertions, 9 deletions
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_SZ 40 /* 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_ALIGN 8 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; - conn->security_size = sizeof(struct rxkad_level1_hdr); - break; case RXRPC_SECURITY_ENCRYPT: - conn->size_align = 8; - conn->security_size = sizeof(struct rxkad_level2_hdr); break; default: ret = -EKEYREJECTED; @@ -148,6 +143,40 @@ error: } /* + * Work out how much data we can put in a packet. + */ +static int rxkad_how_much_data(struct rxrpc_call *call, size_t remain, + size_t *_buf_size, size_t *_data_size, size_t *_offset) +{ + size_t shdr, buf_size, chunk; + + switch (call->conn->params.security_level) { + default: + buf_size = chunk = min_t(size_t, remain, RXRPC_JUMBO_DATALEN); + shdr = 0; + goto out; + case RXRPC_SECURITY_AUTH: + shdr = sizeof(struct rxkad_level1_hdr); + break; + case RXRPC_SECURITY_ENCRYPT: + shdr = sizeof(struct rxkad_level2_hdr); + break; + } + + buf_size = round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN); + + chunk = buf_size - shdr; + if (remain < chunk) + buf_size = round_up(shdr + remain, RXKAD_ALIGN); + +out: + *_buf_size = buf_size; + *_data_size = chunk; + *_offset = shdr; + return 0; +} + +/* * prime the encryption state with the invariant parts of a connection's * description */ @@ -237,6 +266,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, struct rxkad_level1_hdr hdr; struct rxrpc_crypt iv; struct scatterlist sg; + size_t pad; u16 check; _enter(""); @@ -247,6 +277,12 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, hdr.data_size = htonl(data_size); memcpy(skb->head, &hdr, sizeof(hdr)); + pad = sizeof(struct rxkad_level1_hdr) + data_size; + pad = RXKAD_ALIGN - pad; + pad &= RXKAD_ALIGN - 1; + if (pad) + skb_put_zero(skb, pad); + /* start the encryption afresh */ memset(&iv, 0, sizeof(iv)); @@ -275,6 +311,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, struct rxrpc_crypt iv; struct scatterlist sg[16]; unsigned int len; + size_t pad; u16 check; int err; @@ -288,6 +325,12 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, rxkhdr.checksum = 0; memcpy(skb->head, &rxkhdr, sizeof(rxkhdr)); + pad = sizeof(struct rxkad_level2_hdr) + data_size; + pad = RXKAD_ALIGN - pad; + pad &= RXKAD_ALIGN - 1; + if (pad) + skb_put_zero(skb, pad); + /* encrypt from the session key */ token = call->conn->params.key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); @@ -303,8 +346,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, if (skb_shinfo(skb)->nr_frags > 16) goto out; - len = data_size + call->conn->size_align - 1; - len &= ~(call->conn->size_align - 1); + len = round_up(data_size, RXKAD_ALIGN); sg_init_table(sg, ARRAY_SIZE(sg)); err = skb_to_sgvec(skb, sg, 8, len); @@ -1353,6 +1395,7 @@ const struct rxrpc_security rxkad = { .free_preparse_server_key = rxkad_free_preparse_server_key, .destroy_server_key = rxkad_destroy_server_key, .init_connection_security = rxkad_init_connection_security, + .how_much_data = rxkad_how_much_data, .secure_packet = rxkad_secure_packet, .verify_packet = rxkad_verify_packet, .free_call_crypto = rxkad_free_call_crypto, |