diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 18 | ||||
-rw-r--r-- | src/cookie.c | 65 | ||||
-rw-r--r-- | src/cookie.h | 3 | ||||
-rw-r--r-- | src/crypto/chacha20poly1305.c | 110 | ||||
-rw-r--r-- | src/crypto/chacha20poly1305.h | 11 | ||||
-rw-r--r-- | src/messages.h | 4 | ||||
-rw-r--r-- | src/peer.c | 1 | ||||
-rw-r--r-- | src/selftest/chacha20poly1305.h | 35 |
8 files changed, 204 insertions, 43 deletions
diff --git a/src/config.c b/src/config.c index 741cace..c061b2d 100644 --- a/src/config.c +++ b/src/config.c @@ -116,6 +116,7 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device) size_t i, offset; struct wgdevice in_device; void __user *user_peer; + bool modified_static_identity = false; BUILD_BUG_ON(WG_KEY_LEN != NOISE_PUBLIC_KEY_LEN); BUILD_BUG_ON(WG_KEY_LEN != NOISE_SYMMETRIC_KEY_LEN); @@ -136,15 +137,24 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device) if (in_device.replace_peer_list) peer_remove_all(wg); - if (in_device.remove_private_key) + if (in_device.remove_private_key) { noise_set_static_identity_private_key(&wg->static_identity, NULL); - else if (memcmp(zeros, in_device.private_key, WG_KEY_LEN)) + modified_static_identity = true; + } else if (memcmp(zeros, in_device.private_key, WG_KEY_LEN)) { noise_set_static_identity_private_key(&wg->static_identity, in_device.private_key); + modified_static_identity = true; + } - if (in_device.remove_preshared_key) + if (in_device.remove_preshared_key) { noise_set_static_identity_preshared_key(&wg->static_identity, NULL); - else if (memcmp(zeros, in_device.preshared_key, WG_KEY_LEN)) + modified_static_identity = true; + } else if (memcmp(zeros, in_device.preshared_key, WG_KEY_LEN)) { noise_set_static_identity_preshared_key(&wg->static_identity, in_device.preshared_key); + modified_static_identity = true; + } + + if (modified_static_identity) + cookie_checker_precompute_keys(&wg->cookie_checker, NULL); for (i = 0, offset = 0, user_peer = user_device + sizeof(struct wgdevice); i < in_device.num_peers; ++i, user_peer += offset) { ret = set_peer(wg, user_peer, &offset); diff --git a/src/cookie.c b/src/cookie.c index a2d1b22..b0f1284 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -23,6 +23,31 @@ int cookie_checker_init(struct cookie_checker *checker, struct wireguard_device return 0; } +static int precompute_peer_key(struct wireguard_peer *peer, void *psk) +{ + blake2s(peer->latest_cookie.cookie_decryption_key, peer->handshake.remote_static, psk, NOISE_SYMMETRIC_KEY_LEN, NOISE_PUBLIC_KEY_LEN, psk ? NOISE_SYMMETRIC_KEY_LEN : 0); + return 0; +} + +void cookie_checker_precompute_keys(struct cookie_checker *checker, struct wireguard_peer *peer) +{ + down_read(&checker->device->static_identity.lock); + if (unlikely(checker->device->static_identity.has_identity)) { + memset(checker->cookie_encryption_key, 0, NOISE_SYMMETRIC_KEY_LEN); + goto out; + } + + if (peer) + precompute_peer_key(peer, checker->device->static_identity.has_psk ? checker->device->static_identity.preshared_key : NULL); + else { + blake2s(checker->cookie_encryption_key, checker->device->static_identity.static_public, checker->device->static_identity.preshared_key, NOISE_SYMMETRIC_KEY_LEN, NOISE_PUBLIC_KEY_LEN, checker->device->static_identity.has_psk ? NOISE_SYMMETRIC_KEY_LEN : 0); + peer_for_each_unlocked(checker->device, precompute_peer_key, checker->device->static_identity.has_psk ? checker->device->static_identity.preshared_key : NULL); + } + +out: + up_read(&checker->device->static_identity.lock); +} + void cookie_checker_uninit(struct cookie_checker *checker) { ratelimiter_uninit(&checker->ratelimiter); @@ -159,32 +184,16 @@ void cookie_add_mac_to_packet(void *message, size_t len, struct wireguard_peer * void cookie_message_create(struct message_handshake_cookie *dst, struct sk_buff *skb, void *data_start, size_t data_len, __le32 index, struct cookie_checker *checker) { struct message_macs *macs = (struct message_macs *)((u8 *)data_start + data_len - sizeof(struct message_macs)); - struct blake2s_state state; u8 key[NOISE_SYMMETRIC_KEY_LEN]; u8 cookie[COOKIE_LEN]; dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE); dst->receiver_index = index; - get_random_bytes(dst->salt, COOKIE_SALT_LEN); - blake2s(dst->salt, dst->salt, NULL, COOKIE_SALT_LEN, COOKIE_SALT_LEN, 0); /* Avoid directly transmitting RNG output. */ - - down_read(&checker->device->static_identity.lock); - if (unlikely(!checker->device->static_identity.has_identity)) { - memset(dst, 0, sizeof(struct message_handshake_cookie)); - up_read(&checker->device->static_identity.lock); - return; - } - if (checker->device->static_identity.has_psk) - blake2s_init_key(&state, NOISE_SYMMETRIC_KEY_LEN, checker->device->static_identity.preshared_key, NOISE_SYMMETRIC_KEY_LEN); - else - blake2s_init(&state, NOISE_SYMMETRIC_KEY_LEN); - blake2s_update(&state, checker->device->static_identity.static_public, NOISE_PUBLIC_KEY_LEN); - up_read(&checker->device->static_identity.lock); - blake2s_update(&state, dst->salt, COOKIE_SALT_LEN); - blake2s_final(&state, key, NOISE_SYMMETRIC_KEY_LEN); + get_random_bytes(dst->nonce, COOKIE_NONCE_LEN); + blake2s(dst->nonce, dst->nonce, NULL, COOKIE_NONCE_LEN, COOKIE_NONCE_LEN, 0); /* Avoid directly transmitting RNG output. */ make_cookie(cookie, skb, checker); - chacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN, macs->mac1, COOKIE_LEN, 0, key); + xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN, macs->mac1, COOKIE_LEN, dst->nonce, checker->cookie_encryption_key); memzero_explicit(key, NOISE_HASH_LEN); memzero_explicit(cookie, COOKIE_LEN); @@ -192,7 +201,6 @@ void cookie_message_create(struct message_handshake_cookie *dst, struct sk_buff void cookie_message_consume(struct message_handshake_cookie *src, struct wireguard_device *wg) { - struct blake2s_state state; u8 key[NOISE_SYMMETRIC_KEY_LEN]; u8 cookie[COOKIE_LEN]; struct index_hashtable_entry *entry; @@ -208,23 +216,8 @@ void cookie_message_consume(struct message_handshake_cookie *src, struct wiregua } up_read(&entry->peer->latest_cookie.lock); - down_read(&wg->static_identity.lock); - if (unlikely(!wg->static_identity.has_identity)) { - up_read(&wg->static_identity.lock); - goto out; - } - if (wg->static_identity.has_psk) - blake2s_init_key(&state, NOISE_SYMMETRIC_KEY_LEN, wg->static_identity.preshared_key, NOISE_SYMMETRIC_KEY_LEN); - else - blake2s_init(&state, NOISE_SYMMETRIC_KEY_LEN); - up_read(&wg->static_identity.lock); - - blake2s_update(&state, entry->peer->handshake.remote_static, NOISE_PUBLIC_KEY_LEN); - blake2s_update(&state, src->salt, COOKIE_SALT_LEN); - blake2s_final(&state, key, NOISE_SYMMETRIC_KEY_LEN); - down_write(&entry->peer->latest_cookie.lock); - if (chacha20poly1305_decrypt(cookie, src->encrypted_cookie, sizeof(src->encrypted_cookie), entry->peer->latest_cookie.last_mac1_sent, COOKIE_LEN, 0, key)) { + if (xchacha20poly1305_decrypt(cookie, src->encrypted_cookie, sizeof(src->encrypted_cookie), entry->peer->latest_cookie.last_mac1_sent, COOKIE_LEN, src->nonce, entry->peer->latest_cookie.cookie_decryption_key)) { memcpy(entry->peer->latest_cookie.cookie, cookie, COOKIE_LEN); entry->peer->latest_cookie.birthdate = get_jiffies_64(); entry->peer->latest_cookie.is_valid = true; diff --git a/src/cookie.h b/src/cookie.h index 4ea20e1..13c646d 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -13,6 +13,7 @@ struct sk_buff; struct cookie_checker { u8 secret[NOISE_HASH_LEN]; + u8 cookie_encryption_key[NOISE_SYMMETRIC_KEY_LEN]; u64 secret_birthdate; struct rw_semaphore secret_lock; struct ratelimiter ratelimiter; @@ -25,6 +26,7 @@ struct cookie { u8 cookie[COOKIE_LEN]; bool have_sent_mac1; u8 last_mac1_sent[COOKIE_LEN]; + u8 cookie_decryption_key[NOISE_SYMMETRIC_KEY_LEN]; struct rw_semaphore lock; }; @@ -37,6 +39,7 @@ enum cookie_mac_state { int cookie_checker_init(struct cookie_checker *checker, struct wireguard_device *wg); void cookie_checker_uninit(struct cookie_checker *checker); +void cookie_checker_precompute_keys(struct cookie_checker *checker, struct wireguard_peer *peer); void cookie_init(struct cookie *cookie); enum cookie_mac_state cookie_validate_packet(struct cookie_checker *checker, struct sk_buff *skb, void *data_start, size_t data_len, bool check_cookie); diff --git a/src/crypto/chacha20poly1305.c b/src/crypto/chacha20poly1305.c index a7421d6..3b860bf 100644 --- a/src/crypto/chacha20poly1305.c +++ b/src/crypto/chacha20poly1305.c @@ -52,6 +52,11 @@ static inline u32 le32_to_cpuvp(const void *p) return le32_to_cpup(p); } +static inline u64 le64_to_cpuvp(const void *p) +{ + return le64_to_cpup(p); +} + static inline u32 rotl32(u32 v, u8 n) { return (v << n) | (v >> (sizeof(v) * 8 - n)); @@ -133,9 +138,85 @@ static void chacha20_generic_block(struct chacha20_ctx *ctx, void *stream) ctx->state[12]++; } +static const char constant[16] = "expand 32-byte k"; + +static void hchacha20(u8 derived_key[CHACHA20POLY1305_KEYLEN], const u8 nonce[16], const u8 key[CHACHA20POLY1305_KEYLEN]) +{ + u32 x[CHACHA20_BLOCK_SIZE / sizeof(u32)]; + __le32 *out = (__force __le32 *)derived_key; + int i; + + x[0] = le32_to_cpuvp(constant + 0); + x[1] = le32_to_cpuvp(constant + 4); + x[2] = le32_to_cpuvp(constant + 8); + x[3] = le32_to_cpuvp(constant + 12); + x[4] = le32_to_cpuvp(key + 0); + x[5] = le32_to_cpuvp(key + 4); + x[6] = le32_to_cpuvp(key + 8); + x[7] = le32_to_cpuvp(key + 12); + x[8] = le32_to_cpuvp(key + 16); + x[9] = le32_to_cpuvp(key + 20); + x[10] = le32_to_cpuvp(key + 24); + x[11] = le32_to_cpuvp(key + 28); + x[12] = le32_to_cpuvp(nonce + 0); + x[13] = le32_to_cpuvp(nonce + 4); + x[14] = le32_to_cpuvp(nonce + 8); + x[15] = le32_to_cpuvp(nonce + 12); + + for (i = 0; i < 20; i += 2) { + x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 16); + x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16); + x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16); + x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16); + + x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); + x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); + x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); + x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); + + x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8); + x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8); + x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8); + x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8); + + x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); + x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); + x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); + x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); + + x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16); + x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16); + x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16); + x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16); + + x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); + x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); + x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); + x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); + + x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8); + x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8); + x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8); + x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8); + + x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); + x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); + x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); + x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7); + } + + out[0] = cpu_to_le32(x[0]); + out[1] = cpu_to_le32(x[1]); + out[2] = cpu_to_le32(x[2]); + out[3] = cpu_to_le32(x[3]); + out[4] = cpu_to_le32(x[12]); + out[5] = cpu_to_le32(x[13]); + out[6] = cpu_to_le32(x[14]); + out[7] = cpu_to_le32(x[15]); +} + static void chacha20_keysetup(struct chacha20_ctx *ctx, const u8 key[CHACHA20_KEY_SIZE], const u8 nonce[sizeof(u64)]) { - static const char constant[16] = "expand 32-byte k"; ctx->state[0] = le32_to_cpuvp(constant + 0); ctx->state[1] = le32_to_cpuvp(constant + 4); ctx->state[2] = le32_to_cpuvp(constant + 8); @@ -700,4 +781,31 @@ bool chacha20poly1305_decrypt_sg(struct scatterlist *dst, struct scatterlist *sr return !ret; } + +bool xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, + const u8 *ad, const size_t ad_len, + const u8 nonce[XCHACHA20POLY1305_NONCELEN], + const u8 key[CHACHA20POLY1305_KEYLEN]) +{ + u8 derived_key[CHACHA20POLY1305_KEYLEN]; + bool ret; + hchacha20(derived_key, nonce, key); + ret = chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, le64_to_cpuvp(nonce + 16), derived_key); + memzero_explicit(derived_key, CHACHA20POLY1305_KEYLEN); + return ret; +} + +bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, + const u8 *ad, const size_t ad_len, + const u8 nonce[XCHACHA20POLY1305_NONCELEN], + const u8 key[CHACHA20POLY1305_KEYLEN]) +{ + u8 derived_key[CHACHA20POLY1305_KEYLEN]; + bool ret; + hchacha20(derived_key, nonce, key); + ret = chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, le64_to_cpuvp(nonce + 16), derived_key); + memzero_explicit(derived_key, CHACHA20POLY1305_KEYLEN); + return ret; +} + #include "../selftest/chacha20poly1305.h" diff --git a/src/crypto/chacha20poly1305.h b/src/crypto/chacha20poly1305.h index 2ae9ff5..068995a 100644 --- a/src/crypto/chacha20poly1305.h +++ b/src/crypto/chacha20poly1305.h @@ -8,6 +8,7 @@ struct scatterlist; enum chacha20poly1305_lengths { + XCHACHA20POLY1305_NONCELEN = 24, CHACHA20POLY1305_KEYLEN = 32, CHACHA20POLY1305_AUTHTAGLEN = 16 }; @@ -31,6 +32,16 @@ bool chacha20poly1305_decrypt_sg(struct scatterlist *dst, struct scatterlist *sr const u8 *ad, const size_t ad_len, const u64 nonce, const u8 key[CHACHA20POLY1305_KEYLEN]); +bool xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, + const u8 *ad, const size_t ad_len, + const u8 nonce[XCHACHA20POLY1305_NONCELEN], + const u8 key[CHACHA20POLY1305_KEYLEN]); + +bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, + const u8 *ad, const size_t ad_len, + const u8 nonce[XCHACHA20POLY1305_NONCELEN], + const u8 key[CHACHA20POLY1305_KEYLEN]); + #ifdef CONFIG_X86_64 #include <linux/version.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) diff --git a/src/messages.h b/src/messages.h index f5362ac..8fa1c95 100644 --- a/src/messages.h +++ b/src/messages.h @@ -27,7 +27,7 @@ enum noise_lengths { enum cookie_values { COOKIE_SECRET_MAX_AGE = 2 * 60 * HZ, COOKIE_SECRET_LATENCY = 5 * HZ, - COOKIE_SALT_LEN = 32, + COOKIE_NONCE_LEN = XCHACHA20POLY1305_NONCELEN, COOKIE_LEN = 16 }; @@ -99,7 +99,7 @@ struct message_handshake_response { struct message_handshake_cookie { struct message_header header; __le32 receiver_index; - u8 salt[COOKIE_SALT_LEN]; + u8 nonce[COOKIE_NONCE_LEN]; u8 encrypted_cookie[noise_encrypted_len(COOKIE_LEN)]; }; @@ -35,6 +35,7 @@ struct wireguard_peer *peer_create(struct wireguard_device *wg, const u8 public_ peer->device = wg; cookie_init(&peer->latest_cookie); noise_handshake_init(&peer->handshake, &wg->static_identity, public_key, peer); + cookie_checker_precompute_keys(&wg->cookie_checker, peer); mutex_init(&peer->keypairs.keypair_update_lock); INIT_WORK(&peer->transmit_handshake_work, packet_send_queued_handshakes); rwlock_init(&peer->endpoint_lock); diff --git a/src/selftest/chacha20poly1305.h b/src/selftest/chacha20poly1305.h index 455d58b..1d79299 100644 --- a/src/selftest/chacha20poly1305.h +++ b/src/selftest/chacha20poly1305.h @@ -25,6 +25,25 @@ static const struct chacha20poly1305_testvec chacha20poly1305_dec_vectors[] = { .result = "\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x72\x65\x20\x64\x72\x61\x66\x74\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x76\x61\x6c\x69\x64\x20\x66\x6f\x72\x20\x61\x20\x6d\x61\x78\x69\x6d\x75\x6d\x20\x6f\x66\x20\x73\x69\x78\x20\x6d\x6f\x6e\x74\x68\x73\x20\x61\x6e\x64\x20\x6d\x61\x79\x20\x62\x65\x20\x75\x70\x64\x61\x74\x65\x64\x2c\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x2c\x20\x6f\x72\x20\x6f\x62\x73\x6f\x6c\x65\x74\x65\x64\x20\x62\x79\x20\x6f\x74\x68\x65\x72\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x2e\x20\x49\x74\x20\x69\x73\x20\x69\x6e\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x74\x6f\x20\x75\x73\x65\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x73\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x6d\x61\x74\x65\x72\x69\x61\x6c\x20\x6f\x72\x20\x74\x6f\x20\x63\x69\x74\x65\x20\x74\x68\x65\x6d\x20\x6f\x74\x68\x65\x72\x20\x74\x68\x61\x6e\x20\x61\x73\x20\x2f\xe2\x80\x9c\x77\x6f\x72\x6b\x20\x69\x6e\x20\x70\x72\x6f\x67\x72\x65\x73\x73\x2e\x2f\xe2\x80\x9d" } }; +static const struct chacha20poly1305_testvec xchacha20poly1305_enc_vectors[] = { { + .key = "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0", + .nonce = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17", + .assoc = "\xf3\x33\x88\x86\x00\x00\x00\x00\x00\x00\x4e\x91", + .alen = 12, + .input = "\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x72\x65\x20\x64\x72\x61\x66\x74\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x76\x61\x6c\x69\x64\x20\x66\x6f\x72\x20\x61\x20\x6d\x61\x78\x69\x6d\x75\x6d\x20\x6f\x66\x20\x73\x69\x78\x20\x6d\x6f\x6e\x74\x68\x73\x20\x61\x6e\x64\x20\x6d\x61\x79\x20\x62\x65\x20\x75\x70\x64\x61\x74\x65\x64\x2c\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x2c\x20\x6f\x72\x20\x6f\x62\x73\x6f\x6c\x65\x74\x65\x64\x20\x62\x79\x20\x6f\x74\x68\x65\x72\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x2e\x20\x49\x74\x20\x69\x73\x20\x69\x6e\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x74\x6f\x20\x75\x73\x65\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x73\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x6d\x61\x74\x65\x72\x69\x61\x6c\x20\x6f\x72\x20\x74\x6f\x20\x63\x69\x74\x65\x20\x74\x68\x65\x6d\x20\x6f\x74\x68\x65\x72\x20\x74\x68\x61\x6e\x20\x61\x73\x20\x2f\xe2\x80\x9c\x77\x6f\x72\x6b\x20\x69\x6e\x20\x70\x72\x6f\x67\x72\x65\x73\x73\x2e\x2f\xe2\x80\x9d", + .ilen = 265, + .result = "\x1a\x6e\x3a\xd9\xfd\x41\x3f\x77\x54\x72\x0a\x70\x9a\xa0\x29\x92\x2e\xed\x93\xcf\x0f\x71\x88\x18\x7a\x9d\x2d\x24\xe0\xf5\xea\x3d\x55\x64\xd7\xad\x2a\x1a\x1f\x7e\x86\x6d\xb0\xce\x80\x41\x72\x86\x26\xee\x84\xd7\xef\x82\x9e\xe2\x60\x9d\x5a\xfc\xf0\xe4\x19\x85\xea\x09\xc6\xfb\xb3\xa9\x50\x09\xec\x5e\x11\x90\xa1\xc5\x4e\x49\xef\x50\xd8\x8f\xe0\x78\xd7\xfd\xb9\x3b\xc9\xf2\x91\xc8\x25\xc8\xa7\x63\x60\xce\x10\xcd\xc6\x7f\xf8\x16\xf8\xe1\x0a\xd9\xde\x79\x50\x33\xf2\x16\x0f\x17\xba\xb8\x5d\xd8\xdf\x4e\x51\xa8\x39\xd0\x85\xca\x46\x6a\x10\xa7\xa3\x88\xef\x79\xb9\xf8\x24\xf3\xe0\x71\x7b\x76\x28\x46\x3a\x3a\x1b\x91\xb6\xd4\x3e\x23\xe5\x44\x15\xbf\x60\x43\x9d\xa4\xbb\xd5\x5f\x89\xeb\xef\x8e\xfd\xdd\xb4\x0d\x46\xf0\x69\x23\x63\xae\x94\xf5\x5e\xa5\xad\x13\x1c\x41\x76\xe6\x90\xd6\x6d\xa2\x8f\x97\x4c\xa8\x0b\xcf\x8d\x43\x2b\x9c\x9b\xc5\x58\xa5\xb6\x95\x9a\xbf\x81\xc6\x54\xc9\x66\x0c\xe5\x4f\x6a\x53\xa1\xe5\x0c\xba\x31\xde\x34\x64\x73\x8a\x3b\xbd\x92\x01\xdb\x71\x69\xf3\x58\x99\xbc\xd1\xcb\x4a\x05\xe2\x58\x9c\x25\x17\xcd\xdc\x83\xb7\xff\xfb\x09\x61\xad\xbf\x13\x5b\x5e\xed\x46\x82\x6f\x22\xd8\x93\xa6\x85\x5b\x40\x39\x5c\xc5\x9c" +} }; +static const struct chacha20poly1305_testvec xchacha20poly1305_dec_vectors[] = { { + .key = "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0", + .nonce = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17", + .assoc = "\xf3\x33\x88\x86\x00\x00\x00\x00\x00\x00\x4e\x91", + .alen = 12, + .input = "\x1a\x6e\x3a\xd9\xfd\x41\x3f\x77\x54\x72\x0a\x70\x9a\xa0\x29\x92\x2e\xed\x93\xcf\x0f\x71\x88\x18\x7a\x9d\x2d\x24\xe0\xf5\xea\x3d\x55\x64\xd7\xad\x2a\x1a\x1f\x7e\x86\x6d\xb0\xce\x80\x41\x72\x86\x26\xee\x84\xd7\xef\x82\x9e\xe2\x60\x9d\x5a\xfc\xf0\xe4\x19\x85\xea\x09\xc6\xfb\xb3\xa9\x50\x09\xec\x5e\x11\x90\xa1\xc5\x4e\x49\xef\x50\xd8\x8f\xe0\x78\xd7\xfd\xb9\x3b\xc9\xf2\x91\xc8\x25\xc8\xa7\x63\x60\xce\x10\xcd\xc6\x7f\xf8\x16\xf8\xe1\x0a\xd9\xde\x79\x50\x33\xf2\x16\x0f\x17\xba\xb8\x5d\xd8\xdf\x4e\x51\xa8\x39\xd0\x85\xca\x46\x6a\x10\xa7\xa3\x88\xef\x79\xb9\xf8\x24\xf3\xe0\x71\x7b\x76\x28\x46\x3a\x3a\x1b\x91\xb6\xd4\x3e\x23\xe5\x44\x15\xbf\x60\x43\x9d\xa4\xbb\xd5\x5f\x89\xeb\xef\x8e\xfd\xdd\xb4\x0d\x46\xf0\x69\x23\x63\xae\x94\xf5\x5e\xa5\xad\x13\x1c\x41\x76\xe6\x90\xd6\x6d\xa2\x8f\x97\x4c\xa8\x0b\xcf\x8d\x43\x2b\x9c\x9b\xc5\x58\xa5\xb6\x95\x9a\xbf\x81\xc6\x54\xc9\x66\x0c\xe5\x4f\x6a\x53\xa1\xe5\x0c\xba\x31\xde\x34\x64\x73\x8a\x3b\xbd\x92\x01\xdb\x71\x69\xf3\x58\x99\xbc\xd1\xcb\x4a\x05\xe2\x58\x9c\x25\x17\xcd\xdc\x83\xb7\xff\xfb\x09\x61\xad\xbf\x13\x5b\x5e\xed\x46\x82\x6f\x22\xd8\x93\xa6\x85\x5b\x40\x39\x5c\xc5\x9c", + .ilen = 281, + .result = "\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x72\x65\x20\x64\x72\x61\x66\x74\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x76\x61\x6c\x69\x64\x20\x66\x6f\x72\x20\x61\x20\x6d\x61\x78\x69\x6d\x75\x6d\x20\x6f\x66\x20\x73\x69\x78\x20\x6d\x6f\x6e\x74\x68\x73\x20\x61\x6e\x64\x20\x6d\x61\x79\x20\x62\x65\x20\x75\x70\x64\x61\x74\x65\x64\x2c\x20\x72\x65\x70\x6c\x61\x63\x65\x64\x2c\x20\x6f\x72\x20\x6f\x62\x73\x6f\x6c\x65\x74\x65\x64\x20\x62\x79\x20\x6f\x74\x68\x65\x72\x20\x64\x6f\x63\x75\x6d\x65\x6e\x74\x73\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x2e\x20\x49\x74\x20\x69\x73\x20\x69\x6e\x61\x70\x70\x72\x6f\x70\x72\x69\x61\x74\x65\x20\x74\x6f\x20\x75\x73\x65\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x73\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x6d\x61\x74\x65\x72\x69\x61\x6c\x20\x6f\x72\x20\x74\x6f\x20\x63\x69\x74\x65\x20\x74\x68\x65\x6d\x20\x6f\x74\x68\x65\x72\x20\x74\x68\x61\x6e\x20\x61\x73\x20\x2f\xe2\x80\x9c\x77\x6f\x72\x6b\x20\x69\x6e\x20\x70\x72\x6f\x67\x72\x65\x73\x73\x2e\x2f\xe2\x80\x9d" +} }; + bool chacha20poly1305_selftest(void) { size_t i; @@ -47,6 +66,22 @@ bool chacha20poly1305_selftest(void) success = false; } } + for (i = 0; i < ARRAY_SIZE(xchacha20poly1305_enc_vectors); ++i) { + memset(computed_result, 0, sizeof(computed_result)); + success = xchacha20poly1305_encrypt(computed_result, xchacha20poly1305_enc_vectors[i].input, xchacha20poly1305_enc_vectors[i].ilen, xchacha20poly1305_enc_vectors[i].assoc, xchacha20poly1305_enc_vectors[i].alen, xchacha20poly1305_enc_vectors[i].nonce, xchacha20poly1305_enc_vectors[i].key); + if (memcmp(computed_result, xchacha20poly1305_enc_vectors[i].result, xchacha20poly1305_enc_vectors[i].ilen + POLY1305_MAC_SIZE)) { + pr_info("xchacha20poly1305 encryption self-test %zu: FAIL\n", i + 1); + success = false; + } + } + for (i = 0; i < ARRAY_SIZE(xchacha20poly1305_dec_vectors); ++i) { + memset(computed_result, 0, sizeof(computed_result)); + success = xchacha20poly1305_decrypt(computed_result, xchacha20poly1305_dec_vectors[i].input, xchacha20poly1305_dec_vectors[i].ilen, xchacha20poly1305_dec_vectors[i].assoc, xchacha20poly1305_dec_vectors[i].alen, xchacha20poly1305_dec_vectors[i].nonce, xchacha20poly1305_dec_vectors[i].key); + if (!success || memcmp(computed_result, xchacha20poly1305_dec_vectors[i].result, xchacha20poly1305_dec_vectors[i].ilen - POLY1305_MAC_SIZE)) { + pr_info("xchacha20poly1305 decryption self-test %zu: FAIL\n", i + 1); + success = false; + } + } if (success) pr_info("chacha20poly1305 self-tests: pass\n"); return success; |