Add cross providers tests
diff --git a/picotlsvs/picotlsvs.sln b/picotlsvs/picotlsvs.sln
index 558b08f..6be9680 100644
--- a/picotlsvs/picotlsvs.sln
+++ b/picotlsvs/picotlsvs.sln
@@ -65,17 +65,6 @@
 		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testfusion", "testfusion\testfusion.vcxproj", "{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}"
-	ProjectSection(ProjectDependencies) = postProject
-		{559AC085-1BEF-450A-A62D-0D370561D596} = {559AC085-1BEF-450A-A62D-0D370561D596}
-		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5} = {499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}
-		{56C264BF-822B-4F29-B512-5B26157CA2EC} = {56C264BF-822B-4F29-B512-5B26157CA2EC}
-		{592127C5-DD8C-47ED-8EBA-026B5848C374} = {592127C5-DD8C-47ED-8EBA-026B5848C374}
-		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB} = {55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}
-		{0A0E7AF2-05C8-488B-867C-D83B776B8BF4} = {0A0E7AF2-05C8-488B-867C-D83B776B8BF4}
-		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
-	EndProjectSection
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x64 = Debug|x64
@@ -166,24 +155,16 @@
 		{7A04A2BF-03BF-4C3A-9E44-A53B0E90036B}.Release|x86.Build.0 = Release|Win32
 		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Debug|x64.ActiveCfg = Debug|x64
 		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Debug|x64.Build.0 = Debug|x64
-		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Debug|x86.ActiveCfg = Debug|Win32
+		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Debug|x86.ActiveCfg = Debug|x64
 		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Release|x64.ActiveCfg = Release|x64
 		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Release|x64.Build.0 = Release|x64
 		{55F22DE6-EAAE-4279-97B7-84FAAB7F29BB}.Release|x86.ActiveCfg = Release|Win32
 		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Debug|x64.ActiveCfg = Debug|x64
 		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Debug|x64.Build.0 = Debug|x64
-		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Debug|x86.ActiveCfg = Debug|Win32
+		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Debug|x86.ActiveCfg = Debug|x64
 		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Release|x64.ActiveCfg = Release|x64
 		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Release|x64.Build.0 = Release|x64
 		{513DC1C9-2CD4-437C-B8EC-168924EB5AAC}.Release|x86.ActiveCfg = Release|Win32
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Debug|x64.ActiveCfg = Debug|x64
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Debug|x64.Build.0 = Debug|x64
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Debug|x86.ActiveCfg = Debug|Win32
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Debug|x86.Build.0 = Debug|Win32
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Release|x64.ActiveCfg = Release|x64
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Release|x64.Build.0 = Release|x64
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Release|x86.ActiveCfg = Release|Win32
-		{893BA0BA-F452-4C6B-8A5B-C6D07E0DFA0E}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/t/fusion.c b/t/fusion.c
index f1cf273..f9c61bb 100644
--- a/t/fusion.c
+++ b/t/fusion.c
@@ -20,13 +20,6 @@
  * IN THE SOFTWARE.
  */
 
