diff options
Diffstat (limited to 'net/rxrpc/rxkad.c')
| -rw-r--r-- | net/rxrpc/rxkad.c | 57 | 
1 files changed, 29 insertions, 28 deletions
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 6b32d61d4cdc..f1a68270862d 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -145,16 +145,17 @@ 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) +static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)  { -	size_t shdr, buf_size, chunk; +	struct rxrpc_txbuf *txb; +	size_t shdr, space; + +	remain = min(remain, 65535 - sizeof(struct rxrpc_wire_header));  	switch (call->conn->security_level) {  	default: -		buf_size = chunk = min_t(size_t, remain, RXRPC_JUMBO_DATALEN); -		shdr = 0; -		goto out; +		space = min_t(size_t, remain, RXRPC_JUMBO_DATALEN); +		return rxrpc_alloc_data_txbuf(call, space, 0, gfp);  	case RXRPC_SECURITY_AUTH:  		shdr = sizeof(struct rxkad_level1_hdr);  		break; @@ -163,17 +164,16 @@ static int rxkad_how_much_data(struct rxrpc_call *call, size_t remain,  		break;  	} -	buf_size = round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN); +	space = min_t(size_t, round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN), remain + shdr); +	space = round_up(space, RXKAD_ALIGN); -	chunk = buf_size - shdr; -	if (remain < chunk) -		buf_size = round_up(shdr + remain, RXKAD_ALIGN); +	txb = rxrpc_alloc_data_txbuf(call, space, RXKAD_ALIGN, gfp); +	if (!txb) +		return NULL; -out: -	*_buf_size = buf_size; -	*_data_size = chunk; -	*_offset = shdr; -	return 0; +	txb->offset += shdr; +	txb->space -= shdr; +	return txb;  }  /* @@ -251,7 +251,8 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,  				    struct rxrpc_txbuf *txb,  				    struct skcipher_request *req)  { -	struct rxkad_level1_hdr *hdr = (void *)txb->data; +	struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; +	struct rxkad_level1_hdr *hdr = (void *)(whdr + 1);  	struct rxrpc_crypt iv;  	struct scatterlist sg;  	size_t pad; @@ -259,7 +260,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,  	_enter(""); -	check = txb->seq ^ ntohl(txb->wire.callNumber); +	check = txb->seq ^ call->call_id;  	hdr->data_size = htonl((u32)check << 16 | txb->len);  	txb->len += sizeof(struct rxkad_level1_hdr); @@ -267,14 +268,14 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,  	pad = RXKAD_ALIGN - pad;  	pad &= RXKAD_ALIGN - 1;  	if (pad) { -		memset(txb->data + txb->offset, 0, pad); +		memset(txb->kvec[0].iov_base + txb->offset, 0, pad);  		txb->len += pad;  	}  	/* start the encryption afresh */  	memset(&iv, 0, sizeof(iv)); -	sg_init_one(&sg, txb->data, 8); +	sg_init_one(&sg, hdr, 8);  	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); @@ -293,7 +294,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,  				       struct skcipher_request *req)  {  	const struct rxrpc_key_token *token; -	struct rxkad_level2_hdr *rxkhdr = (void *)txb->data; +	struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base; +	struct rxkad_level2_hdr *rxkhdr = (void *)(whdr + 1);  	struct rxrpc_crypt iv;  	struct scatterlist sg;  	size_t pad; @@ -302,7 +304,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,  	_enter(""); -	check = txb->seq ^ ntohl(txb->wire.callNumber); +	check = txb->seq ^ call->call_id;  	rxkhdr->data_size = htonl(txb->len | (u32)check << 16);  	rxkhdr->checksum = 0; @@ -312,7 +314,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,  	pad = RXKAD_ALIGN - pad;  	pad &= RXKAD_ALIGN - 1;  	if (pad) { -		memset(txb->data + txb->offset, 0, pad); +		memset(txb->kvec[0].iov_base + txb->offset, 0, pad);  		txb->len += pad;  	} @@ -320,7 +322,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,  	token = call->conn->key->payload.data[0];  	memcpy(&iv, token->kad->session_key, sizeof(iv)); -	sg_init_one(&sg, txb->data, txb->len); +	sg_init_one(&sg, rxkhdr, txb->len);  	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, txb->len, iv.x); @@ -362,9 +364,9 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)  	memcpy(&iv, call->conn->rxkad.csum_iv.x, sizeof(iv));  	/* calculate the security checksum */ -	x = (ntohl(txb->wire.cid) & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT); +	x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);  	x |= txb->seq & 0x3fffffff; -	crypto.buf[0] = txb->wire.callNumber; +	crypto.buf[0] = htonl(call->call_id);  	crypto.buf[1] = htonl(x);  	sg_init_one(&sg, crypto.buf, 8); @@ -378,7 +380,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)  	y = (y >> 16) & 0xffff;  	if (y == 0)  		y = 1; /* zero checksums are not permitted */ -	txb->wire.cksum = htons(y); +	txb->cksum = htons(y);  	switch (call->conn->security_level) {  	case RXRPC_SECURITY_PLAIN: @@ -726,7 +728,6 @@ static int rxkad_send_response(struct rxrpc_connection *conn,  	rxrpc_local_dont_fragment(conn->local, false);  	ret = kernel_sendmsg(conn->local->socket, &msg, iov, 3, len); -	rxrpc_local_dont_fragment(conn->local, true);  	if (ret < 0) {  		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,  				    rxrpc_tx_point_rxkad_response); @@ -1256,7 +1257,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, +	.alloc_txbuf			= rxkad_alloc_txbuf,  	.secure_packet			= rxkad_secure_packet,  	.verify_packet			= rxkad_verify_packet,  	.free_call_crypto		= rxkad_free_call_crypto,  |