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)
{
}
}
+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).
}
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;
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,
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);
}
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);
}
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);
}
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);
}
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");
} 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");
+ }
}
/*
} 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
static void
test_EC_KAT(const char *name, const br_ec_impl *impl, uint32_t curve_mask)
{
-
printf("Test %s: ", name);
fflush(stdout);
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)
{
(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
(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
{
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
{
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 {
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[] = {
STU(MD5_SHA1),
STU(multihash),
STU(HMAC),
+ STU(HKDF),
STU(HMAC_DRBG),
STU(AESCTR_DRBG),
STU(PRF),
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),