aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/GNUmakefile5
-rw-r--r--tests/test-bus.c3
-rw-r--r--tests/test-ecdsa.c87
-rw-r--r--tests/test-ecdsa.h39
-rw-r--r--tests/test-ecdsa.py50
-rw-r--r--tests/test-hash.c6
-rw-r--r--tests/test-rpc_hash.c700
-rw-r--r--tests/test-rpc_pkey.c348
-rw-r--r--tests/test-rpc_server.c18
-rw-r--r--tests/test-rsa.c154
11 files changed, 1262 insertions, 149 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
deleted file mode 100644
index 0e3ba34..0000000
--- a/tests/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-test-aes-key-wrap
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index 596bf0f..4bb5f72 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -29,14 +29,15 @@
INC = ../hal.h
LIB = ../libhal.a
-BIN = test-aes-key-wrap test-hash test-pbkdf2 test-rsa test-ecdsa test-bus test-trng
+BIN = test-aes-key-wrap test-hash test-pbkdf2 test-ecdsa test-bus test-trng test-rsa
+BIN += test-rpc_hash test-rpc_server test-rpc_pkey
CFLAGS = -g3 -Wall -fPIC -std=c99 -I..
all: ${BIN}
test: all
- for i in ${BIN}; do ./$$i; done
+ for i in ${BIN}; do (set -x; ./$$i); done
clean:
rm -f *.o ${BIN}
diff --git a/tests/test-bus.c b/tests/test-bus.c
index 1c60e5d..b4a3e1c 100644
--- a/tests/test-bus.c
+++ b/tests/test-bus.c
@@ -91,7 +91,8 @@ static void _time_check(char *label, const struct timeval t0, const int err)
t.tv_sec -= 1;
}
rounds = (float)TEST_NUM_ROUNDS/((float)t.tv_sec + ((float)t.tv_usec / 1000000));
- printf("%s%lu.%06lu seconds, %u/sec\n", label, t.tv_sec, t.tv_usec, (unsigned)rounds);
+ printf("%s%lu.%06lu seconds, %u/sec\n", label,
+ (unsigned long)t.tv_sec, (unsigned long)t.tv_usec, (unsigned)rounds);
}
#define time_check(_label_, _expr_) \
diff --git a/tests/test-ecdsa.c b/tests/test-ecdsa.c
index ce8aee1..da2b367 100644
--- a/tests/test-ecdsa.c
+++ b/tests/test-ecdsa.c
@@ -49,6 +49,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
+#include <errno.h>
#include <sys/time.h>
@@ -103,7 +104,9 @@ static void set_next_random(const uint8_t * const data, const size_t length)
static int test_against_static_vectors(const ecdsa_tc_t * const tc)
{
+ char fn[sizeof("test-ecdsa-private-key-xxxxxx.der")];
hal_error_t err;
+ FILE *f;
printf("Starting static test vector tests for P-%lu\n", (unsigned long) (tc->d_len * 8));
@@ -127,20 +130,34 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
if (tc->Qy_len != Qy_len || memcmp(tc->Qy, Qy, Qy_len) != 0)
return printf("Qy mismatch\n"), 0;
- if (hal_ecdsa_key_to_der_len(key1) != tc->key_len)
+ if (hal_ecdsa_private_key_to_der_len(key1) != tc->key_len)
return printf("DER Key length mismatch\n"), 0;
- uint8_t keyder[tc->key_len];
- size_t keyder_len;
+ uint8_t der[tc->key_len];
+ size_t der_len;
- if ((err = hal_ecdsa_key_to_der(key1, keyder, &keyder_len, sizeof(keyder))) != HAL_OK)
- return printf("hal_ecdsa_key_to_der() failed: %s\n", hal_error_string(err)), 0;
+ err = hal_ecdsa_private_key_to_der(key1, der, &der_len, sizeof(der));
+
+ snprintf(fn, sizeof(fn), "test-ecdsa-private-key-p%u.der", (unsigned) tc->d_len * 8);
+
+ if ((f = fopen(fn, "wb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
+
+ if (fwrite(der, der_len, 1, f) != 1)
+ return printf("Length mismatch writing %s\n", fn), 0;
+
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
+
+ /* Deferred error from hal_ecdsa_private_key_to_der() */
+ if (err != HAL_OK)
+ return printf("hal_ecdsa_private_key_to_der() failed: %s\n", hal_error_string(err)), 0;
uint8_t keybuf2[hal_ecdsa_key_t_size];
hal_ecdsa_key_t *key2 = NULL;
- if ((err = hal_ecdsa_key_from_der(&key2, keybuf2, sizeof(keybuf2), keyder, keyder_len)) != HAL_OK)
- return printf("hal_ecdsa_key_from_der() failed: %s\n", hal_error_string(err)), 0;
+ if ((err = hal_ecdsa_private_key_from_der(&key2, keybuf2, sizeof(keybuf2), der, der_len)) != HAL_OK)
+ return printf("hal_ecdsa_private_key_from_der() failed: %s\n", hal_error_string(err)), 0;
if (memcmp(key1, key2, hal_ecdsa_key_t_size) != 0)
return printf("Private key mismatch after read/write cycle\n"), 0;
@@ -150,13 +167,13 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
uint8_t sig[tc->sig_len + 4];
size_t sig_len;
- if ((err = hal_ecdsa_sign(NULL, key1, tc->H, tc->H_len, sig, &sig_len, sizeof(sig), HAL_ECDSA_SIGNATURE_FORMAT_ASN1)) != HAL_OK)
+ if ((err = hal_ecdsa_sign(NULL, key1, tc->H, tc->H_len, sig, &sig_len, sizeof(sig))) != HAL_OK)
return printf("hal_ecdsa_sign() failed: %s\n", hal_error_string(err)), 0;
if (sig_len != tc->sig_len || memcmp(sig, tc->sig, tc->sig_len) != 0)
return printf("Signature mismatch\n"), 0;
- if ((err = hal_ecdsa_verify(NULL, key2, tc->H, tc->H_len, sig, sig_len, HAL_ECDSA_SIGNATURE_FORMAT_ASN1)) != HAL_OK)
+ if ((err = hal_ecdsa_verify(NULL, key2, tc->H, tc->H_len, sig, sig_len)) != HAL_OK)
return printf("hal_ecdsa_verify(private) failed: %s\n", hal_error_string(err)), 0;
hal_ecdsa_key_clear(key2);
@@ -176,7 +193,7 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
tc->Qx, tc->Qx_len, tc->Qy, tc->Qy_len)) != HAL_OK)
return printf("hal_ecdsa_load_public() failed: %s\n", hal_error_string(err)), 0;
- if ((err = hal_ecdsa_verify(NULL, key2, tc->H, tc->H_len, sig, sig_len, HAL_ECDSA_SIGNATURE_FORMAT_ASN1)) != HAL_OK)
+ if ((err = hal_ecdsa_verify(NULL, key2, tc->H, tc->H_len, sig, sig_len)) != HAL_OK)
return printf("hal_ecdsa_verify(public) failed: %s\n", hal_error_string(err)), 0;
uint8_t point[hal_ecdsa_key_to_ecpoint_len(key1)];
@@ -192,7 +209,36 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
return printf("hal_ecdsa_key_from_point() failed: %s\n", hal_error_string(err)), 0;
if (memcmp(key1, key2, hal_ecdsa_key_t_size) != 0)
- return printf("Public key mismatch after read/write cycle\n"), 0;
+ return printf("Public key mismatch after first read/write cycle\n"), 0;
+
+ hal_ecdsa_key_clear(key2);
+ key2 = NULL;
+
+ err = hal_ecdsa_public_key_to_der(key1, der, &der_len, sizeof(der));
+
+ snprintf(fn, sizeof(fn), "test-ecdsa-public-key-p%u.der", (unsigned) tc->d_len * 8);
+
+ if ((f = fopen(fn, "wb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
+
+ if (fwrite(der, der_len, 1, f) != 1)
+ return printf("Length mismatch writing %s\n", fn), 0;
+
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
+
+ /* Deferred error from hal_ecdsa_public_key_to_der() */
+ if (err != HAL_OK)
+ return printf("hal_ecdsa_public_key_to_der() failed: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_ecdsa_public_key_from_der(&key2, keybuf2, sizeof(keybuf2), der, der_len)) != HAL_OK)
+ return printf("hal_ecdsa_public_key_from_der() failed: %s\n", hal_error_string(err)), 0;
+
+ if (memcmp(key1, key2, hal_ecdsa_key_t_size) != 0)
+ return printf("Public key mismatch after second read/write cycle\n"), 0;
+
+ hal_ecdsa_key_clear(key1);
+ hal_ecdsa_key_clear(key2);
return 1;
}
@@ -203,7 +249,7 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
* Run one keygen/sign/verify test with a newly generated key.
*/
-static int test_keygen_sign_verify(const hal_ecdsa_curve_t curve)
+static int test_keygen_sign_verify(const hal_curve_name_t curve)
{
const hal_hash_descriptor_t *hash_descriptor = NULL;
@@ -213,17 +259,17 @@ static int test_keygen_sign_verify(const hal_ecdsa_curve_t curve)
switch (curve) {
- case HAL_ECDSA_CURVE_P256:
+ case HAL_CURVE_P256:
printf("ECDSA P-256 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha256;
break;
- case HAL_ECDSA_CURVE_P384:
+ case HAL_CURVE_P384:
printf("ECDSA P-384 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha384;
break;
- case HAL_ECDSA_CURVE_P521:
+ case HAL_CURVE_P521:
printf("ECDSA P-521 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha512;
break;
@@ -263,13 +309,12 @@ static int test_keygen_sign_verify(const hal_ecdsa_curve_t curve)
printf("Signing\n");
if ((err = hal_ecdsa_sign(NULL, key, hashbuf, sizeof(hashbuf),
- sigbuf, &siglen, sizeof(sigbuf), HAL_ECDSA_SIGNATURE_FORMAT_ASN1)) != HAL_OK)
+ sigbuf, &siglen, sizeof(sigbuf))) != HAL_OK)
return printf("hal_ecdsa_sign() failed: %s\n", hal_error_string(err)), 0;
printf("Verifying\n");
- if ((err = hal_ecdsa_verify(NULL, key, hashbuf, sizeof(hashbuf),
- sigbuf, siglen, HAL_ECDSA_SIGNATURE_FORMAT_ASN1)) != HAL_OK)
+ if ((err = hal_ecdsa_verify(NULL, key, hashbuf, sizeof(hashbuf), sigbuf, siglen)) != HAL_OK)
return printf("hal_ecdsa_verify() failed: %s\n", hal_error_string(err)), 0;
return 1;
@@ -339,12 +384,12 @@ int main(int argc, char *argv[])
*/
if (csprng_core != NULL && sha256_core != NULL) {
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P256));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P256));
}
if (csprng_core != NULL && sha512_core != NULL) {
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P384));
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P521));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P384));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P521));
}
return !ok;
diff --git a/tests/test-ecdsa.h b/tests/test-ecdsa.h
index ca51858..9fafe18 100644
--- a/tests/test-ecdsa.h
+++ b/tests/test-ecdsa.h
@@ -89,13 +89,13 @@ static const uint8_t p256_s[] = { /* 32 bytes */
0x92, 0xdb, 0xea, 0xa1, 0xaf, 0x2b, 0xc3, 0x67
};
-static const uint8_t p256_sig[] = { /* 70 bytes */
- 0x30, 0x44, 0x02, 0x20, 0x72, 0x14, 0xbc, 0x96, 0x47, 0x16, 0x0b, 0xbd,
- 0x39, 0xff, 0x2f, 0x80, 0x53, 0x3f, 0x5d, 0xc6, 0xdd, 0xd7, 0x0d, 0xdf,
- 0x86, 0xbb, 0x81, 0x56, 0x61, 0xe8, 0x05, 0xd5, 0xd4, 0xe6, 0xf2, 0x7c,
- 0x02, 0x20, 0x7d, 0x1f, 0xf9, 0x61, 0x98, 0x0f, 0x96, 0x1b, 0xda, 0xa3,
- 0x23, 0x3b, 0x62, 0x09, 0xf4, 0x01, 0x33, 0x17, 0xd3, 0xe3, 0xf9, 0xe1,
- 0x49, 0x35, 0x92, 0xdb, 0xea, 0xa1, 0xaf, 0x2b, 0xc3, 0x67
+static const uint8_t p256_sig[] = { /* 64 bytes */
+ 0x72, 0x14, 0xbc, 0x96, 0x47, 0x16, 0x0b, 0xbd, 0x39, 0xff, 0x2f, 0x80,
+ 0x53, 0x3f, 0x5d, 0xc6, 0xdd, 0xd7, 0x0d, 0xdf, 0x86, 0xbb, 0x81, 0x56,
+ 0x61, 0xe8, 0x05, 0xd5, 0xd4, 0xe6, 0xf2, 0x7c, 0x7d, 0x1f, 0xf9, 0x61,
+ 0x98, 0x0f, 0x96, 0x1b, 0xda, 0xa3, 0x23, 0x3b, 0x62, 0x09, 0xf4, 0x01,
+ 0x33, 0x17, 0xd3, 0xe3, 0xf9, 0xe1, 0x49, 0x35, 0x92, 0xdb, 0xea, 0xa1,
+ 0xaf, 0x2b, 0xc3, 0x67
};
static const uint8_t p256_u1[] = { /* 32 bytes */
@@ -223,16 +223,15 @@ static const uint8_t p384_s[] = { /* 48 bytes */
0x67, 0xad, 0xad, 0xf1, 0x68, 0xeb, 0xbe, 0x80, 0x37, 0x94, 0xa4, 0x02
};
-static const uint8_t p384_sig[] = { /* 103 bytes */
- 0x30, 0x65, 0x02, 0x31, 0x00, 0xa0, 0xc2, 0x7e, 0xc8, 0x93, 0x09, 0x2d,
- 0xea, 0x1e, 0x1b, 0xd2, 0xcc, 0xfe, 0xd3, 0xcf, 0x94, 0x5c, 0x81, 0x34,
- 0xed, 0x0c, 0x9f, 0x81, 0x31, 0x1a, 0x0f, 0x4a, 0x05, 0x94, 0x2d, 0xb8,
- 0xdb, 0xed, 0x8d, 0xd5, 0x9f, 0x26, 0x74, 0x71, 0xd5, 0x46, 0x2a, 0xa1,
- 0x4f, 0xe7, 0x2d, 0xe8, 0x56, 0x02, 0x30, 0x20, 0xab, 0x3f, 0x45, 0xb7,
- 0x4f, 0x10, 0xb6, 0xe1, 0x1f, 0x96, 0xa2, 0xc8, 0xeb, 0x69, 0x4d, 0x20,
- 0x6b, 0x9d, 0xda, 0x86, 0xd3, 0xc7, 0xe3, 0x31, 0xc2, 0x6b, 0x22, 0xc9,
- 0x87, 0xb7, 0x53, 0x77, 0x26, 0x57, 0x76, 0x67, 0xad, 0xad, 0xf1, 0x68,
- 0xeb, 0xbe, 0x80, 0x37, 0x94, 0xa4, 0x02
+static const uint8_t p384_sig[] = { /* 96 bytes */
+ 0xa0, 0xc2, 0x7e, 0xc8, 0x93, 0x09, 0x2d, 0xea, 0x1e, 0x1b, 0xd2, 0xcc,
+ 0xfe, 0xd3, 0xcf, 0x94, 0x5c, 0x81, 0x34, 0xed, 0x0c, 0x9f, 0x81, 0x31,
+ 0x1a, 0x0f, 0x4a, 0x05, 0x94, 0x2d, 0xb8, 0xdb, 0xed, 0x8d, 0xd5, 0x9f,
+ 0x26, 0x74, 0x71, 0xd5, 0x46, 0x2a, 0xa1, 0x4f, 0xe7, 0x2d, 0xe8, 0x56,
+ 0x20, 0xab, 0x3f, 0x45, 0xb7, 0x4f, 0x10, 0xb6, 0xe1, 0x1f, 0x96, 0xa2,
+ 0xc8, 0xeb, 0x69, 0x4d, 0x20, 0x6b, 0x9d, 0xda, 0x86, 0xd3, 0xc7, 0xe3,
+ 0x31, 0xc2, 0x6b, 0x22, 0xc9, 0x87, 0xb7, 0x53, 0x77, 0x26, 0x57, 0x76,
+ 0x67, 0xad, 0xad, 0xf1, 0x68, 0xeb, 0xbe, 0x80, 0x37, 0x94, 0xa4, 0x02
};
static const uint8_t p384_u1[] = { /* 48 bytes */
@@ -264,7 +263,7 @@ static const uint8_t p384_w[] = { /* 48 bytes */
};
typedef struct {
- hal_ecdsa_curve_t curve;
+ hal_curve_name_t curve;
const uint8_t * H; size_t H_len;
const uint8_t * M; size_t M_len;
const uint8_t * Qx; size_t Qx_len;
@@ -286,7 +285,7 @@ typedef struct {
} ecdsa_tc_t;
static const ecdsa_tc_t ecdsa_tc[] = {
- { HAL_ECDSA_CURVE_P256,
+ { HAL_CURVE_P256,
p256_H, sizeof(p256_H),
p256_M, sizeof(p256_M),
p256_Qx, sizeof(p256_Qx),
@@ -306,7 +305,7 @@ static const ecdsa_tc_t ecdsa_tc[] = {
p256_v, sizeof(p256_v),
p256_w, sizeof(p256_w),
},
- { HAL_ECDSA_CURVE_P384,
+ { HAL_CURVE_P384,
p384_H, sizeof(p384_H),
p384_M, sizeof(p384_M),
p384_Qx, sizeof(p384_Qx),
diff --git a/tests/test-ecdsa.py b/tests/test-ecdsa.py
index 1ecfef9..efd96e3 100644
--- a/tests/test-ecdsa.py
+++ b/tests/test-ecdsa.py
@@ -50,38 +50,31 @@ from pyasn1.codec.der.decoder import decode as DER_Decode
wrapper = TextWrapper(width = 78, initial_indent = " " * 2, subsequent_indent = " " * 2)
-def long_to_bytes(l):
+def long_to_bytes(number, order):
#
# This is just plain nasty.
#
- s = "%x" % l
- return ("0" + s if len(s) & 1 else s).decode("hex")
+ s = "%x" % number
+ s = ("0" * (order/8 - len(s))) + s
+ return s.decode("hex")
-def bytes_to_bits(b):
+def bytes_to_bits(bytes):
#
# This, on the other hand, is not just plain nasty, this is fancy nasty.
# This is nasty with raisins in it.
#
- bits = bin(long(b.encode("hex"), 16))[2:]
- if len(bits) % 8:
- bits = ("0" * (8 - len(bits) % 8)) + bits
- return tuple(int(i) for i in bits)
+ s = bin(long(bytes.encode("hex"), 16))[2:]
+ if len(s) % 8:
+ s = ("0" * (8 - len(s) % 8)) + s
+ return tuple(int(i) for i in s)
###
-class ECDSA_Sig_Value(Sequence):
- componentType = NamedTypes(
- NamedType("r", Integer()),
- NamedType("s", Integer()))
-
-def encode_sig(r, s):
- sig = ECDSA_Sig_Value()
- sig["r"] = r
- sig["s"] = s
- return DER_Encode(sig)
+def encode_sig(r, s, order):
+ return long_to_bytes(r, order) + long_to_bytes(s, order)
-p256_sig = encode_sig(p256_r, p256_s)
-p384_sig = encode_sig(p384_r, p384_s)
+p256_sig = encode_sig(p256_r, p256_s, 256)
+p384_sig = encode_sig(p384_r, p384_s, 384)
###
@@ -93,9 +86,9 @@ class ECPrivateKey(Sequence):
OptionalNamedType("parameters", ObjectIdentifier().subtype(explicitTag = Tag(tagClassContext, tagFormatSimple, 0))),
OptionalNamedType("publicKey", BitString().subtype(explicitTag = Tag(tagClassContext, tagFormatSimple, 1))))
-def encode_key(d, Qx, Qy, oid):
- private_key = long_to_bytes(d)
- public_key = bytes_to_bits(chr(0x04) + long_to_bytes(Qx) + long_to_bytes(Qy))
+def encode_key(d, Qx, Qy, order, oid):
+ private_key = long_to_bytes(d, order)
+ public_key = bytes_to_bits(chr(0x04) + long_to_bytes(Qx, order) + long_to_bytes(Qy, order))
parameters = oid
key = ECPrivateKey()
key["version"] = 1
@@ -104,8 +97,8 @@ def encode_key(d, Qx, Qy, oid):
key["publicKey"] = public_key
return DER_Encode(key)
-p256_key = encode_key(p256_d, p256_Qx, p256_Qy, "1.2.840.10045.3.1.7")
-p384_key = encode_key(p384_d, p384_Qx, p384_Qy, "1.3.132.0.34")
+p256_key = encode_key(p256_d, p256_Qx, p256_Qy, 256, "1.2.840.10045.3.1.7")
+p384_key = encode_key(p384_d, p384_Qx, p384_Qy, 384, "1.3.132.0.34")
###
@@ -125,11 +118,12 @@ for name in dir():
vars = sorted(vars)
for curve in curves:
+ order = int(curve[1:])
for var in vars:
name = curve + "_" + var
value = globals().get(name, None)
if isinstance(value, (int, long)):
- value = long_to_bytes(value)
+ value = long_to_bytes(value, order)
if value is not None:
print
print "static const uint8_t %s[] = { /* %d bytes */" % (name, len(value))
@@ -138,14 +132,14 @@ for curve in curves:
print
print "typedef struct {"
-print " hal_ecdsa_curve_t curve;"
+print " hal_curve_name_t curve;"
for var in vars:
print " const uint8_t *%8s; size_t %8s_len;" % (var, var)
print "} ecdsa_tc_t;"
print
print "static const ecdsa_tc_t ecdsa_tc[] = {"
for curve in curves:
- print " { HAL_ECDSA_CURVE_%s," % curve.upper()
+ print " { HAL_CURVE_%s," % curve.upper()
for var in vars:
name = curve + "_" + var
if name in globals():
diff --git a/tests/test-hash.c b/tests/test-hash.c
index 0cceb8a..e8c6a01 100644
--- a/tests/test-hash.c
+++ b/tests/test-hash.c
@@ -534,9 +534,6 @@ static int _test_hash(const hal_core_t *core,
const uint8_t * const result, const size_t result_len,
const char * const label)
{
- if (core == NULL)
- return 1;
-
uint8_t statebuf[512], digest[512];
hal_hash_state_t *state = NULL;
hal_error_t err;
@@ -586,9 +583,6 @@ static int _test_hmac(const hal_core_t *core,
const uint8_t * const result, const size_t result_len,
const char * const label)
{
- if (core == NULL)
- return 1;
-
uint8_t statebuf[1024], digest[512];
hal_hmac_state_t *state = NULL;
hal_error_t err;
diff --git a/tests/test-rpc_hash.c b/tests/test-rpc_hash.c
new file mode 100644
index 0000000..ded440f
--- /dev/null
+++ b/tests/test-rpc_hash.c
@@ -0,0 +1,700 @@
+/*
+ * test-rpc_hash.c
+ * ---------------
+ * Test code for RPC interface to Cryptech hash cores.
+ *
+ * Authors: Rob Austein, Paul Selkirk
+ * Copyright (c) 2015-2016, NORDUnet A/S
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <hal.h>
+
+#warning This is wrong, nothing outside libhal itself should include hal_internal.h
+#include <hal_internal.h>
+
+/* Usual NIST sample messages. */
+
+/* "abc" */
+static const uint8_t nist_512_single[] = { /* 3 bytes */
+ 0x61, 0x62, 0x63
+};
+
+static const uint8_t sha1_single_digest[] = { /* 20 bytes */
+ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71,
+ 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d
+};
+
+static const uint8_t sha256_single_digest[] = { /* 32 bytes */
+ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
+ 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
+};
+
+/* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
+static const uint8_t nist_512_double[] = { /* 56 bytes */
+ 0x61, 0x62, 0x63, 0x64, 0x62, 0x63, 0x64, 0x65, 0x63, 0x64, 0x65, 0x66,
+ 0x64, 0x65, 0x66, 0x67, 0x65, 0x66, 0x67, 0x68, 0x66, 0x67, 0x68, 0x69,
+ 0x67, 0x68, 0x69, 0x6a, 0x68, 0x69, 0x6a, 0x6b, 0x69, 0x6a, 0x6b, 0x6c,
+ 0x6a, 0x6b, 0x6c, 0x6d, 0x6b, 0x6c, 0x6d, 0x6e, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x6d, 0x6e, 0x6f, 0x70, 0x6e, 0x6f, 0x70, 0x71
+};
+
+static const uint8_t sha1_double_digest[] = { /* 20 bytes */
+ 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, 0x4a, 0xa1,
+ 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1
+};
+
+static const uint8_t sha256_double_digest[] = { /* 32 bytes */
+ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93,
+ 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
+};
+
+/* "abc" */
+static const uint8_t nist_1024_single[] = { /* 3 bytes */
+ 0x61, 0x62, 0x63
+};
+
+static const uint8_t sha512_224_single_digest[] = { /* 28 bytes */
+ 0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54, 0xda, 0xae, 0x75, 0x30,
+ 0x46, 0x08, 0x42, 0xe2, 0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4,
+ 0x3e, 0x89, 0x24, 0xaa
+};
+
+static const uint8_t sha512_256_single_digest[] = { /* 32 bytes */
+ 0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9, 0x9b, 0x2e, 0x29, 0xb7,
+ 0x6b, 0x4c, 0x7d, 0xab, 0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46,
+ 0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23
+};
+
+static const uint8_t sha384_single_digest[] = { /* 48 bytes */
+ 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69,
+ 0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+ 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b,
+ 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
+};
+
+static const uint8_t sha512_single_digest[] = { /* 64 bytes */
+ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
+ 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+ 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
+ 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
+ 0xa5, 0x4c, 0xa4, 0x9f
+};
+
+/* "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" */
+static const uint8_t nist_1024_double[] = { /* 112 bytes */
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x62, 0x63, 0x64, 0x65,
+ 0x66, 0x67, 0x68, 0x69, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x6b, 0x6c, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x68, 0x69, 0x6a, 0x6b,
+ 0x6c, 0x6d, 0x6e, 0x6f, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x6b, 0x6c, 0x6d, 0x6e,
+ 0x6f, 0x70, 0x71, 0x72, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
+ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x6e, 0x6f, 0x70, 0x71,
+ 0x72, 0x73, 0x74, 0x75
+};
+
+static const uint8_t sha512_224_double_digest[] = { /* 28 bytes */
+ 0x23, 0xfe, 0xc5, 0xbb, 0x94, 0xd6, 0x0b, 0x23, 0x30, 0x81, 0x92, 0x64,
+ 0x0b, 0x0c, 0x45, 0x33, 0x35, 0xd6, 0x64, 0x73, 0x4f, 0xe4, 0x0e, 0x72,
+ 0x68, 0x67, 0x4a, 0xf9
+};
+
+static const uint8_t sha512_256_double_digest[] = { /* 32 bytes */
+ 0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8, 0x40, 0xda, 0x39, 0x88,
+ 0x12, 0x1d, 0x31, 0xbe, 0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14,
+ 0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a
+};
+
+static const uint8_t sha384_double_digest[] = { /* 48 bytes */
+ 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 0x3d, 0x19, 0x2f, 0xc7,
+ 0x82, 0xcd, 0x1b, 0x47, 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+ 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, 0xfc, 0xc7, 0xc7, 0x1a,
+ 0x55, 0x7e, 0x2d, 0xb9, 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39
+};
+
+static const uint8_t sha512_double_digest[] = { /* 64 bytes */
+ 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28,
+ 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+ 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50, 0x1d, 0x28, 0x9e,
+ 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+ 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b,
+ 0x87, 0x4b, 0xe9, 0x09
+};
+
+/* HMAC-SHA-1 test cases from RFC 2202. */
+
+static const uint8_t hmac_sha1_tc_1_key[] = { /* 20 bytes */
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+};
+
+/* 'Hi There' */
+static const uint8_t hmac_sha1_tc_1_data[] = { /* 8 bytes */
+ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
+};
+
+static const uint8_t hmac_sha1_tc_1_result_sha1[] = { /* 20 bytes */
+ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6,
+ 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00
+};
+
+/* 'Jefe' */
+static const uint8_t hmac_sha1_tc_2_key[] = { /* 4 bytes */
+ 0x4a, 0x65, 0x66, 0x65
+};
+
+/* 'what do ya want for nothing?' */
+static const uint8_t hmac_sha1_tc_2_data[] = { /* 28 bytes */
+ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77,
+ 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x3f
+};
+
+static const uint8_t hmac_sha1_tc_2_result_sha1[] = { /* 20 bytes */
+ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5,
+ 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79
+};
+
+static const uint8_t hmac_sha1_tc_3_key[] = { /* 20 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+static const uint8_t hmac_sha1_tc_3_data[] = { /* 50 bytes */
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd
+};
+
+static const uint8_t hmac_sha1_tc_3_result_sha1[] = { /* 20 bytes */
+ 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4,
+ 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3
+};
+
+static const uint8_t hmac_sha1_tc_4_key[] = { /* 25 bytes */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19
+};
+
+static const uint8_t hmac_sha1_tc_4_data[] = { /* 50 bytes */
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd
+};
+
+static const uint8_t hmac_sha1_tc_4_result_sha1[] = { /* 20 bytes */
+ 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9,
+ 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda
+};
+
+static const uint8_t hmac_sha1_tc_5_key[] = { /* 20 bytes */
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
+};
+
+/* 'Test With Truncation' */
+static const uint8_t hmac_sha1_tc_5_data[] = { /* 20 bytes */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x57, 0x69, 0x74, 0x68, 0x20, 0x54, 0x72,
+ 0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e
+};
+
+static const uint8_t hmac_sha1_tc_5_result_sha1[] = { /* 20 bytes */
+ 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1,
+ 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04
+};
+
+static const uint8_t hmac_sha1_tc_6_key[] = { /* 80 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+/* 'Test Using Larger Than Block-Size Key - Hash Key First' */
+static const uint8_t hmac_sha1_tc_6_data[] = { /* 54 bytes */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c,
+ 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x4b, 0x65,
+ 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+ 0x20, 0x46, 0x69, 0x72, 0x73, 0x74
+};
+
+static const uint8_t hmac_sha1_tc_6_result_sha1[] = { /* 20 bytes */
+ 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37,
+ 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12
+};
+
+static const uint8_t hmac_sha1_tc_7_key[] = { /* 80 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+/* 'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data' */
+static const uint8_t hmac_sha1_tc_7_data[] = { /* 73 bytes */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c,
+ 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x4b, 0x65,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72,
+ 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74, 0x61
+};
+
+static const uint8_t hmac_sha1_tc_7_result_sha1[] = { /* 20 bytes */
+ 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7,
+ 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91
+};
+
+/* HMAC-SHA-2 test cases from RFC 4231. */
+
+static const uint8_t hmac_sha2_tc_1_key[] = { /* 20 bytes */
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+};
+
+/* 'Hi There' */
+static const uint8_t hmac_sha2_tc_1_data[] = { /* 8 bytes */
+ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
+};
+
+static const uint8_t hmac_sha2_tc_1_result_sha256[] = { /* 32 bytes */
+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce,
+ 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
+ 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
+};
+
+static const uint8_t hmac_sha2_tc_1_result_sha384[] = { /* 48 bytes */
+ 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4,
+ 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+ 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9,
+ 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6
+};
+
+static const uint8_t hmac_sha2_tc_1_result_sha512[] = { /* 64 bytes */
+ 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24,
+ 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+ 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7,
+ 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+ 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20,
+ 0x3a, 0x12, 0x68, 0x54
+};
+
+/* 'Jefe' */
+static const uint8_t hmac_sha2_tc_2_key[] = { /* 4 bytes */
+ 0x4a, 0x65, 0x66, 0x65
+};
+
+/* 'what do ya want for nothing?' */
+static const uint8_t hmac_sha2_tc_2_data[] = { /* 28 bytes */
+ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77,
+ 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x3f
+};
+
+static const uint8_t hmac_sha2_tc_2_result_sha256[] = { /* 32 bytes */
+ 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26,
+ 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+ 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
+};
+
+static const uint8_t hmac_sha2_tc_2_result_sha384[] = { /* 48 bytes */
+ 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2,
+ 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+ 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca,
+ 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49
+};
+
+static const uint8_t hmac_sha2_tc_2_result_sha512[] = { /* 64 bytes */
+ 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7,
+ 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+ 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75,
+ 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+ 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a,
+ 0x38, 0xbc, 0xe7, 0x37
+};
+
+static const uint8_t hmac_sha2_tc_3_key[] = { /* 20 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+static const uint8_t hmac_sha2_tc_3_data[] = { /* 50 bytes */
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd
+};
+
+static const uint8_t hmac_sha2_tc_3_result_sha256[] = { /* 32 bytes */
+ 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb,
+ 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
+ 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe
+};
+
+static const uint8_t hmac_sha2_tc_3_result_sha384[] = { /* 48 bytes */
+ 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0,
+ 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
+ 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d,
+ 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27
+};
+
+static const uint8_t hmac_sha2_tc_3_result_sha512[] = { /* 64 bytes */
+ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75,
+ 0x6c, 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
+ 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82,
+ 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
+ 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59,
+ 0xe1, 0x32, 0x92, 0xfb
+};
+
+static const uint8_t hmac_sha2_tc_4_key[] = { /* 25 bytes */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19
+};
+
+static const uint8_t hmac_sha2_tc_4_data[] = { /* 50 bytes */
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd
+};
+
+static const uint8_t hmac_sha2_tc_4_result_sha256[] = { /* 32 bytes */
+ 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98,
+ 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
+ 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b
+};
+
+static const uint8_t hmac_sha2_tc_4_result_sha384[] = { /* 48 bytes */
+ 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62,
+ 0x90, 0xaf, 0x6c, 0xa7, 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
+ 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, 0x68, 0x01, 0xdd, 0x23,
+ 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb
+};
+
+static const uint8_t hmac_sha2_tc_4_result_sha512[] = { /* 64 bytes */
+ 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5,
+ 0xf6, 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
+ 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9, 0x1c, 0xa5, 0xc1,
+ 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
+ 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb,
+ 0x10, 0xa2, 0x98, 0xdd
+};
+
+/* Skipping HMAC-SHA-2 test case 5. */
+
+static const uint8_t hmac_sha2_tc_6_key[] = { /* 131 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+/* 'Test Using Larger Than Block-Size Key - Hash Key First' */
+static const uint8_t hmac_sha2_tc_6_data[] = { /* 54 bytes */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c,
+ 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x4b, 0x65,
+ 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+ 0x20, 0x46, 0x69, 0x72, 0x73, 0x74
+};
+
+static const uint8_t hmac_sha2_tc_6_result_sha256[] = { /* 32 bytes */
+ 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa,
+ 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
+ 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
+};
+
+static const uint8_t hmac_sha2_tc_6_result_sha384[] = { /* 48 bytes */
+ 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a,
+ 0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+ 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab,
+ 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52
+};
+
+static const uint8_t hmac_sha2_tc_6_result_sha512[] = { /* 64 bytes */
+ 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1,
+ 0xdd, 0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+ 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37,
+ 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+ 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98,
+ 0x5d, 0x78, 0x65, 0x98
+};
+
+static const uint8_t hmac_sha2_tc_7_key[] = { /* 131 bytes */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
+};
+
+/* 'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.' */
+static const uint8_t hmac_sha2_tc_7_data[] = { /* 152 bytes */
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65,
+ 0x73, 0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+ 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e,
+ 0x20, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x61, 0x73,
+ 0x68, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
+ 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e
+};
+
+static const uint8_t hmac_sha2_tc_7_result_sha256[] = { /* 32 bytes */
+ 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc,
+ 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
+ 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2
+};
+
+static const uint8_t hmac_sha2_tc_7_result_sha384[] = { /* 48 bytes */
+ 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25,
+ 0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+ 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31,
+ 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e
+};
+
+static const uint8_t hmac_sha2_tc_7_result_sha512[] = { /* 64 bytes */
+ 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9,
+ 0x6e, 0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+ 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac,
+ 0x3c, 0x49, 0x82, 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+ 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40,
+ 0xfa, 0x8c, 0x6a, 0x58
+};
+
+static int _test_hash(const hal_digest_algorithm_t alg,
+ const uint8_t * const data, const size_t data_len,
+ const uint8_t * const result, const size_t result_len,
+ const char * const label)
+{
+ uint8_t digest[512];
+ hal_error_t err;
+
+ assert(data != NULL && result != NULL && label != NULL);
+ assert(result_len <= sizeof(digest));
+
+ printf("Starting %s test\n", label);
+
+ hal_client_handle_t client = {0};
+ hal_session_handle_t session = {0};
+ hal_hash_handle_t hash;
+
+ if ((err = hal_rpc_hash_initialize(client, session, &hash, alg, NULL, 0)) != HAL_OK) {
+ printf("Failed while initializing hash: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ if ((err = hal_rpc_hash_update(hash, data, data_len)) != HAL_OK) {
+ printf("Failed while updating hash: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ if ((err = hal_rpc_hash_finalize(hash, digest, sizeof(digest))) != HAL_OK) {
+ printf("Failed while finalizing hash: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ printf("Comparing result with known value\n");
+ if (memcmp(result, digest, result_len)) {
+ size_t i;
+ printf("MISMATCH\nExpected:");
+ for (i = 0; i < result_len; i++)
+ printf(" %02x", result[i]);
+ printf("\nGot: ");
+ for (i = 0; i < result_len; i++)
+ printf(" %02x", digest[i]);
+ printf("\n");
+ return 0;
+ }
+
+ printf("OK\n");
+ return 1;
+}
+
+static int _test_hmac(const hal_digest_algorithm_t alg,
+ const uint8_t * const key, const size_t key_len,
+ const uint8_t * const data, const size_t data_len,
+ const uint8_t * const result, const size_t result_len,
+ const char * const label)
+{
+ uint8_t digest[512];
+ hal_error_t err;
+
+ assert(data != NULL && result != NULL && label != NULL);
+ assert(result_len <= sizeof(digest));
+
+ printf("Starting %s test\n", label);
+
+ hal_client_handle_t client = {0};
+ hal_session_handle_t session = {0};
+ hal_hash_handle_t hash;
+
+ if ((err = hal_rpc_hash_initialize(client, session, &hash, alg, key, key_len)) != HAL_OK) {
+ printf("Failed while initializing HMAC: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ if ((err = hal_rpc_hash_update(hash, data, data_len)) != HAL_OK) {
+ printf("Failed while updating HMAC: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ if ((err = hal_rpc_hash_finalize(hash, digest, sizeof(digest))) != HAL_OK) {
+ printf("Failed while finalizing HMAC: %s\n", hal_error_string(err));
+ return 0;
+ }
+
+ printf("Comparing result with known value\n");
+ if (memcmp(result, digest, result_len)) {
+ size_t i;
+ printf("MISMATCH\nExpected:");
+ for (i = 0; i < result_len; i++)
+ printf(" %02x", result[i]);
+ printf("\nGot: ");
+ for (i = 0; i < result_len; i++)
+ printf(" %02x", digest[i]);
+ printf("\n");
+ return 0;
+ }
+
+ printf("OK\n");
+ return 1;
+}
+
+#define test_hash(_alg_, _data_, _result_, _label_) \
+ _test_hash(_alg_, _data_, sizeof(_data_), _result_, sizeof(_result_), _label_)
+
+#define test_hmac(_alg_, _key_, _data_, _result_, _label_) \
+ _test_hmac(_alg_, _key_, sizeof(_key_), _data_, sizeof(_data_), _result_, sizeof(_result_), _label_)
+
+int main (int argc, char *argv[])
+{
+// rpc_client_init(RPC_LOCAL);
+ rpc_client_init(RPC_REMOTE);
+
+ int ok = 1;
+
+ ok &= test_hash(hal_digest_algorithm_sha1, nist_512_single, sha1_single_digest, "SHA-1 single block");
+ ok &= test_hash(hal_digest_algorithm_sha1, nist_512_double, sha1_double_digest, "SHA-1 double block");
+
+ ok &= test_hash(hal_digest_algorithm_sha256, nist_512_single, sha256_single_digest, "SHA-256 single block");
+ ok &= test_hash(hal_digest_algorithm_sha256, nist_512_double, sha256_double_digest, "SHA-256 double block");
+
+ ok &= test_hash(hal_digest_algorithm_sha512_224, nist_1024_single, sha512_224_single_digest, "SHA-512/224 single block");
+ ok &= test_hash(hal_digest_algorithm_sha512_224, nist_1024_double, sha512_224_double_digest, "SHA-512/224 double block");
+
+ ok &= test_hash(hal_digest_algorithm_sha512_256, nist_1024_single, sha512_256_single_digest, "SHA-512/256 single block");
+ ok &= test_hash(hal_digest_algorithm_sha512_256, nist_1024_double, sha512_256_double_digest, "SHA-512/256 double block");
+
+ ok &= test_hash(hal_digest_algorithm_sha384, nist_1024_single, sha384_single_digest, "SHA-384 single block");
+ ok &= test_hash(hal_digest_algorithm_sha384, nist_1024_double, sha384_double_digest, "SHA-384 double block");
+
+ ok &= test_hash(hal_digest_algorithm_sha512, nist_1024_single, sha512_single_digest, "SHA-512 single block");
+ ok &= test_hash(hal_digest_algorithm_sha512, nist_1024_double, sha512_double_digest, "SHA-512 double block");
+
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_1_key, hmac_sha1_tc_1_data, hmac_sha1_tc_1_result_sha1, "HMAC-SHA-1 test case 1");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_2_key, hmac_sha1_tc_2_data, hmac_sha1_tc_2_result_sha1, "HMAC-SHA-1 test case 2");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_3_key, hmac_sha1_tc_3_data, hmac_sha1_tc_3_result_sha1, "HMAC-SHA-1 test case 3");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_4_key, hmac_sha1_tc_4_data, hmac_sha1_tc_4_result_sha1, "HMAC-SHA-1 test case 4");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_5_key, hmac_sha1_tc_5_data, hmac_sha1_tc_5_result_sha1, "HMAC-SHA-1 test case 5");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_6_key, hmac_sha1_tc_6_data, hmac_sha1_tc_6_result_sha1, "HMAC-SHA-1 test case 6");
+ ok &= test_hmac(hal_digest_algorithm_sha1, hmac_sha1_tc_7_key, hmac_sha1_tc_7_data, hmac_sha1_tc_7_result_sha1, "HMAC-SHA-1 test case 7");
+
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_1_key, hmac_sha2_tc_1_data, hmac_sha2_tc_1_result_sha256, "HMAC-SHA-256 test case 1");
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_2_key, hmac_sha2_tc_2_data, hmac_sha2_tc_2_result_sha256, "HMAC-SHA-256 test case 2");
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_3_key, hmac_sha2_tc_3_data, hmac_sha2_tc_3_result_sha256, "HMAC-SHA-256 test case 3");
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_4_key, hmac_sha2_tc_4_data, hmac_sha2_tc_4_result_sha256, "HMAC-SHA-256 test case 4");
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_6_key, hmac_sha2_tc_6_data, hmac_sha2_tc_6_result_sha256, "HMAC-SHA-256 test case 6");
+ ok &= test_hmac(hal_digest_algorithm_sha256, hmac_sha2_tc_7_key, hmac_sha2_tc_7_data, hmac_sha2_tc_7_result_sha256, "HMAC-SHA-256 test case 7");
+
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_1_key, hmac_sha2_tc_1_data, hmac_sha2_tc_1_result_sha384, "HMAC-SHA-384 test case 1");
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_2_key, hmac_sha2_tc_2_data, hmac_sha2_tc_2_result_sha384, "HMAC-SHA-384 test case 2");
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_3_key, hmac_sha2_tc_3_data, hmac_sha2_tc_3_result_sha384, "HMAC-SHA-384 test case 3");
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_4_key, hmac_sha2_tc_4_data, hmac_sha2_tc_4_result_sha384, "HMAC-SHA-384 test case 4");
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_6_key, hmac_sha2_tc_6_data, hmac_sha2_tc_6_result_sha384, "HMAC-SHA-384 test case 6");
+ ok &= test_hmac(hal_digest_algorithm_sha384, hmac_sha2_tc_7_key, hmac_sha2_tc_7_data, hmac_sha2_tc_7_result_sha384, "HMAC-SHA-384 test case 7");
+
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_1_key, hmac_sha2_tc_1_data, hmac_sha2_tc_1_result_sha512, "HMAC-SHA-512 test case 1");
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_2_key, hmac_sha2_tc_2_data, hmac_sha2_tc_2_result_sha512, "HMAC-SHA-512 test case 2");
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_3_key, hmac_sha2_tc_3_data, hmac_sha2_tc_3_result_sha512, "HMAC-SHA-512 test case 3");
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_4_key, hmac_sha2_tc_4_data, hmac_sha2_tc_4_result_sha512, "HMAC-SHA-512 test case 4");
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_6_key, hmac_sha2_tc_6_data, hmac_sha2_tc_6_result_sha512, "HMAC-SHA-512 test case 6");
+ ok &= test_hmac(hal_digest_algorithm_sha512, hmac_sha2_tc_7_key, hmac_sha2_tc_7_data, hmac_sha2_tc_7_result_sha512, "HMAC-SHA-512 test case 7");
+
+ return !ok;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/test-rpc_pkey.c b/tests/test-rpc_pkey.c
new file mode 100644
index 0000000..03404a4
--- /dev/null
+++ b/tests/test-rpc_pkey.c
@@ -0,0 +1,348 @@
+/*
+ * test-rpc_pkey.c
+ * ---------------
+ * Test code for RPC interface to Cryptech public key operations.
+ *
+ * Authors: Rob Austein, Paul Selkirk
+ * Copyright (c) 2015-2016, NORDUnet A/S
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <hal.h>
+
+#warning This is wrong, nothing outside libhal itself should include hal_internal.h
+#include <hal_internal.h>
+
+#include "test-rsa.h"
+#include "test-ecdsa.h"
+
+static inline const char *ecdsa_curve_to_string(const hal_curve_name_t curve)
+{
+ switch (curve) {
+ case HAL_CURVE_P256: return "P-256";
+ case HAL_CURVE_P384: return "P-384";
+ case HAL_CURVE_P521: return "P-521";
+ default: return "?????";
+ }
+}
+
+static int test_rsa_testvec(const rsa_tc_t * const tc)
+{
+ const hal_client_handle_t client = {0};
+ const hal_session_handle_t session = {0};
+ hal_pkey_handle_t private_key, public_key;
+ hal_error_t err;
+ size_t len;
+
+ assert(tc != NULL);
+
+ printf("Starting %lu-bit RSA test vector tests\n", (unsigned long) tc->size);
+
+ uint8_t tc_keybuf[hal_rsa_key_t_size];
+ hal_rsa_key_t *tc_key = NULL;
+
+ if ((err = hal_rsa_key_load_private(&tc_key,
+ tc_keybuf, sizeof(tc_keybuf),
+ tc->n.val, tc->n.len,
+ tc->e.val, tc->e.len,
+ tc->d.val, tc->d.len,
+ tc->p.val, tc->p.len,
+ tc->q.val, tc->q.len,
+ tc->u.val, tc->u.len,
+ tc->dP.val, tc->dP.len,
+ tc->dQ.val, tc->dQ.len)) != HAL_OK)
+ return printf("Could not load RSA private key from test vector: %s\n", hal_error_string(err)), 0;
+
+ const uint8_t private_label[] = "RSA private key", public_label[] = "RSA public key";
+
+ uint8_t private_der[hal_rsa_private_key_to_der_len(tc_key)];
+ uint8_t public_der[hal_rsa_public_key_to_der_len(tc_key)];
+
+ if ((err = hal_rsa_private_key_to_der(tc_key, private_der, &len, sizeof(private_der))) != HAL_OK)
+ return printf("Could not DER encode private key from test vector: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(private_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &private_key, HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE,
+ private_label, sizeof(private_label), private_der, sizeof(private_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load private key into RPC: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rsa_public_key_to_der(tc_key, public_der, &len, sizeof(public_der))) != HAL_OK)
+ return printf("Could not DER encode public key from test vector: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(public_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &public_key, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
+ public_label, sizeof(public_label), public_der, sizeof(public_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load public key into RPC: %s\n", hal_error_string(err)), 0;
+
+ uint8_t sig[tc->s.len];
+
+ /*
+ * Raw RSA test cases include PKCS #1.5 padding, we need to drill down to the DigestInfo.
+ */
+ assert(tc->m.len > 4 && tc->m.val[0] == 0x00 && tc->m.val[1] == 0x01 && tc->m.val[2] == 0xff);
+ const uint8_t *digestinfo = memchr(tc->m.val + 2, 0x00, tc->m.len - 2);
+ assert(digestinfo != NULL);
+ const size_t digestinfo_len = tc->m.val + tc->m.len - ++digestinfo;
+
+ if ((err = hal_rpc_pkey_sign(session, private_key, hal_hash_handle_none,
+ digestinfo, digestinfo_len, sig, &len, sizeof(sig))) != HAL_OK)
+ return printf("Could not sign: %s\n", hal_error_string(err)), 0;
+
+ if (tc->s.len != len || memcmp(sig, tc->s.val, tc->s.len) != 0)
+ return printf("MISMATCH\n"), 0;
+
+ if ((err = hal_rpc_pkey_verify(session, public_key, hal_hash_handle_none,
+ digestinfo, digestinfo_len, tc->s.val, tc->s.len)) != HAL_OK)
+ return printf("Could not verify: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(private_key)) != HAL_OK)
+ return printf("Could not delete private key: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(public_key)) != HAL_OK)
+ return printf("Could not delete public key: %s\n", hal_error_string(err)), 0;
+
+ printf("OK\n");
+ return 1;
+}
+
+static int test_ecdsa_testvec(const ecdsa_tc_t * const tc)
+{
+ const hal_client_handle_t client = {0};
+ const hal_session_handle_t session = {0};
+ hal_pkey_handle_t private_key, public_key;
+ hal_error_t err;
+ size_t len;
+
+ assert(tc != NULL);
+
+ printf("Starting ECDSA %s test vector tests\n", ecdsa_curve_to_string(tc->curve));
+
+ uint8_t tc_keybuf[hal_ecdsa_key_t_size];
+ hal_ecdsa_key_t *tc_key = NULL;
+
+ if ((err = hal_ecdsa_key_load_private(&tc_key, tc_keybuf, sizeof(tc_keybuf), tc->curve,
+ tc->Qx, tc->Qx_len, tc->Qy, tc->Qy_len,
+ tc->d, tc->d_len)) != HAL_OK)
+ return printf("Could not load ECDSA private key from test vector: %s\n", hal_error_string(err)), 0;
+
+ const uint8_t private_label[] = "ECDSA private key", public_label[] = "ECDSA public key";
+
+ uint8_t private_der[hal_ecdsa_private_key_to_der_len(tc_key)];
+ uint8_t public_der[hal_ecdsa_public_key_to_der_len(tc_key)];
+
+ if ((err = hal_ecdsa_private_key_to_der(tc_key, private_der, &len, sizeof(private_der))) != HAL_OK)
+ return printf("Could not DER encode private key from test vector: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(private_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &private_key, HAL_KEY_TYPE_EC_PRIVATE, tc->curve,
+ private_label, sizeof(private_label), private_der, sizeof(private_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load private key into RPC: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_ecdsa_public_key_to_der(tc_key, public_der, &len, sizeof(public_der))) != HAL_OK)
+ return printf("Could not DER encode public key from test vector: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(public_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &public_key, HAL_KEY_TYPE_EC_PUBLIC, tc->curve,
+ public_label, sizeof(public_label), public_der, sizeof(public_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load public key into RPC: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_verify(session, public_key, hal_hash_handle_none,
+ tc->H, tc->H_len, tc->sig, tc->sig_len)) != HAL_OK)
+ return printf("Could not verify signature from test vector: %s\n", hal_error_string(err)), 0;
+
+ uint8_t sig[tc->sig_len + 4];
+
+ if ((err = hal_rpc_pkey_sign(session, private_key, hal_hash_handle_none,
+ tc->H, tc->H_len, sig, &len, sizeof(sig))) != HAL_OK)
+ return printf("Could not sign: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_verify(session, public_key, hal_hash_handle_none,
+ tc->H, tc->H_len, sig, len)) != HAL_OK)
+ return printf("Could not verify own signature: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(private_key)) != HAL_OK)
+ return printf("Could not delete private key: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(public_key)) != HAL_OK)
+ return printf("Could not delete public key: %s\n", hal_error_string(err)), 0;
+
+ printf("OK\n");
+ return 1;
+}
+
+static int test_rsa_generate(const rsa_tc_t * const tc)
+{
+ const hal_client_handle_t client = {0};
+ const hal_session_handle_t session = {0};
+ hal_pkey_handle_t private_key, public_key;
+ hal_error_t err;
+ size_t len;
+
+ assert(tc != NULL);
+
+ printf("Starting %lu-bit RSA key generation tests\n", (unsigned long) tc->size);
+
+ const uint8_t private_label[] = "Generated RSA private key", public_label[] = "Generated RSA public key";
+
+ if ((err = hal_rpc_pkey_generate_rsa(client, session, &private_key, private_label, sizeof(private_label),
+ tc->size, tc->e.val, tc->e.len,
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not generate RSA private key: %s\n", hal_error_string(err)), 0;
+
+ uint8_t public_der[hal_rpc_pkey_get_public_key_len(private_key)];
+
+ if ((err = hal_rpc_pkey_get_public_key(private_key, public_der, &len, sizeof(public_der))) != HAL_OK)
+ return printf("Could not DER encode RPC RSA public key from RPC RSA private key: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(public_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &public_key, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
+ public_label, sizeof(public_label), public_der, sizeof(public_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load public key into RPC: %s\n", hal_error_string(err)), 0;
+
+ uint8_t sig[tc->s.len];
+
+ /*
+ * Raw RSA test cases include PKCS #1.5 padding, we need to drill down to the DigestInfo.
+ */
+ assert(tc->m.len > 4 && tc->m.val[0] == 0x00 && tc->m.val[1] == 0x01 && tc->m.val[2] == 0xff);
+ const uint8_t *digestinfo = memchr(tc->m.val + 2, 0x00, tc->m.len - 2);
+ assert(digestinfo != NULL);
+ const size_t digestinfo_len = tc->m.val + tc->m.len - ++digestinfo;
+
+ if ((err = hal_rpc_pkey_sign(session, private_key, hal_hash_handle_none,
+ digestinfo, digestinfo_len, sig, &len, sizeof(sig))) != HAL_OK)
+ return printf("Could not sign: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_verify(session, public_key, hal_hash_handle_none,
+ digestinfo, digestinfo_len, sig, len)) != HAL_OK)
+ return printf("Could not verify: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(private_key)) != HAL_OK)
+ return printf("Could not delete private key: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(public_key)) != HAL_OK)
+ return printf("Could not delete public key: %s\n", hal_error_string(err)), 0;
+
+ printf("OK\n");
+ return 1;
+}
+
+static int test_ecdsa_generate(const ecdsa_tc_t * const tc)
+{
+ const hal_client_handle_t client = {0};
+ const hal_session_handle_t session = {0};
+ hal_pkey_handle_t private_key, public_key;
+ hal_error_t err;
+ size_t len;
+
+ assert(tc != NULL);
+
+ printf("Starting ECDSA %s key generation tests\n", ecdsa_curve_to_string(tc->curve));
+
+ const uint8_t private_label[] = "Generated ECDSA private key", public_label[] = "Generated ECDSA public key";
+
+ if ((err = hal_rpc_pkey_generate_ec(client, session, &private_key,
+ private_label, sizeof(private_label),
+ tc->curve, HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not generate EC key pair: %s\n", hal_error_string(err)), 0;
+
+ uint8_t public_der[hal_rpc_pkey_get_public_key_len(private_key)];
+
+ if ((err = hal_rpc_pkey_get_public_key(private_key, public_der, &len, sizeof(public_der))) != HAL_OK)
+ return printf("Could not DER encode public key from test vector: %s\n", hal_error_string(err)), 0;
+
+ assert(len == sizeof(public_der));
+
+ if ((err = hal_rpc_pkey_load(client, session, &public_key, HAL_KEY_TYPE_EC_PUBLIC, tc->curve,
+ public_label, sizeof(public_label), public_der, sizeof(public_der),
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)) != HAL_OK)
+ return printf("Could not load public key into RPC: %s\n", hal_error_string(err)), 0;
+
+ uint8_t sig[tc->sig_len + 4];
+
+ if ((err = hal_rpc_pkey_sign(session, private_key, hal_hash_handle_none,
+ tc->H, tc->H_len, sig, &len, sizeof(sig))) != HAL_OK)
+ return printf("Could not sign: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_verify(session, public_key, hal_hash_handle_none,
+ tc->H, tc->H_len, sig, len)) != HAL_OK)
+ return printf("Could not verify own signature: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(private_key)) != HAL_OK)
+ return printf("Could not delete private key: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rpc_pkey_delete(public_key)) != HAL_OK)
+ return printf("Could not delete public key: %s\n", hal_error_string(err)), 0;
+
+ printf("OK\n");
+ return 1;
+}
+
+int main (int argc, char *argv[])
+{
+ rpc_client_init(RPC_LOCAL);
+ // rpc_client_init(RPC_REMOTE);
+
+ int ok = 1;
+
+ for (int i = 0; i < (sizeof(rsa_tc)/sizeof(*rsa_tc)); i++)
+ ok &= test_rsa_testvec(&rsa_tc[i]);
+
+ for (int i = 0; i < (sizeof(ecdsa_tc)/sizeof(*ecdsa_tc)); i++)
+ ok &= test_ecdsa_testvec(&ecdsa_tc[i]);
+
+ for (int i = 0; i < (sizeof(rsa_tc)/sizeof(*rsa_tc)); i++)
+ ok &= test_rsa_generate(&rsa_tc[i]);
+
+ for (int i = 0; i < (sizeof(ecdsa_tc)/sizeof(*ecdsa_tc)); i++)
+ ok &= test_ecdsa_generate(&ecdsa_tc[i]);
+
+ return !ok;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/test-rpc_server.c b/tests/test-rpc_server.c
new file mode 100644
index 0000000..6359cb5
--- /dev/null
+++ b/tests/test-rpc_server.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <hal.h>
+
+#warning This is wrong, nothing outside libhal itself should include hal_internal.h
+#include <hal_internal.h>
+
+int main (int argc, char *argv[])
+{
+ if (rpc_server_init() != HAL_OK)
+ return 1;
+
+ rpc_server_main();
+ return 0;
+}
diff --git a/tests/test-rsa.c b/tests/test-rsa.c
index e7e831e..1fc516b 100644
--- a/tests/test-rsa.c
+++ b/tests/test-rsa.c
@@ -1,13 +1,7 @@
/*
* test-rsa.c
* ----------
- * First stumblings towards a test harness for RSA using Cryptech
- * ModExp core.
- *
- * For the moment this just does modular exponentiation tests using
- * RSA keys and pre-formatted data-to-be-signed, without attempting
- * CRT or any of the other clever stuff we should be doing. This is
- * not usable for any sane purpose other than testing.
+ * Test harness for RSA using Cryptech ModExp core.
*
* Authors: Rob Austein
* Copyright (c) 2015, NORDUnet A/S
@@ -67,15 +61,11 @@ static int test_modexp(const hal_core_t *core,
printf("%s test for %lu-bit RSA key\n", kind, (unsigned long) tc->size);
if (hal_modexp(core, msg->val, msg->len, exp->val, exp->len,
- tc->n.val, tc->n.len, result, sizeof(result)) != HAL_OK) {
- printf("ModExp failed\n");
- return 0;
- }
+ tc->n.val, tc->n.len, result, sizeof(result)) != HAL_OK)
+ return printf("ModExp failed\n"), 0;
- if (memcmp(result, val->val, val->len)) {
- printf("MISMATCH\n");
- return 0;
- }
+ if (memcmp(result, val->val, val->len))
+ return printf("MISMATCH\n"), 0;
return 1;
}
@@ -103,10 +93,8 @@ static int test_decrypt(const hal_core_t *core,
tc->q.val, tc->q.len,
tc->u.val, tc->u.len,
tc->dP.val, tc->dP.len,
- tc->dQ.val, tc->dQ.len)) != HAL_OK) {
- printf("RSA CRT key load failed: %s\n", hal_error_string(err));
- return 0;
- }
+ tc->dQ.val, tc->dQ.len)) != HAL_OK)
+ return printf("RSA CRT key load failed: %s\n", hal_error_string(err)), 0;
uint8_t result[tc->n.len];
@@ -133,7 +121,7 @@ static int test_gen(const hal_core_t *core,
{
printf("%s test for %lu-bit RSA key\n", kind, (unsigned long) tc->size);
- char fn[sizeof("test-rsa-key-xxxxxx.der")];
+ char fn[sizeof("test-rsa-private-key-xxxxxx.der")];
uint8_t keybuf1[hal_rsa_key_t_size], keybuf2[hal_rsa_key_t_size];
hal_rsa_key_t *key1 = NULL, *key2 = NULL;
hal_error_t err = HAL_OK;
@@ -141,52 +129,39 @@ static int test_gen(const hal_core_t *core,
const uint8_t f4[] = { 0x01, 0x00, 0x01 };
- if ((err = hal_rsa_key_gen(core, &key1, keybuf1, sizeof(keybuf1), bitsToBytes(tc->size), f4, sizeof(f4))) != HAL_OK) {
- printf("RSA key generation failed: %s\n", hal_error_string(err));
- return 0;
- }
+ if ((err = hal_rsa_key_gen(core, &key1, keybuf1, sizeof(keybuf1), bitsToBytes(tc->size), f4, sizeof(f4))) != HAL_OK)
+ return printf("RSA key generation failed: %s\n", hal_error_string(err)), 0;
size_t der_len = 0;
- if ((err = hal_rsa_key_to_der(key1, NULL, &der_len, 0)) != HAL_OK) {
- printf("Getting DER length of RSA key failed: %s\n", hal_error_string(err));
- return 0;
- }
+ if ((err = hal_rsa_private_key_to_der(key1, NULL, &der_len, 0)) != HAL_OK)
+ return printf("Getting DER length of RSA key failed: %s\n", hal_error_string(err)), 0;
uint8_t der[der_len];
- if ((err = hal_rsa_key_to_der(key1, der, &der_len, sizeof(der))) != HAL_OK) {
- printf("Converting RSA key to DER failed: %s\n", hal_error_string(err));
- return 0;
- }
+ err = hal_rsa_private_key_to_der(key1, der, &der_len, sizeof(der));
- if ((err = hal_rsa_key_from_der(&key2, keybuf2, sizeof(keybuf2), der, sizeof(der))) != HAL_OK) {
- printf("Converting RSA key back from DER failed: %s\n", hal_error_string(err));
- return 0;
- }
+ snprintf(fn, sizeof(fn), "test-rsa-private-key-%04lu.der", (unsigned long) tc->size);
+ printf("Writing %s\n", fn);
- if (memcmp(keybuf1, keybuf2, hal_rsa_key_t_size) != 0) {
- printf("RSA key mismatch after conversion to and back from DER\n");
- return 0;
- }
+ if ((f = fopen(fn, "wb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
- snprintf(fn, sizeof(fn), "test-rsa-key-%04lu.der", (unsigned long) tc->size);
- printf("Writing %s\n", fn);
+ if (fwrite(der, der_len, 1, f) != 1)
+ return printf("Length mismatch writing %s\n", fn), 0;
- if ((f = fopen(fn, "wb")) == NULL) {
- printf("Couldn't open %s: %s\n", fn, strerror(errno));
- return 0;
- }
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
- if (fwrite(der, der_len, 1, f) != 1) {
- printf("Length mismatch writing %s\n", fn);
- return 0;
- }
+ /* Deferred error from hal_rsa_private_key_to_der() */
+ if (err != HAL_OK)
+ return printf("Converting RSA private key to DER failed: %s\n", hal_error_string(err)), 0;
- if (fclose(f) == EOF) {
- printf("Couldn't close %s: %s\n", fn, strerror(errno));
- return 0;
- }
+ if ((err = hal_rsa_private_key_from_der(&key2, keybuf2, sizeof(keybuf2), der, sizeof(der))) != HAL_OK)
+ return printf("Converting RSA key back from DER failed: %s\n", hal_error_string(err)), 0;
+
+ if (memcmp(keybuf1, keybuf2, hal_rsa_key_t_size) != 0)
+ return printf("RSA private key mismatch after conversion to and back from DER\n"), 0;
uint8_t result[tc->n.len];
@@ -196,31 +171,70 @@ static int test_gen(const hal_core_t *core,
snprintf(fn, sizeof(fn), "test-rsa-sig-%04lu.der", (unsigned long) tc->size);
printf("Writing %s\n", fn);
- if ((f = fopen(fn, "wb")) == NULL) {
- printf("Couldn't open %s: %s\n", fn, strerror(errno));
- return 0;
- }
+ if ((f = fopen(fn, "wb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
- if (fwrite(result, sizeof(result), 1, f) != 1) {
- printf("Length mismatch writing %s key\n", fn);
- return 0;
- }
+ if (fwrite(result, sizeof(result), 1, f) != 1)
+ return printf("Length mismatch writing %s\n", fn), 0;
- if (fclose(f) == EOF) {
- printf("Couldn't close %s: %s\n", fn, strerror(errno));
- return 0;
- }
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
if (err != HAL_OK) /* Deferred failure from hal_rsa_decrypt(), above */
return 0;
if ((err = hal_rsa_encrypt(core, key1, result, sizeof(result), result, sizeof(result))) != HAL_OK)
- printf("RSA signature check failed: %s\n", hal_error_string(err));
+ printf("First RSA signature check failed: %s\n", hal_error_string(err));
- const int mismatch = (err == HAL_OK && memcmp(result, tc->m.val, tc->m.len) != 0);
+ int mismatch = 0;
- if (mismatch)
- printf("MISMATCH\n");
+ if (err == HAL_OK && memcmp(result, tc->m.val, tc->m.len) != 0)
+ mismatch = (printf("MISMATCH\n"), 1);
+
+ hal_rsa_key_clear(key2);
+ key2 = NULL;
+
+ if ((f = fopen(fn, "rb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
+
+ if (fread(result, sizeof(result), 1, f) != 1)
+ return printf("Length mismatch reading %s\n", fn), 0;
+
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
+
+ err = hal_rsa_public_key_to_der(key1, der, &der_len, sizeof(der));
+
+ snprintf(fn, sizeof(fn), "test-rsa-public-key-%04lu.der", (unsigned long) tc->size);
+ printf("Writing %s\n", fn);
+
+ if ((f = fopen(fn, "wb")) == NULL)
+ return printf("Couldn't open %s: %s\n", fn, strerror(errno)), 0;
+
+ if (fwrite(der, der_len, 1, f) != 1)
+ return printf("Length mismatch writing %s\n", fn), 0;
+
+ if (fclose(f) == EOF)
+ return printf("Couldn't close %s: %s\n", fn, strerror(errno)), 0;
+
+ /* Deferred error from hal_rsa_public_key_to_der() */
+ if (err != HAL_OK)
+ return printf("Converting RSA public key to DER failed: %s\n", hal_error_string(err)), 0;
+
+ if ((err = hal_rsa_public_key_from_der(&key2, keybuf2, sizeof(keybuf2), der, der_len)) != HAL_OK)
+ return printf("Converting RSA public key back from DER failed: %s\n", hal_error_string(err)), 0;
+
+ /*
+ * Can't directly compare private key with public key. We could
+ * extract and compare the public key components, not much point if
+ * the public key passes the signature verification test below.
+ */
+
+ if ((err = hal_rsa_encrypt(core, key2, result, sizeof(result), result, sizeof(result))) != HAL_OK)
+ return printf("Second RSA signature check failed: %s\n", hal_error_string(err)), 0;
+
+ if (err == HAL_OK && memcmp(result, tc->m.val, tc->m.len) != 0)
+ mismatch = (printf("MISMATCH\n"), 1);
hal_rsa_key_clear(key1);
hal_rsa_key_clear(key2);