@@ -94,12 +94,16 @@
goto err;
}
- /* Remainder of IV consists of implicit part (unique per session) */
- ASSERT(buf_write(&iv_buffer, ctx->implicit_iv, ctx->implicit_iv_len));
- ASSERT(iv_buffer.len == iv_len);
+ /* Write packet id part of IV to work buffer */
+ ASSERT(buf_write(&work, iv, packet_id_size(false)));
- /* Write explicit part of IV to work buffer */
- ASSERT(buf_write(&work, iv, iv_len - ctx->implicit_iv_len));
+ /* This generates the IV by XORing the implicit part of the IV
+ * with the packet id already written to the iv buffer */
+ for (int i = 0; i < iv_len; i++)
+ {
+ iv[i] = iv[i] ^ ctx->implicit_iv[i];
+ }
+
dmsg(D_PACKET_CONTENT, "ENCRYPT IV: %s", format_hex(iv, iv_len, 0, &gc));
/* Init cipher_ctx with IV. key & keylen are already initialized */
@@ -426,16 +430,21 @@
{
uint8_t iv[OPENVPN_MAX_IV_LENGTH] = { 0 };
const int iv_len = cipher_ctx_iv_length(ctx->cipher);
- const size_t packet_iv_len = iv_len - ctx->implicit_iv_len;
+ const size_t packet_iv_len = packet_id_size(false);
- ASSERT(ctx->implicit_iv_len <= iv_len);
- if (buf->len + ctx->implicit_iv_len < iv_len)
+ if (buf->len < packet_iv_len)
{
CRYPT_ERROR("missing IV info");
}
memcpy(iv, BPTR(buf), packet_iv_len);
- memcpy(iv + packet_iv_len, ctx->implicit_iv, ctx->implicit_iv_len);
+
+ /* This generates the IV by XORing the implicit part of the IV
+ * with the packet id already written to the iv buffer */
+ for (int i = 0; i < iv_len; i++)
+ {
+ iv[i] = iv[i] ^ ctx->implicit_iv[i];
+ }
dmsg(D_PACKET_CONTENT, "DECRYPT IV: %s", format_hex(iv, iv_len, 0, &gc));
@@ -962,7 +971,6 @@
hmac_ctx_free(ctx->hmac);
ctx->hmac = NULL;
}
- ctx->implicit_iv_len = 0;
}
void
@@ -1078,18 +1086,15 @@
cipher_ctx_t *cipher = co->key_ctx_bi.encrypt.cipher;
if (cipher_ctx_mode_aead(cipher))
{
- size_t impl_iv_len = cipher_ctx_iv_length(cipher) - sizeof(packet_id_type);
ASSERT(cipher_ctx_iv_length(cipher) <= OPENVPN_MAX_IV_LENGTH);
ASSERT(cipher_ctx_iv_length(cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
/* Generate dummy implicit IV */
ASSERT(rand_bytes(co->key_ctx_bi.encrypt.implicit_iv,
OPENVPN_MAX_IV_LENGTH));
- co->key_ctx_bi.encrypt.implicit_iv_len = impl_iv_len;
memcpy(co->key_ctx_bi.decrypt.implicit_iv,
co->key_ctx_bi.encrypt.implicit_iv, OPENVPN_MAX_IV_LENGTH);
- co->key_ctx_bi.decrypt.implicit_iv_len = impl_iv_len;
}
}
@@ -163,6 +163,17 @@
{
cipher_ctx_t *cipher; /**< Generic cipher %context. */
hmac_ctx_t *hmac; /**< Generic HMAC %context. */
+ /**
+ * This implicit IV will be always XORed with the packet id that is sent on
+ * the wire to get the IV. For the common AEAD ciphers of AES-GCM and
+ * Chacha20-Poly1305, the length of the IV is 12 bytes (96 bits).
+ *
+ * For non-epoch 32bit packet id AEAD format we set the first 32
+ * bits of implicit_iv to 0.
+ * Xor with the packet id in this case works as concatenation:
+ * after xor the lower 32 bit of the IV are the packet id and
+ * the rest of the IV is from the implicit IV.
+ */
uint8_t implicit_iv[OPENVPN_MAX_IV_LENGTH];
/**< The implicit part of the IV */
size_t implicit_iv_len; /**< The length of implicit_iv */
@@ -1562,10 +1562,11 @@
size_t impl_iv_len = 0;
ASSERT(cipher_ctx_iv_length(ctx->cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
impl_iv_len = cipher_ctx_iv_length(ctx->cipher) - sizeof(packet_id_type);
- ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
+ ASSERT(impl_iv_len + sizeof(packet_id_type) <= OPENVPN_MAX_IV_LENGTH);
ASSERT(impl_iv_len <= key_len);
- memcpy(ctx->implicit_iv, key, impl_iv_len);
- ctx->implicit_iv_len = impl_iv_len;
+ CLEAR(ctx->implicit_iv);
+ /* The first bytes of the IV are filled with the packet id */
+ memcpy(ctx->implicit_iv + sizeof(packet_id_type), key, impl_iv_len);
}
}
@@ -284,18 +284,15 @@
if (cipher_ctx_mode_aead(cipher))
{
- size_t impl_iv_len = cipher_ctx_iv_length(cipher) - sizeof(packet_id_type);
ASSERT(cipher_ctx_iv_length(cipher) <= OPENVPN_MAX_IV_LENGTH);
ASSERT(cipher_ctx_iv_length(cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
/* Generate dummy implicit IV */
ASSERT(rand_bytes(co->key_ctx_bi.encrypt.implicit_iv,
OPENVPN_MAX_IV_LENGTH));
- co->key_ctx_bi.encrypt.implicit_iv_len = impl_iv_len;
memcpy(co->key_ctx_bi.decrypt.implicit_iv,
co->key_ctx_bi.encrypt.implicit_iv, OPENVPN_MAX_IV_LENGTH);
- co->key_ctx_bi.decrypt.implicit_iv_len = impl_iv_len;
}
}