Added "ctmulq" implementation of Poly1305 (using 64->128 multiplications when available).
[BearSSL] / test / test_crypto.c
index ddba9ac..95edd24 100644 (file)
@@ -591,7 +591,7 @@ test_HMAC_CT(const br_hash_class *digest_class,
 
        br_hmac_key_init(&kc, digest_class, key, key_len);
 
 
        br_hmac_key_init(&kc, digest_class, key, key_len);
 
-       for (u = 0; u < 130; u ++) {
+       for (u = 0; u < 2; u ++) {
                for (v = 0; v < 130; v ++) {
                        size_t min_len, max_len;
                        size_t w;
                for (v = 0; v < 130; v ++) {
                        size_t min_len, max_len;
                        size_t w;
@@ -3157,7 +3157,6 @@ test_AES_generic(char *name,
                        data_len = hextobin(plain, KAT_AES_CTR[u + 2]);
                        hextobin(cipher, KAT_AES_CTR[u + 3]);
                        vc->init(xc, key, key_len);
                        data_len = hextobin(plain, KAT_AES_CTR[u + 2]);
                        hextobin(cipher, KAT_AES_CTR[u + 3]);
                        vc->init(xc, key, key_len);
-
                        memcpy(buf, plain, data_len);
                        vc->run(xc, iv, 1, buf, data_len);
                        check_equals("KAT CTR AES (1)", buf, cipher, data_len);
                        memcpy(buf, plain, data_len);
                        vc->run(xc, iv, 1, buf, data_len);
                        check_equals("KAT CTR AES (1)", buf, cipher, data_len);
@@ -3271,6 +3270,60 @@ test_AES_ct64(void)
                1, 1);
 }
 
                1, 1);
 }
 
+static void
+test_AES_x86ni(void)
+{
+       const br_block_cbcenc_class *x_cbcenc;
+       const br_block_cbcdec_class *x_cbcdec;
+       const br_block_ctr_class *x_ctr;
+       int hcbcenc, hcbcdec, hctr;
+
+       x_cbcenc = br_aes_x86ni_cbcenc_get_vtable();
+       x_cbcdec = br_aes_x86ni_cbcdec_get_vtable();
+       x_ctr = br_aes_x86ni_ctr_get_vtable();
+       hcbcenc = (x_cbcenc != NULL);
+       hcbcdec = (x_cbcdec != NULL);
+       hctr = (x_ctr != NULL);
+       if (hcbcenc != hctr || hcbcdec != hctr) {
+               fprintf(stderr, "AES_x86ni availability mismatch (%d/%d/%d)\n",
+                       hcbcenc, hcbcdec, hctr);
+               exit(EXIT_FAILURE);
+       }
+       if (hctr) {
+               test_AES_generic("AES_x86ni",
+                       x_cbcenc, x_cbcdec, x_ctr, 1, 1);
+       } else {
+               printf("Test AES_x86ni: UNAVAILABLE\n");
+       }
+}
+
+static void
+test_AES_pwr8(void)
+{
+       const br_block_cbcenc_class *x_cbcenc;
+       const br_block_cbcdec_class *x_cbcdec;
+       const br_block_ctr_class *x_ctr;
+       int hcbcenc, hcbcdec, hctr;
+
+       x_cbcenc = br_aes_pwr8_cbcenc_get_vtable();
+       x_cbcdec = br_aes_pwr8_cbcdec_get_vtable();
+       x_ctr = br_aes_pwr8_ctr_get_vtable();
+       hcbcenc = (x_cbcenc != NULL);
+       hcbcdec = (x_cbcdec != NULL);
+       hctr = (x_ctr != NULL);
+       if (hcbcenc != hctr || hcbcdec != hctr) {
+               fprintf(stderr, "AES_pwr8 availability mismatch (%d/%d/%d)\n",
+                       hcbcenc, hcbcdec, hctr);
+               exit(EXIT_FAILURE);
+       }
+       if (hctr) {
+               test_AES_generic("AES_pwr8",
+                       x_cbcenc, x_cbcdec, x_ctr, 1, 1);
+       } else {
+               printf("Test AES_pwr8: UNAVAILABLE\n");
+       }
+}
+
 /*
  * DES known-answer tests. Order: plaintext, key, ciphertext.
  * (mostly from NIST SP 800-20).
 /*
  * DES known-answer tests. Order: plaintext, key, ciphertext.
  * (mostly from NIST SP 800-20).
@@ -4137,24 +4190,12 @@ test_Poly1305_inner(const char *name, br_poly1305_run ipoly,
                memcpy(data, plain, len);
                ipoly(key, nonce, data, len,
                        aad, aad_len, tmp, br_chacha20_ct_run, 1);
                memcpy(data, plain, len);
                ipoly(key, nonce, data, len,
                        aad, aad_len, tmp, br_chacha20_ct_run, 1);
-               if (memcmp(data, cipher, len) != 0) {
-                       fprintf(stderr, "ChaCha20+Poly1305 KAT failed (1)\n");
-                       exit(EXIT_FAILURE);
-               }
-               if (memcmp(tmp, tag, 16) != 0) {
-                       fprintf(stderr, "ChaCha20+Poly1305 KAT failed (2)\n");
-                       exit(EXIT_FAILURE);
-               }
+               check_equals("ChaCha20+Poly1305 KAT (1)", data, cipher, len);
+               check_equals("ChaCha20+Poly1305 KAT (2)", tmp, tag, 16);
                ipoly(key, nonce, data, len,
                        aad, aad_len, tmp, br_chacha20_ct_run, 0);
                ipoly(key, nonce, data, len,
                        aad, aad_len, tmp, br_chacha20_ct_run, 0);
-               if (memcmp(data, plain, len) != 0) {
-                       fprintf(stderr, "ChaCha20+Poly1305 KAT failed (3)\n");
-                       exit(EXIT_FAILURE);
-               }
-               if (memcmp(tmp, tag, 16) != 0) {
-                       fprintf(stderr, "ChaCha20+Poly1305 KAT failed (4)\n");
-                       exit(EXIT_FAILURE);
-               }
+               check_equals("ChaCha20+Poly1305 KAT (3)", data, plain, len);
+               check_equals("ChaCha20+Poly1305 KAT (4)", tmp, tag, 16);
 
                printf(".");
                fflush(stdout);
 
                printf(".");
                fflush(stdout);
@@ -4220,6 +4261,20 @@ test_Poly1305_i15(void)
                &br_poly1305_ctmul_run);
 }
 
                &br_poly1305_ctmul_run);
 }
 
+static void
+test_Poly1305_ctmulq(void)
+{
+       br_poly1305_run bp;
+
+       bp = br_poly1305_ctmulq_get();
+       if (bp == 0) {
+               printf("Test Poly1305_ctmulq: UNAVAILABLE\n");
+       } else {
+               test_Poly1305_inner("Poly1305_ctmulq", bp,
+                       &br_poly1305_ctmul_run);
+       }
+}
+
 /*
  * A 1024-bit RSA key, generated with OpenSSL.
  */
 /*
  * A 1024-bit RSA key, generated with OpenSSL.
  */
@@ -4649,6 +4704,31 @@ test_GHASH(const char *name, br_ghash gh)
                check_equals("KAT GHASH", y, ref, sizeof ref);
        }
 
                check_equals("KAT GHASH", y, ref, sizeof ref);
        }
 
