diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-04-03 16:19:44 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-04-04 03:44:35 +0200 |
commit | 0656a29de11c3c9ab2cd3d187c8bfc8507e78aaa (patch) | |
tree | 225f327aa2a2ecf708eb9b3bc1c53c947c074974 /src | |
parent | f7d65b3268ec8f11d0fbf455ce8f7b00b0f79c47 (diff) |
chacha20poly1305: check return values of sgops
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/crypto/chacha20poly1305.c | 24 | ||||
-rw-r--r-- | src/crypto/chacha20poly1305.h | 2 | ||||
-rw-r--r-- | src/data.c | 10 |
3 files changed, 22 insertions, 14 deletions
diff --git a/src/crypto/chacha20poly1305.c b/src/crypto/chacha20poly1305.c index 9cc1305..d0fbe1c 100644 --- a/src/crypto/chacha20poly1305.c +++ b/src/crypto/chacha20poly1305.c @@ -607,13 +607,14 @@ void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, chacha20poly1305_deinit_simd(have_simd); } -void chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *src, const size_t src_len, +bool chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *src, const size_t src_len, const u8 *ad, const size_t ad_len, const u64 nonce, const u8 key[CHACHA20POLY1305_KEYLEN], bool have_simd) { struct poly1305_ctx poly1305_state; struct chacha20_ctx chacha20_state; + int ret = 0; struct blkcipher_walk walk; u8 block0[CHACHA20_BLOCK_SIZE] = { 0 }; u8 mac[POLY1305_MAC_SIZE]; @@ -631,19 +632,21 @@ void chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *sr if (likely(src_len)) { blkcipher_walk_init(&walk, dst, src, src_len); - blkcipher_walk_virt_block(&chacha20_desc, &walk, CHACHA20_BLOCK_SIZE); + ret = blkcipher_walk_virt_block(&chacha20_desc, &walk, CHACHA20_BLOCK_SIZE); while (walk.nbytes >= CHACHA20_BLOCK_SIZE) { size_t chunk_len = rounddown(walk.nbytes, CHACHA20_BLOCK_SIZE); chacha20_crypt(&chacha20_state, walk.dst.virt.addr, walk.src.virt.addr, chunk_len, have_simd); poly1305_update(&poly1305_state, walk.dst.virt.addr, chunk_len, have_simd); - blkcipher_walk_done(&chacha20_desc, &walk, walk.nbytes % CHACHA20_BLOCK_SIZE); + ret = blkcipher_walk_done(&chacha20_desc, &walk, walk.nbytes % CHACHA20_BLOCK_SIZE); } if (walk.nbytes) { chacha20_crypt(&chacha20_state, walk.dst.virt.addr, walk.src.virt.addr, walk.nbytes, have_simd); poly1305_update(&poly1305_state, walk.dst.virt.addr, walk.nbytes, have_simd); - blkcipher_walk_done(&chacha20_desc, &walk, 0); + ret = blkcipher_walk_done(&chacha20_desc, &walk, 0); } } + if (unlikely(ret)) + goto err; poly1305_update(&poly1305_state, pad0, (0x10 - src_len) & 0xf, have_simd); @@ -655,9 +658,11 @@ void chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *sr poly1305_finish(&poly1305_state, mac); scatterwalk_map_and_copy(mac, dst, src_len, sizeof(mac), 1); +err: memzero_explicit(&poly1305_state, sizeof(poly1305_state)); memzero_explicit(&chacha20_state, sizeof(chacha20_state)); memzero_explicit(mac, sizeof(mac)); + return !ret; } bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, @@ -719,7 +724,7 @@ bool chacha20poly1305_decrypt_sg(struct scatterlist *dst, struct scatterlist *sr struct poly1305_ctx poly1305_state; struct chacha20_ctx chacha20_state; struct blkcipher_walk walk; - int ret; + int ret = 0; u8 block0[CHACHA20_BLOCK_SIZE] = { 0 }; u8 read_mac[POLY1305_MAC_SIZE], computed_mac[POLY1305_MAC_SIZE]; size_t dst_len; @@ -744,19 +749,21 @@ bool chacha20poly1305_decrypt_sg(struct scatterlist *dst, struct scatterlist *sr dst_len = src_len - POLY1305_MAC_SIZE; if (likely(dst_len)) { blkcipher_walk_init(&walk, dst, src, dst_len); - blkcipher_walk_virt_block(&chacha20_desc, &walk, CHACHA20_BLOCK_SIZE); + ret = blkcipher_walk_virt_block(&chacha20_desc, &walk, CHACHA20_BLOCK_SIZE); while (walk.nbytes >= CHACHA20_BLOCK_SIZE) { size_t chunk_len = rounddown(walk.nbytes, CHACHA20_BLOCK_SIZE); poly1305_update(&poly1305_state, walk.src.virt.addr, chunk_len, have_simd); chacha20_crypt(&chacha20_state, walk.dst.virt.addr, walk.src.virt.addr, chunk_len, have_simd); - blkcipher_walk_done(&chacha20_desc, &walk, walk.nbytes % CHACHA20_BLOCK_SIZE); + ret = blkcipher_walk_done(&chacha20_desc, &walk, walk.nbytes % CHACHA20_BLOCK_SIZE); } if (walk.nbytes) { poly1305_update(&poly1305_state, walk.src.virt.addr, walk.nbytes, have_simd); chacha20_crypt(&chacha20_state, walk.dst.virt.addr, walk.src.virt.addr, walk.nbytes, have_simd); - blkcipher_walk_done(&chacha20_desc, &walk, 0); + ret = blkcipher_walk_done(&chacha20_desc, &walk, 0); } } + if (unlikely(ret)) + goto err; poly1305_update(&poly1305_state, pad0, (0x10 - dst_len) & 0xf, have_simd); @@ -771,6 +778,7 @@ bool chacha20poly1305_decrypt_sg(struct scatterlist *dst, struct scatterlist *sr scatterwalk_map_and_copy(read_mac, src, dst_len, POLY1305_MAC_SIZE, 0); ret = crypto_memneq(read_mac, computed_mac, POLY1305_MAC_SIZE); +err: memzero_explicit(read_mac, POLY1305_MAC_SIZE); memzero_explicit(computed_mac, POLY1305_MAC_SIZE); memzero_explicit(&chacha20_state, sizeof(chacha20_state)); diff --git a/src/crypto/chacha20poly1305.h b/src/crypto/chacha20poly1305.h index 76b76d2..b881c82 100644 --- a/src/crypto/chacha20poly1305.h +++ b/src/crypto/chacha20poly1305.h @@ -19,7 +19,7 @@ void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, const u8 *ad, const size_t ad_len, const u64 nonce, const u8 key[CHACHA20POLY1305_KEYLEN]); -void chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *src, const size_t src_len, +bool __must_check chacha20poly1305_encrypt_sg(struct scatterlist *dst, struct scatterlist *src, const size_t src_len, const u8 *ad, const size_t ad_len, const u64 nonce, const u8 key[CHACHA20POLY1305_KEYLEN], bool have_simd); @@ -164,10 +164,9 @@ static inline bool skb_encrypt(struct sk_buff *skb, struct noise_keypair *keypai /* Now we can encrypt the scattergather segments */ sg = __builtin_alloca(num_frags * sizeof(struct scatterlist)); /* bounded to 128 */ sg_init_table(sg, num_frags); - skb_to_sgvec(skb, sg, sizeof(struct message_data), noise_encrypted_len(plaintext_len)); - chacha20poly1305_encrypt_sg(sg, sg, plaintext_len, NULL, 0, PACKET_CB(skb)->nonce, keypair->sending.key, have_simd); - - return true; + if (skb_to_sgvec(skb, sg, sizeof(struct message_data), noise_encrypted_len(plaintext_len)) <= 0) + return false; + return chacha20poly1305_encrypt_sg(sg, sg, plaintext_len, NULL, 0, PACKET_CB(skb)->nonce, keypair->sending.key, have_simd); } static inline bool skb_decrypt(struct sk_buff *skb, struct noise_symmetric_key *key) @@ -192,7 +191,8 @@ static inline bool skb_decrypt(struct sk_buff *skb, struct noise_symmetric_key * sg = __builtin_alloca(num_frags * sizeof(struct scatterlist)); /* bounded to 128 */ sg_init_table(sg, num_frags); - skb_to_sgvec(skb, sg, 0, skb->len); + if (skb_to_sgvec(skb, sg, 0, skb->len) <= 0) + return false; if (!chacha20poly1305_decrypt_sg(sg, sg, skb->len, NULL, 0, PACKET_CB(skb)->nonce, key->key)) return false; |