aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--GNUmakefile2
-rw-r--r--asn1.c3
-rw-r--r--ecdsa.c2
-rw-r--r--hash.c104
-rw-r--r--ks.c1
-rw-r--r--ks_mmap.c1
-rw-r--r--ks_volatile.c1
-rw-r--r--rpc_pkey.c36
-rw-r--r--tests/GNUmakefile2
-rw-r--r--tests/test-hash.c6
-rw-r--r--tests/test-rpc_hash.c2
-rw-r--r--tests/test-rpc_pkey.c348
13 files changed, 436 insertions, 73 deletions
diff --git a/.gitignore b/.gitignore
index b5ca513..5a3bff4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ tests/test-ecdsa-*.der
tests/test-hash
tests/test-pbkdf2
tests/test-rpc_hash
+tests/test-rpc_pkey
tests/test-rpc_server
tests/test-rsa
tests/test-rsa-*.der
diff --git a/GNUmakefile b/GNUmakefile
index 75bcf44..a4154af 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -156,7 +156,7 @@ else ifeq (${KS},flash)
endif
TFMDIR := $(abspath ../thirdparty/libtfm)
-CFLAGS += -g3 -Wall -std=c99 -I${TFMDIR} -DHAL_ECDSA_DEBUG_ONLY_STATIC_TEST_VECTOR_RANDOM=1
+CFLAGS += -g3 -Wall -std=c99 -I${TFMDIR}
LDFLAGS := -g3 -L${TFMDIR} -ltfm
CFLAGS += -DHAL_STATIC_HASH_STATE_BLOCKS=${STATIC_HASH_STATE_BLOCKS}
diff --git a/asn1.c b/asn1.c
index c50a7b4..2206ec3 100644
--- a/asn1.c
+++ b/asn1.c
@@ -161,7 +161,8 @@ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t a
const uint8_t * const pubkey, const size_t pubkey_len,
uint8_t *der, size_t *der_len, const size_t der_max)
{
- if (alg_oid == NULL || alg_oid_len == 0 || pubkey == NULL || pubkey_len == 0 || (curve_oid == NULL && curve_oid_len != 0))
+ if (alg_oid == NULL || alg_oid_len == 0 || pubkey_len == 0 ||
+ (der != NULL && pubkey == NULL) || (curve_oid == NULL && curve_oid_len != 0))
return HAL_ERROR_BAD_ARGUMENTS;
const uint8_t curve_oid_tag = curve_oid == NULL ? ASN1_NULL : ASN1_OBJECT_IDENTIFIER;
diff --git a/ecdsa.c b/ecdsa.c
index 6635cb0..429f05c 100644
--- a/ecdsa.c
+++ b/ecdsa.c
@@ -738,7 +738,7 @@ static inline hal_error_t get_random(void *buffer, const size_t length)
static inline hal_error_t get_random(void *buffer, const size_t length)
{
- return hal_get_random(buffer, length);
+ return hal_get_random(NULL, buffer, length);
}
#endif /* HAL_ECDSA_DEBUG_ONLY_STATIC_TEST_VECTOR_RANDOM */
diff --git a/hash.c b/hash.c
index e2a7f43..a371f48 100644
--- a/hash.c
+++ b/hash.c
@@ -87,6 +87,7 @@ struct hal_hash_driver {
hal_addr_t digest_addr; /* Where to read digest */
uint8_t ctrl_mode; /* Digest mode, for cores that have modes */
sw_hash_core_t sw_core; /* Software implementation, when enabled */
+ size_t sw_word_size; /* Word size for software implementation */
};
/*
@@ -128,27 +129,27 @@ struct hal_hmac_state {
*/
static const hal_hash_driver_t sha1_driver = {
- SHA1_LENGTH_LEN, SHA1_ADDR_BLOCK, SHA1_ADDR_DIGEST, 0, sw_hash_core_sha1
+ SHA1_LENGTH_LEN, SHA1_ADDR_BLOCK, SHA1_ADDR_DIGEST, 0, sw_hash_core_sha1, sizeof(uint32_t)
};
static const hal_hash_driver_t sha256_driver = {
- SHA256_LENGTH_LEN, SHA256_ADDR_BLOCK, SHA256_ADDR_DIGEST, 0, sw_hash_core_sha256
+ SHA256_LENGTH_LEN, SHA256_ADDR_BLOCK, SHA256_ADDR_DIGEST, 0, sw_hash_core_sha256, sizeof(uint32_t)
};
static const hal_hash_driver_t sha512_224_driver = {
- SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512_224, sw_hash_core_sha512
+ SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512_224, sw_hash_core_sha512, sizeof(uint64_t)
};
static const hal_hash_driver_t sha512_256_driver = {
- SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512_256, sw_hash_core_sha512
+ SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512_256, sw_hash_core_sha512, sizeof(uint64_t)
};
static const hal_hash_driver_t sha384_driver = {
- SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_384, sw_hash_core_sha512
+ SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_384, sw_hash_core_sha512, sizeof(uint64_t)
};
static const hal_hash_driver_t sha512_driver = {
- SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512, sw_hash_core_sha512
+ SHA512_LENGTH_LEN, SHA512_ADDR_BLOCK, SHA512_ADDR_DIGEST, MODE_SHA_512, sw_hash_core_sha512, sizeof(uint64_t)
};
/*
@@ -299,6 +300,38 @@ static inline hal_hmac_state_t *alloc_static_hmac_state(void)
}
/*
+ * Internal utility to do a sort of byte-swapping memcpy() (sigh).
+ * This is only used by the software hash cores, but it's simpler to define it unconditionally.
+ */
+
+static inline void swytebop(void *out_, const void * const in_, const size_t n, const size_t w)
+{
+ const uint8_t order[] = { 0x01, 0x02, 0x03, 0x04 };
+
+ const uint8_t * const in = in_;
+ uint8_t *out = out_;
+
+ /* w must be a power of two */
+ assert(in != out && in != NULL && out != NULL && w && !(w & (w - 1)));
+
+ switch (* (uint32_t *) order) {
+
+ case 0x01020304:
+ memcpy(out, in, n);
+ return;
+
+ case 0x04030201:
+ for (int i = 0; i < n; i += w)
+ for (int j = 0; j < w && i + j < n; j++)
+ out[i + j] = in[i + w - j - 1];
+ return;
+
+ default:
+ assert((* (uint32_t *) order) == 0x01020304 || (* (uint32_t *) order) == 0x04030201);
+ }
+}
+
+/*
* Internal utility to do whatever checking we need of a descriptor,
* then extract the driver pointer in a way that works nicely with
* initialization of an automatic const pointer.
@@ -614,7 +647,7 @@ hal_error_t hal_hash_finalize(hal_hash_state_t *state, /* Opaqu
/* All data pushed to core, now we just need to read back the result */
if (HAL_ENABLE_SOFTWARE_HASH_CORES && (state->flags & STATE_FLAG_SOFTWARE_CORE) != 0)
- memcpy(digest_buffer, state->core_state, state->descriptor->digest_length);
+ swytebop(digest_buffer, state->core_state, state->descriptor->digest_length, state->driver->sw_word_size);
else if ((err = hash_read_digest(state->core, state->driver, digest_buffer, state->descriptor->digest_length)) != HAL_OK)
return err;
@@ -898,36 +931,6 @@ static inline int sha1_pos(int i, int j) { assert(i >= 0 && j >= 0 && j < 5); re
static inline int sha2_pos(int i, int j) { assert(i >= 0 && j >= 0 && j < 8); return (8 + j - (i % 8)) % 8; }
/*
- * Byte-swapping version of memcpy() (sigh).
- */
-
-static inline void swytebop(void *out_, const void * const in_, const size_t n, const size_t w)
-{
- const uint8_t order[] = { 0x01, 0x02, 0x03, 0x04 };
-
- const uint8_t * const in = in_;
- uint8_t *out = out_;
-
- assert(in != out && in != NULL && out != NULL && w % 4 == 0 && n % w == 0);
-
- switch (* (uint32_t *) order) {
-
- case 0x01020304:
- memcpy(out, in, n);
- return;
-
- case 0x04030201:
- for (int i = 0; i < n; i += w)
- for (int j = 0; j < w; j++)
- out[i + j] = in[i + w - j - 1];
- return;
-
- default:
- assert((* (uint32_t *) order) == 0x01020304 || (* (uint32_t *) order) == 0x04030201);
- }
-}
-
-/*
* Software implementation of SHA-1 block algorithm.
*/
@@ -938,14 +941,12 @@ static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state)
if (state == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
- uint32_t H[5], S[5], W[80];
+ uint32_t *H = (uint32_t *) state->core_state, S[5], W[80];
if (state->block_count == 0)
memcpy(H, iv, sizeof(iv));
- else
- swytebop(H, state->core_state, sizeof(H), sizeof(*H));
- memcpy(S, H, sizeof(H));
+ memcpy(S, H, sizeof(S));
swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W));
@@ -977,8 +978,6 @@ static hal_error_t sw_hash_core_sha1(hal_hash_state_t *state)
for (int i = 0; i < 5; i++)
H[i] += S[i];
- swytebop(state->core_state, H, sizeof(H), sizeof(*H));
-
return HAL_OK;
}
@@ -995,14 +994,12 @@ static hal_error_t sw_hash_core_sha256(hal_hash_state_t *state)
if (state == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
- uint32_t H[8], S[8], W[64];
+ uint32_t *H = (uint32_t *) state->core_state, S[8], W[64];
if (state->block_count == 0)
memcpy(H, iv, sizeof(iv));
- else
- swytebop(H, state->core_state, sizeof(H), sizeof(*H));
- memcpy(S, H, sizeof(H));
+ memcpy(S, H, sizeof(S));
swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W));
@@ -1023,8 +1020,6 @@ static hal_error_t sw_hash_core_sha256(hal_hash_state_t *state)
for (int i = 0; i < 8; i++)
H[i] += S[i];
- swytebop(state->core_state, H, sizeof(H), sizeof(*H));
-
return HAL_OK;
}
@@ -1051,9 +1046,9 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *state)
if (state == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
- uint64_t H[8], S[8], W[80];
+ uint64_t *H = (uint64_t *) state->core_state, S[8], W[80];
- if (state->block_count == 0)
+ if (state->block_count == 0) {
switch (state->driver->ctrl_mode & MODE_SHA_MASK) {
case MODE_SHA_512_224: memcpy(H, sha512_224_iv, sizeof(sha512_224_iv)); break;
case MODE_SHA_512_256: memcpy(H, sha512_256_iv, sizeof(sha512_256_iv)); break;
@@ -1061,10 +1056,9 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *state)
case MODE_SHA_512: memcpy(H, sha512_iv, sizeof(sha512_iv)); break;
default: return HAL_ERROR_IMPOSSIBLE;
}
- else
- swytebop(H, state->core_state, sizeof(H), sizeof(*H));
+ }
- memcpy(S, H, sizeof(H));
+ memcpy(S, H, sizeof(S));
swytebop(W, state->block, 16 * sizeof(*W), sizeof(*W));
@@ -1085,8 +1079,6 @@ static hal_error_t sw_hash_core_sha512(hal_hash_state_t *state)
for (int i = 0; i < 8; i++)
H[i] += S[i];
- swytebop(state->core_state, H, sizeof(H), sizeof(*H));
-
return HAL_OK;
}
diff --git a/ks.c b/ks.c
index a856bbf..d1ce089 100644
--- a/ks.c
+++ b/ks.c
@@ -93,6 +93,7 @@ hal_error_t hal_ks_store(const hal_key_type_t type,
hal_ks_key_t k;
memset(&k, 0, sizeof(k));
+ k.der_len = sizeof(k.der);
uint8_t kek[KEK_LENGTH];
size_t kek_len;
diff --git a/ks_mmap.c b/ks_mmap.c
index 4c752ea..5eb2a13 100644
--- a/ks_mmap.c
+++ b/ks_mmap.c
@@ -168,6 +168,7 @@ hal_error_t hal_ks_get_kek(uint8_t *kek,
return err;
memcpy(kek, kekbuf, len);
+ *kek_len = len;
return HAL_OK;
}
diff --git a/ks_volatile.c b/ks_volatile.c
index b71e27e..9a47d52 100644
--- a/ks_volatile.c
+++ b/ks_volatile.c
@@ -132,6 +132,7 @@ hal_error_t hal_ks_get_kek(uint8_t *kek,
return err;
memcpy(kek, kekbuf, len);
+ *kek_len = len;
return HAL_OK;
}
diff --git a/rpc_pkey.c b/rpc_pkey.c
index e7331ab..96680ed 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -669,13 +669,13 @@ static hal_error_t sign(const hal_session_handle_t session,
}
/*
- * Verify something using private key associated with handle.
+ * Verify something using public key associated with handle.
*
* RSA has enough quirks that it's simplest to split this out into
* algorithm-specific functions.
*/
-static hal_error_t verify_rsa(uint8_t *keybuf, const size_t keybuf_len,
+static hal_error_t verify_rsa(uint8_t *keybuf, const size_t keybuf_len, const hal_key_type_t type,
const uint8_t * const der, const size_t der_len,
const hal_hash_handle_t hash,
const uint8_t * input, size_t input_len,
@@ -688,7 +688,18 @@ static hal_error_t verify_rsa(uint8_t *keybuf, const size_t keybuf_len,
assert(signature != NULL && signature_len > 0);
assert((hash.handle == hal_hash_handle_none.handle) != (input == NULL || input_len == 0));
- if ((err = hal_rsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ switch (type) {
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ err = hal_rsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ case HAL_KEY_TYPE_RSA_PUBLIC:
+ err = hal_rsa_public_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ default:
+ err = HAL_ERROR_IMPOSSIBLE;
+ }
+
+ if (err != HAL_OK)
return err;
if (input == NULL) {
@@ -711,7 +722,7 @@ static hal_error_t verify_rsa(uint8_t *keybuf, const size_t keybuf_len,
return HAL_OK;
}
-static hal_error_t verify_ecdsa(uint8_t *keybuf, const size_t keybuf_len,
+static hal_error_t verify_ecdsa(uint8_t *keybuf, const size_t keybuf_len, const hal_key_type_t type,
const uint8_t * const der, const size_t der_len,
const hal_hash_handle_t hash,
const uint8_t * input, size_t input_len,
@@ -724,7 +735,18 @@ static hal_error_t verify_ecdsa(uint8_t *keybuf, const size_t keybuf_len,
assert(signature != NULL && signature_len > 0);
assert((hash.handle == hal_hash_handle_none.handle) != (input == NULL || input_len == 0));
- if ((err = hal_ecdsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ switch (type) {
+ case HAL_KEY_TYPE_EC_PRIVATE:
+ err = hal_ecdsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ case HAL_KEY_TYPE_EC_PUBLIC:
+ err = hal_ecdsa_public_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ default:
+ err = HAL_ERROR_IMPOSSIBLE;
+ }
+
+ if (err != HAL_OK)
return err;
if (input == NULL) {
@@ -755,7 +777,7 @@ static hal_error_t verify(const hal_session_handle_t session,
if (slot == NULL)
return HAL_ERROR_KEY_NOT_FOUND;
- hal_error_t (*verifier)(uint8_t *keybuf, const size_t keybuf_len,
+ hal_error_t (*verifier)(uint8_t *keybuf, const size_t keybuf_len, const hal_key_type_t type,
const uint8_t * const der, const size_t der_len,
const hal_hash_handle_t hash,
const uint8_t * const input, const size_t input_len,
@@ -782,7 +804,7 @@ static hal_error_t verify(const hal_session_handle_t session,
err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, der, &der_len, sizeof(der), &slot->ks_hint);
if (err == HAL_OK)
- err = verifier(keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, signature, signature_len);
+ err = verifier(keybuf, sizeof(keybuf), slot->type, der, der_len, hash, input, input_len, signature, signature_len);
memset(keybuf, 0, sizeof(keybuf));
memset(der, 0, sizeof(der));
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index 0fa6281..63db700 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -40,7 +40,7 @@ ifndef RPC_SERVER
endif
endif
ifdef RPC_CLIENT
- BIN += test-rpc_hash test-rpc_get_version
+ BIN += test-rpc_hash test-rpc_pkey test-rpc_get_version
endif
ifdef RPC_SERVER
BIN += test-rpc_server
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
index 8b41ac7..22bc589 100644
--- a/tests/test-rpc_hash.c
+++ b/tests/test-rpc_hash.c
@@ -40,6 +40,8 @@
#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. */
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:
+ */