diff options
Diffstat (limited to 'net/rxrpc/rxkad.c')
-rw-r--r-- | net/rxrpc/rxkad.c | 337 |
1 files changed, 191 insertions, 146 deletions
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index d7a9ab5a9..f0aeb8163 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -9,11 +9,11 @@ * 2 of the License, or (at your option) any later version. */ +#include <crypto/skcipher.h> #include <linux/module.h> #include <linux/net.h> #include <linux/skbuff.h> #include <linux/udp.h> -#include <linux/crypto.h> #include <linux/scatterlist.h> #include <linux/ctype.h> #include <linux/slab.h> @@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE * packets */ -static struct crypto_blkcipher *rxkad_ci; +static struct crypto_skcipher *rxkad_ci; static DEFINE_MUTEX(rxkad_ci_mutex); /* @@ -61,7 +61,7 @@ static DEFINE_MUTEX(rxkad_ci_mutex); */ static int rxkad_init_connection_security(struct rxrpc_connection *conn) { - struct crypto_blkcipher *ci; + struct crypto_skcipher *ci; struct rxrpc_key_token *token; int ret; @@ -70,15 +70,15 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn) token = conn->key->payload.data[0]; conn->security_ix = token->security_index; - ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); + ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { _debug("no cipher"); ret = PTR_ERR(ci); goto error; } - if (crypto_blkcipher_setkey(ci, token->kad->session_key, - sizeof(token->kad->session_key)) < 0) + if (crypto_skcipher_setkey(ci, token->kad->session_key, + sizeof(token->kad->session_key)) < 0) BUG(); switch (conn->security_level) { @@ -113,7 +113,7 @@ error: static void rxkad_prime_packet_security(struct rxrpc_connection *conn) { struct rxrpc_key_token *token; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct scatterlist sg[2]; struct rxrpc_crypt iv; struct { @@ -128,21 +128,23 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) token = conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = conn->cipher; - desc.info = iv.x; - desc.flags = 0; - - tmpbuf.x[0] = conn->epoch; - tmpbuf.x[1] = conn->cid; + tmpbuf.x[0] = htonl(conn->epoch); + tmpbuf.x[1] = htonl(conn->cid); tmpbuf.x[2] = 0; tmpbuf.x[3] = htonl(conn->security_ix); sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv)); - ASSERTCMP(conn->csum_iv.n[0], ==, tmpbuf.x[2]); + ASSERTCMP((u32 __force)conn->csum_iv.n[0], ==, (u32 __force)tmpbuf.x[2]); _leave(""); } @@ -156,7 +158,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, void *sechdr) { struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; struct { @@ -169,21 +171,24 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, _enter(""); - check = ntohl(sp->hdr.seq ^ sp->hdr.callNumber); - data_size |= (u32) check << 16; + check = sp->hdr.seq ^ sp->hdr.callNumber; + data_size |= (u32)check << 16; tmpbuf.hdr.data_size = htonl(data_size); memcpy(&tmpbuf.first, sechdr + 4, sizeof(tmpbuf.first)); /* start the encryption afresh */ memset(&iv, 0, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); memcpy(sechdr, &tmpbuf, sizeof(tmpbuf)); @@ -195,81 +200,91 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, * wholly encrypt a packet (level 2 security) */ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, - struct sk_buff *skb, - u32 data_size, - void *sechdr) + struct sk_buff *skb, + u32 data_size, + void *sechdr) { const struct rxrpc_key_token *token; struct rxkad_level2_hdr rxkhdr __attribute__((aligned(8))); /* must be all on one page */ struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[16]; struct sk_buff *trailer; unsigned int len; u16 check; int nsg; + int err; sp = rxrpc_skb(skb); _enter(""); - check = ntohl(sp->hdr.seq ^ sp->hdr.callNumber); + check = sp->hdr.seq ^ sp->hdr.callNumber; - rxkhdr.data_size = htonl(data_size | (u32) check << 16); + rxkhdr.data_size = htonl(data_size | (u32)check << 16); rxkhdr.checksum = 0; /* encrypt from the session key */ token = call->conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; sg_init_one(&sg[0], sechdr, sizeof(rxkhdr)); sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(rxkhdr)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(rxkhdr), iv.x); + + crypto_skcipher_encrypt(req); /* we want to encrypt the skbuff in-place */ nsg = skb_cow_data(skb, 0, &trailer); + err = -ENOMEM; if (nsg < 0 || nsg > 16) - return -ENOMEM; + goto out; len = data_size + call->conn->size_align - 1; len &= ~(call->conn->size_align - 1); sg_init_table(sg, nsg); skb_to_sgvec(skb, sg, 0, len); - crypto_blkcipher_encrypt_iv(&desc, sg, sg, len); + + skcipher_request_set_crypt(req, sg, sg, len, iv.x); + + crypto_skcipher_encrypt(req); _leave(" = 0"); - return 0; + err = 0; + +out: + skcipher_request_zero(req); + return err; } /* * checksum an RxRPC packet header */ static int rxkad_secure_packet(const struct rxrpc_call *call, - struct sk_buff *skb, - size_t data_size, - void *sechdr) + struct sk_buff *skb, + size_t data_size, + void *sechdr) { struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; struct { __be32 x[2]; } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ - __be32 x; - u32 y; + u32 x, y; int ret; sp = rxrpc_skb(skb); _enter("{%d{%x}},{#%u},%zu,", - call->debug_id, key_serial(call->conn->key), ntohl(sp->hdr.seq), + call->debug_id, key_serial(call->conn->key), sp->hdr.seq, data_size); if (!call->conn->cipher) @@ -281,25 +296,28 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; /* calculate the security checksum */ - x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); - x |= sp->hdr.seq & cpu_to_be32(0x3fffffff); - tmpbuf.x[0] = sp->hdr.callNumber; - tmpbuf.x[1] = x; + x = call->channel << (32 - RXRPC_CIDSHIFT); + x |= sp->hdr.seq & 0x3fffffff; + tmpbuf.x[0] = htonl(sp->hdr.callNumber); + tmpbuf.x[1] = htonl(x); sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); y = ntohl(tmpbuf.x[1]); y = (y >> 16) & 0xffff; if (y == 0) y = 1; /* zero checksums are not permitted */ - sp->hdr.cksum = htons(y); + sp->hdr.cksum = y; switch (call->conn->security_level) { case RXRPC_SECURITY_PLAIN: @@ -330,7 +348,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, { struct rxkad_level1_hdr sechdr; struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[16]; struct sk_buff *trailer; @@ -352,11 +370,13 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, /* start the decryption afresh */ memset(&iv, 0, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; - crypto_blkcipher_decrypt_iv(&desc, sg, sg, 8); + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, 8, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); /* remove the decrypted packet length */ if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) @@ -368,7 +388,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, data_size = buf & 0xffff; check = buf >> 16; - check ^= ntohl(sp->hdr.seq ^ sp->hdr.callNumber); + check ^= sp->hdr.seq ^ sp->hdr.callNumber; check &= 0xffff; if (check != 0) { *_abort_code = RXKADSEALEDINCON; @@ -405,7 +425,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, const struct rxrpc_key_token *token; struct rxkad_level2_hdr sechdr; struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist _sg[4], *sg; struct sk_buff *trailer; @@ -435,11 +455,13 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, /* decrypt from the session key */ token = call->conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; - crypto_blkcipher_decrypt_iv(&desc, sg, sg, skb->len); + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, skb->len, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); if (sg != _sg) kfree(sg); @@ -453,7 +475,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, data_size = buf & 0xffff; check = buf >> 16; - check ^= ntohl(sp->hdr.seq ^ sp->hdr.callNumber); + check ^= sp->hdr.seq ^ sp->hdr.callNumber; check &= 0xffff; if (check != 0) { *_abort_code = RXKADSEALEDINCON; @@ -487,23 +509,21 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, struct sk_buff *skb, u32 *_abort_code) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_skb_priv *sp; struct rxrpc_crypt iv; struct scatterlist sg[2]; struct { __be32 x[2]; } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ - __be32 x; - __be16 cksum; - u32 y; + u16 cksum; + u32 x, y; int ret; sp = rxrpc_skb(skb); _enter("{%d{%x}},{#%u}", - call->debug_id, key_serial(call->conn->key), - ntohl(sp->hdr.seq)); + call->debug_id, key_serial(call->conn->key), sp->hdr.seq); if (!call->conn->cipher) return 0; @@ -516,26 +536,28 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; /* validate the security checksum */ - x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); - x |= sp->hdr.seq & cpu_to_be32(0x3fffffff); - tmpbuf.x[0] = call->call_id; - tmpbuf.x[1] = x; + x = call->channel << (32 - RXRPC_CIDSHIFT); + x |= sp->hdr.seq & 0x3fffffff; + tmpbuf.x[0] = htonl(call->call_id); + tmpbuf.x[1] = htonl(x); sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); y = ntohl(tmpbuf.x[1]); - y = (y >> 16) & 0xffff; - if (y == 0) - y = 1; /* zero checksums are not permitted */ + cksum = (y >> 16) & 0xffff; + if (cksum == 0) + cksum = 1; /* zero checksums are not permitted */ - cksum = htons(y); if (sp->hdr.cksum != cksum) { *_abort_code = RXKADSEALEDINCON; _leave(" = -EPROTO [csum failed]"); @@ -567,10 +589,11 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, static int rxkad_issue_challenge(struct rxrpc_connection *conn) { struct rxkad_challenge challenge; - struct rxrpc_header hdr; + struct rxrpc_wire_header whdr; struct msghdr msg; struct kvec iov[2]; size_t len; + u32 serial; int ret; _enter("{%d,%x}", conn->debug_id, key_serial(conn->key)); @@ -592,26 +615,27 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn) msg.msg_controllen = 0; msg.msg_flags = 0; - hdr.epoch = conn->epoch; - hdr.cid = conn->cid; - hdr.callNumber = 0; - hdr.seq = 0; - hdr.type = RXRPC_PACKET_TYPE_CHALLENGE; - hdr.flags = conn->out_clientflag; - hdr.userStatus = 0; - hdr.securityIndex = conn->security_ix; - hdr._rsvd = 0; - hdr.serviceId = conn->service_id; - - iov[0].iov_base = &hdr; - iov[0].iov_len = sizeof(hdr); + whdr.epoch = htonl(conn->epoch); + whdr.cid = htonl(conn->cid); + whdr.callNumber = 0; + whdr.seq = 0; + whdr.type = RXRPC_PACKET_TYPE_CHALLENGE; + whdr.flags = conn->out_clientflag; + whdr.userStatus = 0; + whdr.securityIndex = conn->security_ix; + whdr._rsvd = 0; + whdr.serviceId = htons(conn->service_id); + + iov[0].iov_base = &whdr; + iov[0].iov_len = sizeof(whdr); iov[1].iov_base = &challenge; iov[1].iov_len = sizeof(challenge); len = iov[0].iov_len + iov[1].iov_len; - hdr.serial = htonl(atomic_inc_return(&conn->serial)); - _proto("Tx CHALLENGE %%%u", ntohl(hdr.serial)); + serial = atomic_inc_return(&conn->serial); + whdr.serial = htonl(serial); + _proto("Tx CHALLENGE %%%u", serial); ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len); if (ret < 0) { @@ -627,13 +651,15 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn) * send a Kerberos security response */ static int rxkad_send_response(struct rxrpc_connection *conn, - struct rxrpc_header *hdr, + struct rxrpc_host_header *hdr, struct rxkad_response *resp, const struct rxkad_key *s2) { + struct rxrpc_wire_header whdr; struct msghdr msg; struct kvec iov[3]; size_t len; + u32 serial; int ret; _enter(""); @@ -644,24 +670,26 @@ static int rxkad_send_response(struct rxrpc_connection *conn, msg.msg_controllen = 0; msg.msg_flags = 0; - hdr->epoch = conn->epoch; - hdr->seq = 0; - hdr->type = RXRPC_PACKET_TYPE_RESPONSE; - hdr->flags = conn->out_clientflag; - hdr->userStatus = 0; - hdr->_rsvd = 0; + memset(&whdr, 0, sizeof(whdr)); + whdr.epoch = htonl(hdr->epoch); + whdr.cid = htonl(hdr->cid); + whdr.type = RXRPC_PACKET_TYPE_RESPONSE; + whdr.flags = conn->out_clientflag; + whdr.securityIndex = hdr->securityIndex; + whdr.serviceId = htons(hdr->serviceId); - iov[0].iov_base = hdr; - iov[0].iov_len = sizeof(*hdr); + iov[0].iov_base = &whdr; + iov[0].iov_len = sizeof(whdr); iov[1].iov_base = resp; iov[1].iov_len = sizeof(*resp); - iov[2].iov_base = (void *) s2->ticket; + iov[2].iov_base = (void *)s2->ticket; iov[2].iov_len = s2->ticket_len; len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; - hdr->serial = htonl(atomic_inc_return(&conn->serial)); - _proto("Tx RESPONSE %%%u", ntohl(hdr->serial)); + serial = atomic_inc_return(&conn->serial); + whdr.serial = htonl(serial); + _proto("Tx RESPONSE %%%u", serial); ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 3, len); if (ret < 0) { @@ -718,18 +746,21 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, struct rxkad_response *resp, const struct rxkad_key *s2) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv)); - desc.tfm = conn->cipher; - desc.info = iv.x; - desc.flags = 0; rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); - crypto_blkcipher_encrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); + + skcipher_request_set_tfm(req, conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } /* @@ -770,7 +801,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, min_level = ntohl(challenge.min_level); _proto("Rx CHALLENGE %%%u { v=%u n=%u ml=%u }", - ntohl(sp->hdr.serial), version, nonce, min_level); + sp->hdr.serial, version, nonce, min_level); abort_code = RXKADINCONSISTENCY; if (version != RXKAD_VERSION) @@ -785,22 +816,23 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, /* build the response packet */ memset(&resp, 0, sizeof(resp)); - resp.version = RXKAD_VERSION; - resp.encrypted.epoch = conn->epoch; - resp.encrypted.cid = conn->cid; - resp.encrypted.securityIndex = htonl(conn->security_ix); + resp.version = htonl(RXKAD_VERSION); + resp.encrypted.epoch = htonl(conn->epoch); + resp.encrypted.cid = htonl(conn->cid); + resp.encrypted.securityIndex = htonl(conn->security_ix); + resp.encrypted.inc_nonce = htonl(nonce + 1); + resp.encrypted.level = htonl(conn->security_level); + resp.kvno = htonl(token->kad->kvno); + resp.ticket_len = htonl(token->kad->ticket_len); + resp.encrypted.call_id[0] = - (conn->channels[0] ? conn->channels[0]->call_id : 0); + htonl(conn->channels[0] ? conn->channels[0]->call_id : 0); resp.encrypted.call_id[1] = - (conn->channels[1] ? conn->channels[1]->call_id : 0); + htonl(conn->channels[1] ? conn->channels[1]->call_id : 0); resp.encrypted.call_id[2] = - (conn->channels[2] ? conn->channels[2]->call_id : 0); + htonl(conn->channels[2] ? conn->channels[2]->call_id : 0); resp.encrypted.call_id[3] = - (conn->channels[3] ? conn->channels[3]->call_id : 0); - resp.encrypted.inc_nonce = htonl(nonce + 1); - resp.encrypted.level = htonl(conn->security_level); - resp.kvno = htonl(token->kad->kvno); - resp.ticket_len = htonl(token->kad->ticket_len); + htonl(conn->channels[3] ? conn->channels[3]->call_id : 0); /* calculate the response checksum and then do the encryption */ rxkad_calc_response_checksum(&resp); @@ -822,7 +854,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, time_t *_expiry, u32 *_abort_code) { - struct blkcipher_desc desc; + struct skcipher_request *req; struct rxrpc_crypt iv, key; struct scatterlist sg[1]; struct in_addr addr; @@ -853,12 +885,21 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv)); - desc.tfm = conn->server_key->payload.data[0]; - desc.info = iv.x; - desc.flags = 0; + req = skcipher_request_alloc(conn->server_key->payload.data[0], + GFP_NOFS); + if (!req) { + *_abort_code = RXKADNOAUTH; + ret = -ENOMEM; + goto error; + } sg_init_one(&sg[0], ticket, ticket_len); - crypto_blkcipher_decrypt_iv(&desc, sg, sg, ticket_len); + + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_free(req); p = ticket; end = p + ticket_len; @@ -966,7 +1007,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, struct rxkad_response *resp, const struct rxrpc_crypt *session_key) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); struct scatterlist sg[2]; struct rxrpc_crypt iv; @@ -976,17 +1017,21 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, ASSERT(rxkad_ci != NULL); mutex_lock(&rxkad_ci_mutex); - if (crypto_blkcipher_setkey(rxkad_ci, session_key->x, - sizeof(*session_key)) < 0) + if (crypto_skcipher_setkey(rxkad_ci, session_key->x, + sizeof(*session_key)) < 0) BUG(); memcpy(&iv, session_key, sizeof(iv)); - desc.tfm = rxkad_ci; - desc.info = iv.x; - desc.flags = 0; rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); - crypto_blkcipher_decrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); + + skcipher_request_set_tfm(req, rxkad_ci); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + mutex_unlock(&rxkad_ci_mutex); _leave(""); @@ -1022,7 +1067,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, kvno = ntohl(response.kvno); sp = rxrpc_skb(skb); _proto("Rx RESPONSE %%%u { v=%u kv=%u tl=%u }", - ntohl(sp->hdr.serial), version, kvno, ticket_len); + sp->hdr.serial, version, kvno, ticket_len); abort_code = RXKADINCONSISTENCY; if (version != RXKAD_VERSION) @@ -1058,9 +1103,9 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, rxkad_decrypt_response(conn, &response, &session_key); abort_code = RXKADSEALEDINCON; - if (response.encrypted.epoch != conn->epoch) + if (ntohl(response.encrypted.epoch) != conn->epoch) goto protocol_error_free; - if (response.encrypted.cid != conn->cid) + if (ntohl(response.encrypted.cid) != conn->cid) goto protocol_error_free; if (ntohl(response.encrypted.securityIndex) != conn->security_ix) goto protocol_error_free; @@ -1077,7 +1122,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, goto protocol_error_free; abort_code = RXKADOUTOFSEQUENCE; - if (response.encrypted.inc_nonce != htonl(conn->security_nonce + 1)) + if (ntohl(response.encrypted.inc_nonce) != conn->security_nonce + 1) goto protocol_error_free; abort_code = RXKADLEVELFAIL; @@ -1115,7 +1160,7 @@ static void rxkad_clear(struct rxrpc_connection *conn) _enter(""); if (conn->cipher) - crypto_free_blkcipher(conn->cipher); + crypto_free_skcipher(conn->cipher); } /* @@ -1141,7 +1186,7 @@ static __init int rxkad_init(void) /* pin the cipher we need so that the crypto layer doesn't invoke * keventd to go get it */ - rxkad_ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); + rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(rxkad_ci)) return PTR_ERR(rxkad_ci); @@ -1155,7 +1200,7 @@ static __exit void rxkad_exit(void) _enter(""); rxrpc_unregister_security(&rxkad); - crypto_free_blkcipher(rxkad_ci); + crypto_free_skcipher(rxkad_ci); } module_exit(rxkad_exit); |