-#if defined(_WINDOWS) && !defined(_WINDOWS64)
-#include <stdio.h>
-int main(int argc, char **argv)
-{
-    printf("Fusion is disabled on x86 32 bits builds.\n");
-}
-#else
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
@@ -58,7 +51,7 @@
 
 static void test_loadn(void)
 {
-    uint8_t buf[8192] = { 0 };
+    uint8_t buf[8192] = {0};
 
     for (size_t off = 0; off < 8192 - 15; ++off) {
         uint8_t *src = buf + off;
@@ -73,7 +66,7 @@
     ok(!!"success");
 }
 
-static const uint8_t zero[16384] = { 0 };
+static const uint8_t zero[16384] = {0};
 
 static void test_ecb(void)
 {
@@ -205,17 +198,26 @@
 {
     static const uint8_t key[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
                          aad[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
-                         iv[] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+                         iv[] = {20, 20, 20, 20, 24, 25, 26, 27, 28, 29, 30, 31},
                          plaintext[] =
                              "hello world\nhello world\nhello world\nhello world\nhello world\nhello world\nhello world\n";
+    static const uint8_t expected[] = {0xd3, 0xa8, 0x1d, 0x96, 0x4c, 0x9b, 0x02, 0xd7, 0x9a, 0xb0, 0x41, 0x07, 0x4c, 0x8c, 0xe2,
+                                       0xe0, 0x2e, 0x83, 0x54, 0x52, 0x45, 0xcb, 0xd4, 0x68, 0xc8, 0x43, 0x45, 0xca, 0x91, 0xfb,
+                                       0xa3, 0x7a, 0x67, 0xed, 0xe8, 0xd7, 0x5e, 0xe2, 0x33, 0xd1, 0x3e, 0xbf, 0x50, 0xc2, 0x4b,
+                                       0x86, 0x83, 0x55, 0x11, 0xbb, 0x17, 0x4f, 0xf5, 0x78, 0xb8, 0x65, 0xeb, 0x9a, 0x2b, 0x8f,
+                                       0x77, 0x08, 0xa9, 0x60, 0x17, 0x73, 0xc5, 0x07, 0xf3, 0x04, 0xc9, 0x3f, 0x67, 0x4d, 0x12,
+                                       0xa1, 0x02, 0x93, 0xc2, 0x3c, 0xd3, 0xf8, 0x59, 0x33, 0xd5, 0x01, 0xc3, 0xbb, 0xaa, 0xe6,
+                                       0x3f, 0xbb, 0x23, 0x66, 0x94, 0x26, 0x28, 0x43, 0xa5, 0xfd, 0x2f};
 
     ptls_aead_context_t *aead = ptls_aead_new_direct(&ptls_fusion_aes128gcm, 0, key, iv);
     uint8_t encrypted[sizeof(plaintext) + 16], decrypted[sizeof(plaintext)];
-    uint8_t seq32[4] = {0x11, 0x23, 0x45, 0x67};
+    uint8_t seq32[4] = {0, 1, 2, 3};
     uint8_t seq32_bad[4] = {0x89, 0xab, 0xcd, 0xef};
 
     ptls_aead_xor_iv(aead, seq32, sizeof(seq32));
     ptls_aead_encrypt(aead, encrypted, plaintext, sizeof(plaintext), 0, aad, sizeof(aad));
+    ok(memcmp(expected, encrypted, sizeof(plaintext)) == 0);
+    ok(memcmp(expected + sizeof(plaintext), encrypted + sizeof(plaintext), 16) == 0);
     ok(ptls_aead_decrypt(aead, decrypted, encrypted, sizeof(encrypted), 0, aad, sizeof(aad)) == sizeof(plaintext));
     ok(memcmp(decrypted, plaintext, sizeof(plaintext)) == 0);
     ptls_aead_xor_iv(aead, seq32, sizeof(seq32));
@@ -224,24 +226,30 @@
     ptls_aead_xor_iv(aead, seq32_bad, sizeof(seq32_bad));
     ptls_aead_xor_iv(aead, seq32, sizeof(seq32));
     ok(ptls_aead_decrypt(aead, decrypted, encrypted, sizeof(encrypted), 0, aad, sizeof(aad)) == sizeof(plaintext));
+    ok(memcmp(decrypted, plaintext, sizeof(plaintext)) == 0);
     ptls_aead_free(aead);
 }
 
-static void test_generated(int aes256)
+static void test_generated(int aes256, int iv96)
 {
     ptls_cipher_context_t *rand = ptls_cipher_new(&ptls_minicrypto_aes128ctr, 1, zero);
     ptls_cipher_init(rand, zero);
     int i;
-
-    for (i = 0; i < 10000; ++i) {
+#ifdef _WINDOWS
+    const int nb_runs = 1000;
+#else
+    const int nb_runs = 10000;
+#endif
+    for (i = 0; i < nb_runs; ++i) {
         /* generate input using RNG */
-        uint8_t key[32], iv[12], aadlen, textlen;
+        uint8_t key[32], iv[12], seq32[4], aadlen, textlen;
         uint64_t seq;
         ptls_cipher_encrypt(rand, key, zero, sizeof(key));
         ptls_cipher_encrypt(rand, iv, zero, sizeof(iv));
         ptls_cipher_encrypt(rand, &aadlen, zero, sizeof(aadlen));
         ptls_cipher_encrypt(rand, &textlen, zero, sizeof(textlen));
         ptls_cipher_encrypt(rand, &seq, zero, sizeof(seq));
+        ptls_cipher_encrypt(rand, seq32, zero, sizeof(seq32));
 
         uint8_t aad[256], text[256];
 
@@ -256,6 +264,9 @@
         { /* check using fusion */
             ptls_aead_context_t *fusion =
                 ptls_aead_new_direct(aes256 ? &ptls_fusion_aes256gcm : &ptls_fusion_aes128gcm, 1, key, iv);
+            if (iv96) {
+                ptls_aead_xor_iv(fusion, seq32, sizeof(seq32));
+            }
             ptls_aead_encrypt(fusion, encrypted, text, textlen, seq, aad, aadlen);
             if (ptls_aead_decrypt(fusion, decrypted, encrypted, textlen + 16, seq, aad, aadlen) != textlen)
                 goto Fail;
@@ -269,6 +280,9 @@
         { /* check that the encrypted text can be decrypted by OpenSSL */
             ptls_aead_context_t *mc =
                 ptls_aead_new_direct(aes256 ? &ptls_minicrypto_aes256gcm : &ptls_minicrypto_aes128gcm, 0, key, iv);
+            if (iv96) {
+                ptls_aead_xor_iv(mc, seq32, sizeof(seq32));
+            }
             if (ptls_aead_decrypt(mc, decrypted, encrypted, textlen + 16, seq, aad, aadlen) != textlen)
                 goto Fail;
             if (memcmp(decrypted, text, textlen) != 0)
@@ -288,14 +302,23 @@
 
 static void test_generated_aes128(void)
 {
-    test_generated(0);
+    test_generated(0, 0);
 }
 
 static void test_generated_aes256(void)
 {
-    test_generated(1);
+    test_generated(1, 0);
 }
 
+static void test_generated_aes128_iv96(void)
+{
+    test_generated(0, 1);
+}
+
+static void test_generated_aes256_iv96(void)
+{
+    test_generated(1, 1);
+}
 int main(int argc, char **argv)
 {
     if (!ptls_fusion_is_supported_by_cpu()) {
@@ -311,7 +334,8 @@
     subtest("gcm-iv96", gcm_iv96);
     subtest("generated-128", test_generated_aes128);
     subtest("generated-256", test_generated_aes256);
+    subtest("generated-128-iv96", test_generated_aes128_iv96);
+    subtest("generated-256-iv96", test_generated_aes256_iv96);
 
     return done_testing();
-}
-#endif /* Windows and not 64 bits */
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/t/picotls.c b/t/picotls.c
index d0e88ff..74e24eb 100644
--- a/t/picotls.c
+++ b/t/picotls.c
@@ -325,7 +325,7 @@
 static void test_aes128gcm(void)
 {
     ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256),
-                        *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256);
+                        *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256);
 
     test_ciphersuite(cs, cs_peer);
     test_aad_ciphersuite(cs, cs_peer);
@@ -335,7 +335,7 @@
 static void test_aes256gcm(void)
 {
     ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384),
-                        *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384);
+                        *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384);
 
     if (cs != NULL && cs_peer != NULL) {
         test_ciphersuite(cs, cs_peer);
@@ -347,7 +347,7 @@
 static void test_chacha20poly1305(void)
 {
     ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256),
-                        *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256);
+                        *cs_peer = find_cipher(ctx_peer, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256);
 
     if (cs != NULL && cs_peer != NULL) {
         test_ciphersuite(cs, cs_peer);