Herbert Xu <[EMAIL PROTECTED]> wrote: > Would it be possible to just use the existing scatterlist interface > for now? We can simplify it later when things settle down.
I'll apply the attached patch for now and drop the bypass patch. It's a bit messy, but it does let me use the sg-list interface. Note that it does paste stack space into sg-list elements, which I think should be okay, and it asks the compiler to get it appropriately aligned bits of stack. David diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index b3bd399..1eaf529 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -111,8 +111,11 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) { struct rxrpc_key_payload *payload; struct blkcipher_desc desc; + struct scatterlist sg[2]; struct rxrpc_crypt iv; - __be32 tmpbuf[4]; + struct { + __be32 x[4]; + } tmpbuf __attribute__((aligned(16))); /* must all be in same page */ _enter(""); @@ -126,16 +129,18 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) desc.info = iv.x; desc.flags = 0; - tmpbuf[0] = conn->epoch; - tmpbuf[1] = conn->cid; - tmpbuf[2] = 0; - tmpbuf[3] = htonl(conn->security_ix); + tmpbuf.x[0] = conn->epoch; + tmpbuf.x[1] = conn->cid; + tmpbuf.x[2] = 0; + tmpbuf.x[3] = htonl(conn->security_ix); - crypto_blkcipher_encrypt_kernel_iv(&desc, (void *) tmpbuf, - (void *) tmpbuf, sizeof(tmpbuf)); + memset(sg, 0, sizeof(sg)); + sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); - memcpy(&conn->csum_iv, &tmpbuf[2], sizeof(conn->csum_iv)); - ASSERTCMP(conn->csum_iv.n[0], ==, tmpbuf[2]); + memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv)); + ASSERTCMP(conn->csum_iv.n[0], ==, tmpbuf.x[2]); _leave(""); } @@ -151,10 +156,11 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, struct rxrpc_skb_priv *sp; struct blkcipher_desc desc; struct rxrpc_crypt iv; + struct scatterlist sg[2]; struct { struct rxkad_level1_hdr hdr; __be32 first; /* first four bytes of data and padding */ - } buf; + } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ u16 check; sp = rxrpc_skb(skb); @@ -164,8 +170,8 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, check = ntohl(sp->hdr.seq ^ sp->hdr.callNumber); data_size |= (u32) check << 16; - buf.hdr.data_size = htonl(data_size); - memcpy(&buf.first, sechdr + 4, sizeof(buf.first)); + tmpbuf.hdr.data_size = htonl(data_size); + memcpy(&tmpbuf.first, sechdr + 4, sizeof(tmpbuf.first)); /* start the encryption afresh */ memset(&iv, 0, sizeof(iv)); @@ -173,10 +179,12 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, desc.info = iv.x; desc.flags = 0; - crypto_blkcipher_encrypt_kernel_iv(&desc, (void *) &buf, - (void *) &buf, sizeof(buf)); + memset(sg, 0, sizeof(sg)); + sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); - memcpy(sechdr, &buf, sizeof(buf)); + memcpy(sechdr, &tmpbuf, sizeof(tmpbuf)); _leave(" = 0"); return 0; @@ -191,7 +199,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, void *sechdr) { const struct rxrpc_key_payload *payload; - struct rxkad_level2_hdr rxkhdr; + struct rxkad_level2_hdr rxkhdr + __attribute__((aligned(8))); /* must be all on one page */ struct rxrpc_skb_priv *sp; struct blkcipher_desc desc; struct rxrpc_crypt iv; @@ -217,8 +226,10 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, desc.info = iv.x; desc.flags = 0; - crypto_blkcipher_encrypt_kernel_iv(&desc, (void *) sechdr, - (void *) &rxkhdr, sizeof(rxkhdr)); + memset(sg, 0, sizeof(sg[0]) * 2); + sg_set_buf(&sg[0], sechdr, sizeof(rxkhdr)); + sg_set_buf(&sg[1], &rxkhdr, sizeof(rxkhdr)); + crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(rxkhdr)); /* we want to encrypt the skbuff in-place */ nsg = skb_cow_data(skb, 0, &trailer); @@ -246,7 +257,11 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, struct rxrpc_skb_priv *sp; struct blkcipher_desc desc; struct rxrpc_crypt iv; - __be32 tmpbuf[2], x; + struct scatterlist sg[2]; + struct { + __be32 x[2]; + } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ + __be32 x; int ret; sp = rxrpc_skb(skb); @@ -271,13 +286,15 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, /* calculate the security checksum */ x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); x |= sp->hdr.seq & __constant_cpu_to_be32(0x3fffffff); - tmpbuf[0] = sp->hdr.callNumber; - tmpbuf[1] = x; + tmpbuf.x[0] = sp->hdr.callNumber; + tmpbuf.x[1] = x; - crypto_blkcipher_encrypt_kernel_iv(&desc, (void *) tmpbuf, - (void *) tmpbuf, sizeof(tmpbuf)); + memset(&sg, 0, sizeof(sg)); + sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); - x = ntohl(tmpbuf[1]); + x = ntohl(tmpbuf.x[1]); x = (x >> 16) & 0xffff; if (x == 0) x = 1; /* zero checksums are not permitted */ @@ -468,7 +485,11 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, struct blkcipher_desc desc; struct rxrpc_skb_priv *sp; struct rxrpc_crypt iv; - __be32 tmpbuf[2], x; + struct scatterlist sg[2]; + struct { + __be32 x[2]; + } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ + __be32 x; __be16 cksum; int ret; @@ -496,13 +517,15 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, /* validate the security checksum */ x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); x |= sp->hdr.seq & __constant_cpu_to_be32(0x3fffffff); - tmpbuf[0] = call->call_id; - tmpbuf[1] = x; + tmpbuf.x[0] = call->call_id; + tmpbuf.x[1] = x; - crypto_blkcipher_encrypt_kernel_iv(&desc, (void *) tmpbuf, - (void *) tmpbuf, sizeof(tmpbuf)); + memset(&sg, 0, sizeof(sg)); + sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); - x = ntohl(tmpbuf[1]); + x = ntohl(tmpbuf.x[1]); x = (x >> 16) & 0xffff; if (x == 0) x = 1; /* zero checksums are not permitted */ @@ -661,6 +684,25 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response) } /* + * load a scatterlist with a potentially split-page buffer + */ +static void rxkad_sg_set_buf2(struct scatterlist sg[2], + void *buf, size_t buflen) +{ + + memset(sg, 0, sizeof(sg)); + + sg_set_buf(&sg[0], buf, buflen); + if (sg[0].offset + buflen > PAGE_SIZE) { + /* the buffer was split over two pages */ + sg[0].length = PAGE_SIZE - sg[0].offset; + sg_set_buf(&sg[1], buf + sg[0].length, buflen - sg[0].length); + } + + ASSERTCMP(sg[0].length + sg[1].length, ==, buflen); +} + +/* * encrypt the response packet */ static void rxkad_encrypt_response(struct rxrpc_connection *conn, @@ -669,6 +711,7 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, { struct blkcipher_desc desc; struct rxrpc_crypt iv; + struct scatterlist ssg[2], dsg[2]; /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv)); @@ -676,10 +719,9 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - crypto_blkcipher_encrypt_kernel_iv(&desc, - (void *) &resp->encrypted, - (void *) &resp->encrypted, - sizeof(resp->encrypted)); + rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted)); + memcpy(dsg, ssg, sizeof(dsg)); + crypto_blkcipher_encrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted)); } /* @@ -691,7 +733,8 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, { const struct rxrpc_key_payload *payload; struct rxkad_challenge challenge; - struct rxkad_response resp; + struct rxkad_response resp + __attribute__((aligned(8))); /* must be aligned for crypto */ struct rxrpc_skb_priv *sp; u32 version, nonce, min_level, abort_code; int ret; @@ -773,6 +816,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, { struct blkcipher_desc desc; struct rxrpc_crypt iv, key; + struct scatterlist ssg[1], dsg[1]; struct in_addr addr; unsigned life; time_t issue, now; @@ -797,6 +841,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, } ASSERT(conn->server_key->payload.data != NULL); + ASSERTCMP((unsigned long) ticket & 7UL, ==, 0); memcpy(&iv, &conn->server_key->type_data, sizeof(iv)); @@ -804,7 +849,9 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - crypto_blkcipher_decrypt_kernel_iv(&desc, ticket, ticket, ticket_len); + sg_init_one(&ssg[0], ticket, ticket_len); + memcpy(dsg, ssg, sizeof(dsg)); + crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, ticket_len); p = ticket; end = p + ticket_len; @@ -913,6 +960,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, const struct rxrpc_crypt *session_key) { struct blkcipher_desc desc; + struct scatterlist ssg[2], dsg[2]; struct rxrpc_crypt iv; _enter(",,%08x%08x", @@ -930,10 +978,9 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - crypto_blkcipher_decrypt_kernel_iv(&desc, - (void *) &resp->encrypted, - (void *) &resp->encrypted, - sizeof(resp->encrypted)); + rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted)); + memcpy(dsg, ssg, sizeof(dsg)); + crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted)); mutex_unlock(&rxkad_ci_mutex); _leave(""); @@ -946,7 +993,8 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, struct sk_buff *skb, u32 *_abort_code) { - struct rxkad_response response; + struct rxkad_response response + __attribute__((aligned(8))); /* must be aligned for crypto */ struct rxrpc_skb_priv *sp; struct rxrpc_crypt session_key; time_t expiry; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html