+       for (u = 0; u <= 1024; u ++) {
+               unsigned char key[32], iv[12];
+               unsigned char buf[1024 + 32];
+               unsigned char y0[16], y1[16];
+               char tmp[100];
+
+               memset(key, 0, sizeof key);
+               memset(iv, 0, sizeof iv);
+               br_enc32be(key, u);
+               memset(buf, 0, sizeof buf);
+               br_chacha20_ct_run(key, iv, 1, buf, sizeof buf);
+
+               memcpy(y0, buf, 16);
+               br_ghash_ctmul32(y0, buf + 16, buf + 32, u);
+               memcpy(y1, buf, 16);
+               gh(y1, buf + 16, buf + 32, u);
+               sprintf(tmp, "XREF %s (len = %u)", name, (unsigned)u);
+               check_equals(tmp, y0, y1, 16);
+
+               if ((u & 31) == 0) {
+                       printf(".");
+                       fflush(stdout);
+               }
+       }
+
        printf("done.\n");
        fflush(stdout);
 }
        printf("done.\n");
        fflush(stdout);
 }
@@ -4671,6 +4751,32 @@ test_GHASH_ctmul64(void)
        test_GHASH("GHASH_ctmul64", br_ghash_ctmul64);
 }
 
        test_GHASH("GHASH_ctmul64", br_ghash_ctmul64);
 }
 
