X-Git-Url: https://bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=test%2Ftest_crypto.c;h=740178db1db2a6e5223538192d7b6d6851d4717e;hp=60a431c8e34f5a33a6bfb05064ae8a6513a32ca1;hb=8ef7680081c61b486622f2d983c0d3d21e83caad;hpb=cfbc702d3d64c209784b664eeab8867b603f4d4c diff --git a/test/test_crypto.c b/test/test_crypto.c index 60a431c..740178d 100644 --- a/test/test_crypto.c +++ b/test/test_crypto.c @@ -1029,6 +1029,107 @@ test_HMAC(void) fflush(stdout); } +static void +test_HKDF_inner(const br_hash_class *dig, const char *ikmhex, + const char *salthex, const char *infohex, const char *okmhex) +{ + unsigned char ikm[100], saltbuf[100], info[100], okm[100], tmp[107]; + const unsigned char *salt; + size_t ikm_len, salt_len, info_len, okm_len; + br_hkdf_context hc; + size_t u; + + ikm_len = hextobin(ikm, ikmhex); + if (salthex == NULL) { + salt = BR_HKDF_NO_SALT; + salt_len = 0; + } else { + salt = saltbuf; + salt_len = hextobin(saltbuf, salthex); + } + info_len = hextobin(info, infohex); + okm_len = hextobin(okm, okmhex); + + br_hkdf_init(&hc, dig, salt, salt_len); + br_hkdf_inject(&hc, ikm, ikm_len); + br_hkdf_flip(&hc); + br_hkdf_produce(&hc, info, info_len, tmp, okm_len); + check_equals("KAT HKDF 1", tmp, okm, okm_len); + + br_hkdf_init(&hc, dig, salt, salt_len); + for (u = 0; u < ikm_len; u ++) { + br_hkdf_inject(&hc, &ikm[u], 1); + } + br_hkdf_flip(&hc); + for (u = 0; u < okm_len; u ++) { + br_hkdf_produce(&hc, info, info_len, &tmp[u], 1); + } + check_equals("KAT HKDF 2", tmp, okm, okm_len); + + br_hkdf_init(&hc, dig, salt, salt_len); + br_hkdf_inject(&hc, ikm, ikm_len); + br_hkdf_flip(&hc); + for (u = 0; u < okm_len; u += 7) { + br_hkdf_produce(&hc, info, info_len, &tmp[u], 7); + } + check_equals("KAT HKDF 3", tmp, okm, okm_len); + + printf("."); + fflush(stdout); +} + +static void +test_HKDF(void) +{ + printf("Test HKDF: "); + fflush(stdout); + + test_HKDF_inner(&br_sha256_vtable, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"); + + test_HKDF_inner(&br_sha256_vtable, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"); + + test_HKDF_inner(&br_sha256_vtable, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"); + + test_HKDF_inner(&br_sha1_vtable, + "0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"); + + test_HKDF_inner(&br_sha1_vtable, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"); + + test_HKDF_inner(&br_sha1_vtable, + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"); + + test_HKDF_inner(&br_sha1_vtable, + "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", + NULL, + "", + "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"); + + printf(" done.\n"); + fflush(stdout); +} + static void test_HMAC_DRBG(void) { @@ -3664,6 +3765,19 @@ test_AES_CTRCBC_x86ni(void) } } +static void +test_AES_CTRCBC_pwr8(void) +{ + const br_block_ctrcbc_class *vt; + + vt = br_aes_pwr8_ctrcbc_get_vtable(); + if (vt != NULL) { + test_AES_CTRCBC_inner("pwr8", vt); + } else { + printf("Test AES CTR/CBC-MAC pwr8: UNAVAILABLE\n"); + } +} + /* * DES known-answer tests. Order: plaintext, key, ciphertext. * (mostly from NIST SP 800-20). @@ -5721,8 +5835,9 @@ test_RSA_OAEP(const char *name, } static void -test_RSA_keygen(const char *name, br_rsa_keygen kg, - br_rsa_pkcs1_sign sign, br_rsa_pkcs1_vrfy vrfy) +test_RSA_keygen(const char *name, br_rsa_keygen kg, br_rsa_compute_modulus cm, + br_rsa_compute_pubexp ce, br_rsa_compute_privexp cd, + br_rsa_public pub, br_rsa_pkcs1_sign sign, br_rsa_pkcs1_vrfy vrfy) { br_hmac_drbg_context rng; int i; @@ -5732,25 +5847,30 @@ test_RSA_keygen(const char *name, br_rsa_keygen kg, br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for RSA keygen", 19); - for (i = 0; i < 40; i ++) { + for (i = 0; i <= 42; i ++) { unsigned size; - uint32_t pubexp; + uint32_t pubexp, z; br_rsa_private_key sk; - br_rsa_public_key pk; + br_rsa_public_key pk, pk2; unsigned char kbuf_priv[BR_RSA_KBUF_PRIV_SIZE(2048)]; unsigned char kbuf_pub[BR_RSA_KBUF_PUB_SIZE(2048)]; + unsigned char n2[256], d[256], msg1[256], msg2[256]; uint32_t mod[256]; uint32_t cc; size_t u, v; unsigned char sig[257], hv[32], hv2[sizeof hv]; unsigned mask1, mask2; + int j; if (i <= 35) { size = 1024 + i; pubexp = 17; - } else { + } else if (i <= 40) { size = 2048; pubexp = (i << 1) - 69; + } else { + size = 2048; + pubexp = 0xFFFFFFFF; } if (!kg(&rng.vtable, @@ -5760,14 +5880,15 @@ test_RSA_keygen(const char *name, br_rsa_keygen kg, exit(EXIT_FAILURE); } + z = pubexp; for (u = pk.elen; u > 0; u --) { - if (pk.e[u - 1] != (pubexp & 0xFF)) { + if (pk.e[u - 1] != (z & 0xFF)) { fprintf(stderr, "wrong public exponent\n"); exit(EXIT_FAILURE); } - pubexp >>= 8; + z >>= 8; } - if (pubexp != 0) { + if (z != 0) { fprintf(stderr, "truncated public exponent\n"); exit(EXIT_FAILURE); } @@ -5806,28 +5927,86 @@ test_RSA_keygen(const char *name, br_rsa_keygen kg, exit(EXIT_FAILURE); } - rng.vtable->generate(&rng.vtable, hv, sizeof hv); - memset(sig, 0, sizeof sig); - sig[pk.nlen] = 0x00; - if (!sign(BR_HASH_OID_SHA256, hv, sizeof hv, &sk, sig)) { - fprintf(stderr, "signature error\n"); + if (cm(NULL, &sk) != pk.nlen) { + fprintf(stderr, "wrong recomputed modulus length\n"); exit(EXIT_FAILURE); } - if (sig[pk.nlen] != 0x00) { - fprintf(stderr, "signature length error\n"); + if (cm(n2, &sk) != pk.nlen || memcmp(pk.n, n2, pk.nlen) != 0) { + fprintf(stderr, "wrong recomputed modulus value\n"); exit(EXIT_FAILURE); } - if (!vrfy(sig, pk.nlen, BR_HASH_OID_SHA256, sizeof hv, - &pk, hv2)) - { - fprintf(stderr, "signature verification error (1)\n"); + + z = ce(&sk); + if (z != pubexp) { + fprintf(stderr, + "wrong recomputed pubexp: %lu (exp: %lu)\n", + (unsigned long)z, (unsigned long)pubexp); + exit(EXIT_FAILURE); + } + + if (cd(NULL, &sk, pubexp) != pk.nlen) { + fprintf(stderr, + "wrong recomputed privexp length (1)\n"); + exit(EXIT_FAILURE); + } + if (cd(d, &sk, pubexp) != pk.nlen) { + fprintf(stderr, + "wrong recomputed privexp length (2)\n"); + exit(EXIT_FAILURE); + } + /* + * To check that the private exponent is correct, we make + * it into a _public_ key, and use the public-key operation + * to perform the modular exponentiation. + */ + pk2 = pk; + pk2.e = d; + pk2.elen = pk.nlen; + rng.vtable->generate(&rng.vtable, msg1, pk.nlen); + msg1[0] = 0x00; + memcpy(msg2, msg1, pk.nlen); + if (!pub(msg2, pk.nlen, &pk2) || !pub(msg2, pk.nlen, &pk)) { + fprintf(stderr, "public-key operation error\n"); exit(EXIT_FAILURE); } - if (memcmp(hv, hv2, sizeof hv) != 0) { - fprintf(stderr, "signature verification error (2)\n"); + if (memcmp(msg1, msg2, pk.nlen) != 0) { + fprintf(stderr, "wrong recomputed privexp\n"); exit(EXIT_FAILURE); } + /* + * We test the RSA operation over a some random messages. + */ + for (j = 0; j < 20; j ++) { + rng.vtable->generate(&rng.vtable, hv, sizeof hv); + memset(sig, 0, sizeof sig); + sig[pk.nlen] = 0x00; + if (!sign(BR_HASH_OID_SHA256, + hv, sizeof hv, &sk, sig)) + { + fprintf(stderr, + "signature error (%d)\n", j); + exit(EXIT_FAILURE); + } + if (sig[pk.nlen] != 0x00) { + fprintf(stderr, + "signature length error (%d)\n", j); + exit(EXIT_FAILURE); + } + if (!vrfy(sig, pk.nlen, BR_HASH_OID_SHA256, sizeof hv, + &pk, hv2)) + { + fprintf(stderr, + "signature verif error (%d)\n", j); + exit(EXIT_FAILURE); + } + if (memcmp(hv, hv2, sizeof hv) != 0) { + fprintf(stderr, + "signature extract error (%d)\n", j); + exit(EXIT_FAILURE); + } + } + printf("."); fflush(stdout); } @@ -5845,6 +6024,8 @@ test_RSA_i15(void) test_RSA_OAEP("RSA i15 OAEP", &br_rsa_i15_oaep_encrypt, &br_rsa_i15_oaep_decrypt); test_RSA_keygen("RSA i15 keygen", &br_rsa_i15_keygen, + &br_rsa_i15_compute_modulus, &br_rsa_i15_compute_pubexp, + &br_rsa_i15_compute_privexp, &br_rsa_i15_public, &br_rsa_i15_pkcs1_sign, &br_rsa_i15_pkcs1_vrfy); } @@ -5857,6 +6038,8 @@ test_RSA_i31(void) test_RSA_OAEP("RSA i31 OAEP", &br_rsa_i31_oaep_encrypt, &br_rsa_i31_oaep_decrypt); test_RSA_keygen("RSA i31 keygen", &br_rsa_i31_keygen, + &br_rsa_i31_compute_modulus, &br_rsa_i31_compute_pubexp, + &br_rsa_i31_compute_privexp, &br_rsa_i31_public, &br_rsa_i31_pkcs1_sign, &br_rsa_i31_pkcs1_vrfy); } @@ -5896,7 +6079,10 @@ test_RSA_i62(void) test_RSA_core("RSA i62 core", pub, priv); test_RSA_sign("RSA i62 sign", priv, sign, vrfy); test_RSA_OAEP("RSA i62 OAEP", menc, mdec); - test_RSA_keygen("RSA i62 keygen", kgen, sign, vrfy); + test_RSA_keygen("RSA i62 keygen", kgen, + &br_rsa_i31_compute_modulus, &br_rsa_i31_compute_pubexp, + &br_rsa_i31_compute_privexp, pub, + sign, vrfy); } else { if (priv || sign || vrfy || menc || mdec || kgen) { fprintf(stderr, "Inconsistent i62 availability\n"); @@ -6767,6 +6953,13 @@ test_EAX(void) } else { printf("Test EAX aes_x86ni: UNAVAILABLE\n"); } + + x_ctrcbc = br_aes_pwr8_ctrcbc_get_vtable(); + if (x_ctrcbc != NULL) { + test_EAX_inner("aes_pwr8", x_ctrcbc); + } else { + printf("Test EAX aes_pwr8: UNAVAILABLE\n"); + } } /* @@ -6979,6 +7172,13 @@ test_CCM(void) } else { printf("Test CCM aes_x86ni: UNAVAILABLE\n"); } + + x_ctrcbc = br_aes_pwr8_ctrcbc_get_vtable(); + if (x_ctrcbc != NULL) { + test_CCM_inner("aes_pwr8", x_ctrcbc); + } else { + printf("Test CCM aes_pwr8: UNAVAILABLE\n"); + } } static void @@ -7209,7 +7409,6 @@ test_EC_P256_carry(const br_ec_impl *impl) static void test_EC_KAT(const char *name, const br_ec_impl *impl, uint32_t curve_mask) { - printf("Test %s: ", name); fflush(stdout); @@ -7237,6 +7436,155 @@ test_EC_KAT(const char *name, const br_ec_impl *impl, uint32_t curve_mask) fflush(stdout); } +static void +test_EC_keygen(const char *name, const br_ec_impl *impl, uint32_t curves) +{ + int curve; + br_hmac_drbg_context rng; + + printf("Test %s keygen: ", name); + fflush(stdout); + + br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for EC keygen", 18); + br_hmac_drbg_update(&rng, name, strlen(name)); + + for (curve = -1; curve <= 35; curve ++) { + br_ec_private_key sk; + br_ec_public_key pk; + unsigned char kbuf_priv[BR_EC_KBUF_PRIV_MAX_SIZE]; + unsigned char kbuf_pub[BR_EC_KBUF_PUB_MAX_SIZE]; + + if (curve < 0 || curve >= 32 || ((curves >> curve) & 1) == 0) { + if (br_ec_keygen(&rng.vtable, impl, + &sk, kbuf_priv, curve) != 0) + { + fprintf(stderr, "br_ec_keygen() did not" + " reject unsupported curve %d\n", + curve); + exit(EXIT_FAILURE); + } + sk.curve = curve; + if (br_ec_compute_pub(impl, NULL, NULL, &sk) != 0) { + fprintf(stderr, "br_ec_keygen() did not" + " reject unsupported curve %d\n", + curve); + exit(EXIT_FAILURE); + } + } else { + size_t len, u; + unsigned char tmp_priv[sizeof kbuf_priv]; + unsigned char tmp_pub[sizeof kbuf_pub]; + unsigned z; + + len = br_ec_keygen(&rng.vtable, impl, + NULL, NULL, curve); + if (len == 0) { + fprintf(stderr, "br_ec_keygen() rejects" + " supported curve %d\n", curve); + exit(EXIT_FAILURE); + } + if (len > sizeof kbuf_priv) { + fprintf(stderr, "oversized kbuf_priv\n"); + exit(EXIT_FAILURE); + } + memset(kbuf_priv, 0, sizeof kbuf_priv); + if (br_ec_keygen(&rng.vtable, impl, + NULL, kbuf_priv, curve) != len) + { + fprintf(stderr, "kbuf_priv length mismatch\n"); + exit(EXIT_FAILURE); + } + z = 0; + for (u = 0; u < len; u ++) { + z |= kbuf_priv[u]; + } + if (z == 0) { + fprintf(stderr, "kbuf_priv not initialized\n"); + exit(EXIT_FAILURE); + } + for (u = len; u < sizeof kbuf_priv; u ++) { + if (kbuf_priv[u] != 0) { + fprintf(stderr, "kbuf_priv overflow\n"); + exit(EXIT_FAILURE); + } + } + if (br_ec_keygen(&rng.vtable, impl, + NULL, tmp_priv, curve) != len) + { + fprintf(stderr, "tmp_priv length mismatch\n"); + exit(EXIT_FAILURE); + } + if (memcmp(kbuf_priv, tmp_priv, len) == 0) { + fprintf(stderr, "keygen stutter\n"); + exit(EXIT_FAILURE); + } + memset(&sk, 0, sizeof sk); + if (br_ec_keygen(&rng.vtable, impl, + &sk, kbuf_priv, curve) != len) + { + fprintf(stderr, + "kbuf_priv length mismatch (2)\n"); + exit(EXIT_FAILURE); + } + if (sk.curve != curve || sk.x != kbuf_priv + || sk.xlen != len) + { + fprintf(stderr, "sk not initialized\n"); + exit(EXIT_FAILURE); + } + + len = br_ec_compute_pub(impl, NULL, NULL, &sk); + if (len > sizeof kbuf_pub) { + fprintf(stderr, "oversized kbuf_pub\n"); + exit(EXIT_FAILURE); + } + memset(kbuf_pub, 0, sizeof kbuf_pub); + if (br_ec_compute_pub(impl, NULL, + kbuf_pub, &sk) != len) + { + fprintf(stderr, "kbuf_pub length mismatch\n"); + exit(EXIT_FAILURE); + } + for (u = len; u < sizeof kbuf_pub; u ++) { + if (kbuf_pub[u] != 0) { + fprintf(stderr, "kbuf_pub overflow\n"); + exit(EXIT_FAILURE); + } + } + memset(&pk, 0, sizeof pk); + if (br_ec_compute_pub(impl, &pk, + tmp_pub, &sk) != len) + { + fprintf(stderr, "tmp_pub length mismatch\n"); + exit(EXIT_FAILURE); + } + if (memcmp(kbuf_pub, tmp_pub, len) != 0) { + fprintf(stderr, "pubkey mismatch\n"); + exit(EXIT_FAILURE); + } + if (pk.curve != curve || pk.q != tmp_pub + || pk.qlen != len) + { + fprintf(stderr, "pk not initialized\n"); + exit(EXIT_FAILURE); + } + + if (impl->mulgen(kbuf_pub, + sk.x, sk.xlen, curve) != len + || memcmp(pk.q, kbuf_pub, len) != 0) + { + fprintf(stderr, "wrong pubkey\n"); + exit(EXIT_FAILURE); + } + } + printf("."); + fflush(stdout); + } + + printf(" done.\n"); + fflush(stdout); +} + static void test_EC_prime_i15(void) { @@ -7244,6 +7592,10 @@ test_EC_prime_i15(void) (uint32_t)1 << BR_EC_secp256r1 | (uint32_t)1 << BR_EC_secp384r1 | (uint32_t)1 << BR_EC_secp521r1); + test_EC_keygen("EC_prime_i15", &br_ec_prime_i15, + (uint32_t)1 << BR_EC_secp256r1 + | (uint32_t)1 << BR_EC_secp384r1 + | (uint32_t)1 << BR_EC_secp521r1); } static void @@ -7253,6 +7605,10 @@ test_EC_prime_i31(void) (uint32_t)1 << BR_EC_secp256r1 | (uint32_t)1 << BR_EC_secp384r1 | (uint32_t)1 << BR_EC_secp521r1); + test_EC_keygen("EC_prime_i31", &br_ec_prime_i31, + (uint32_t)1 << BR_EC_secp256r1 + | (uint32_t)1 << BR_EC_secp384r1 + | (uint32_t)1 << BR_EC_secp521r1); } static void @@ -7260,6 +7616,8 @@ test_EC_p256_m15(void) { test_EC_KAT("EC_p256_m15", &br_ec_p256_m15, (uint32_t)1 << BR_EC_secp256r1); + test_EC_keygen("EC_p256_m15", &br_ec_p256_m15, + (uint32_t)1 << BR_EC_secp256r1); } static void @@ -7267,6 +7625,8 @@ test_EC_p256_m31(void) { test_EC_KAT("EC_p256_m31", &br_ec_p256_m31, (uint32_t)1 << BR_EC_secp256r1); + test_EC_keygen("EC_p256_m31", &br_ec_p256_m31, + (uint32_t)1 << BR_EC_secp256r1); } const struct { @@ -7353,24 +7713,32 @@ static void test_EC_c25519_i15(void) { test_EC_c25519("EC_c25519_i15", &br_ec_c25519_i15); + test_EC_keygen("EC_c25519_i15", &br_ec_c25519_i15, + (uint32_t)1 << BR_EC_curve25519); } static void test_EC_c25519_i31(void) { test_EC_c25519("EC_c25519_i31", &br_ec_c25519_i31); + test_EC_keygen("EC_c25519_i31", &br_ec_c25519_i31, + (uint32_t)1 << BR_EC_curve25519); } static void test_EC_c25519_m15(void) { test_EC_c25519("EC_c25519_m15", &br_ec_c25519_m15); + test_EC_keygen("EC_c25519_m15", &br_ec_c25519_m15, + (uint32_t)1 << BR_EC_curve25519); } static void test_EC_c25519_m31(void) { test_EC_c25519("EC_c25519_m31", &br_ec_c25519_m31); + test_EC_keygen("EC_c25519_m31", &br_ec_c25519_m31, + (uint32_t)1 << BR_EC_curve25519); } static const unsigned char EC_P256_PUB_POINT[] = { @@ -7999,6 +8367,7 @@ static const struct { STU(MD5_SHA1), STU(multihash), STU(HMAC), + STU(HKDF), STU(HMAC_DRBG), STU(AESCTR_DRBG), STU(PRF), @@ -8013,6 +8382,7 @@ static const struct { STU(AES_CTRCBC_ct), STU(AES_CTRCBC_ct64), STU(AES_CTRCBC_x86ni), + STU(AES_CTRCBC_pwr8), STU(DES_tab), STU(DES_ct), STU(ChaCha20_ct),