+static void
+test_GHASH_pclmul(void)
+{
+       br_ghash gh;
+
+       gh = br_ghash_pclmul_get();
+       if (gh == 0) {
+               printf("Test GHASH_pclmul: UNAVAILABLE\n");
+       } else {
+               test_GHASH("GHASH_pclmul", gh);
+       }
+}
+
+static void
+test_GHASH_pwr8(void)
+{
+       br_ghash gh;
+
+       gh = br_ghash_pwr8_get();
+       if (gh == 0) {
+               printf("Test GHASH_pwr8: UNAVAILABLE\n");
+       } else {
+               test_GHASH("GHASH_pwr8", gh);
+       }
+}
+
 static void
 test_EC_inner(const char *sk, const char *sU,
        const br_ec_impl *impl, int curve)
 static void
 test_EC_inner(const char *sk, const char *sU,
        const br_ec_impl *impl, int curve)
@@ -4918,6 +5024,13 @@ test_EC_p256_m15(void)
                (uint32_t)1 << BR_EC_secp256r1);
 }
 
                (uint32_t)1 << BR_EC_secp256r1);
 }
 
+static void
+test_EC_p256_m31(void)
+{
+       test_EC_KAT("EC_p256_m31", &br_ec_p256_m31,
+               (uint32_t)1 << BR_EC_secp256r1);
+}
+
 const struct {
        const char *scalar;
        const char *u_in;
 const struct {
        const char *scalar;
        const char *u_in;
@@ -4935,13 +5048,13 @@ const struct {
 static void
 test_EC_c25519(const char *name, const br_ec_impl *iec)
 {
 static void
 test_EC_c25519(const char *name, const br_ec_impl *iec)
 {
+       unsigned char bu[32], bk[32], br[32];
        size_t v;
        size_t v;
+       int i;
 
        printf("Test %s: ", name);
        fflush(stdout);
        for (v = 0; C25519_KAT[v].scalar; v ++) {
 
        printf("Test %s: ", name);
        fflush(stdout);
        for (v = 0; C25519_KAT[v].scalar; v ++) {
-               unsigned char bu[32], bk[32], br[32];
-
                hextobin(bk, C25519_KAT[v].scalar);
                hextobin(bu, C25519_KAT[v].u_in);
                hextobin(br, C25519_KAT[v].u_out);
                hextobin(bk, C25519_KAT[v].scalar);
                hextobin(bu, C25519_KAT[v].u_in);
                hextobin(br, C25519_KAT[v].u_out);
@@ -4956,6 +5069,44 @@ test_EC_c25519(const char *name, const br_ec_impl *iec)
                printf(".");
                fflush(stdout);
        }
                printf(".");
                fflush(stdout);
        }
+       printf(" ");
+       fflush(stdout);
+
+       memset(bu, 0, sizeof bu);
+       bu[0] = 0x09;
+       memcpy(bk, bu, sizeof bu);
+       for (i = 1; i <= 1000; i ++) {
+               if (!iec->mul(bu, sizeof bu, bk, sizeof bk, BR_EC_curve25519)) {
+                       fprintf(stderr, "Curve25519 multiplication failed"
+                               " (iter=%d)\n", i);
+                       exit(EXIT_FAILURE);
+               }
+               for (v = 0; v < sizeof bu; v ++) {
+                       unsigned t;
+
+                       t = bu[v];
+                       bu[v] = bk[v];
+                       bk[v] = t;
+               }
+               if (i == 1 || i == 1000) {
+                       const char *sref;
+
+                       sref = (i == 1)
+                               ? "422C8E7A6227D7BCA1350B3E2BB7279F7897B87BB6854B783C60E80311AE3079"
+                               : "684CF59BA83309552800EF566F2F4D3C1C3887C49360E3875F2EB94D99532C51";
+                       hextobin(br, sref);
+                       if (memcmp(bk, br, sizeof bk) != 0) {
+                               fprintf(stderr,
+                                       "Curve25519 failed KAT (iter=%d)\n", i);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               if (i % 100 == 0) {
+                       printf(".");
+                       fflush(stdout);
+               }
+       }
+
        printf(" done.\n");
        fflush(stdout);
 }
        printf(" done.\n");
        fflush(stdout);
 }
@@ -4966,6 +5117,24 @@ test_EC_c25519_i15(void)
        test_EC_c25519("EC_c25519_i15", &br_ec_c25519_i15);
 }
 
        test_EC_c25519("EC_c25519_i15", &br_ec_c25519_i15);
 }
 
+static void
+test_EC_c25519_i31(void)
+{
+       test_EC_c25519("EC_c25519_i31", &br_ec_c25519_i31);
+}
+
+static void
+test_EC_c25519_m15(void)
+{
+       test_EC_c25519("EC_c25519_m15", &br_ec_c25519_m15);
+}
+
+static void
+test_EC_c25519_m31(void)
+{
+       test_EC_c25519("EC_c25519_m31", &br_ec_c25519_m31);
+}
+
 static const unsigned char EC_P256_PUB_POINT[] = {
        0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D,
        0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D,
 static const unsigned char EC_P256_PUB_POINT[] = {
        0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D,
        0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D,
@@ -5496,11 +5665,14 @@ static const struct {
        STU(AES_small),
        STU(AES_ct),
        STU(AES_ct64),
        STU(AES_small),
        STU(AES_ct),
        STU(AES_ct64),
+       STU(AES_pwr8),
+       STU(AES_x86ni),
        STU(DES_tab),
        STU(DES_ct),
        STU(ChaCha20_ct),
        STU(Poly1305_ctmul),
        STU(Poly1305_ctmul32),
        STU(DES_tab),
        STU(DES_ct),
        STU(ChaCha20_ct),
        STU(Poly1305_ctmul),
        STU(Poly1305_ctmul32),
+       STU(Poly1305_ctmulq),
        STU(Poly1305_i15),
        STU(RSA_i15),
        STU(RSA_i31),
        STU(Poly1305_i15),
        STU(RSA_i15),
        STU(RSA_i31),
@@ -5508,11 +5680,16 @@ static const struct {
        STU(GHASH_ctmul),
        STU(GHASH_ctmul32),
        STU(GHASH_ctmul64),
        STU(GHASH_ctmul),
        STU(GHASH_ctmul32),
        STU(GHASH_ctmul64),
+       STU(GHASH_pclmul),
+       STU(GHASH_pwr8),
        STU(EC_prime_i15),
        STU(EC_prime_i31),
        STU(EC_p256_m15),
        STU(EC_prime_i15),
        STU(EC_prime_i31),
        STU(EC_p256_m15),
-       /* STU(EC_prime_i32), */
+       STU(EC_p256_m31),
        STU(EC_c25519_i15),
        STU(EC_c25519_i15),
+       STU(EC_c25519_i31),
+       STU(EC_c25519_m15),
+       STU(EC_c25519_m31),
        STU(ECDSA_i15),
        STU(ECDSA_i31),
        { 0, 0 }
        STU(ECDSA_i15),
        STU(ECDSA_i31),
        { 0, 0 }