diff options
-rw-r--r-- | GNUmakefile | 19 | ||||
-rw-r--r-- | hal.h | 1 | ||||
-rw-r--r-- | hal_internal.h | 95 | ||||
-rw-r--r-- | ks.c | 8 | ||||
-rw-r--r-- | rpc_api.c | 78 | ||||
-rw-r--r-- | rpc_client.c | 525 | ||||
-rw-r--r-- | rpc_client_loopback.c | 85 | ||||
-rw-r--r-- | rpc_hash.c | 22 | ||||
-rw-r--r-- | rpc_server.c | 709 | ||||
-rw-r--r-- | rpc_server_loopback.c | 89 | ||||
-rw-r--r-- | rpc_xdr.c | 245 | ||||
-rw-r--r-- | tests/GNUmakefile | 1 | ||||
-rw-r--r-- | tests/test-rpc_hash.c | 698 | ||||
-rw-r--r-- | tests/test-rpc_server.c | 16 |
14 files changed, 2489 insertions, 102 deletions
diff --git a/GNUmakefile b/GNUmakefile index a600dd3..0637f76 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -46,18 +46,13 @@ IO_OBJ_I2C = hal_io_i2c.o # Default I/O bus is EIM, override this to use I2C instead IO_OBJ = ${IO_OBJ_EIM} -RPC_OBJ_COMMON = rpc_api.o rpc_hash.o -RPC_OBJ_CLIENT = ${RPC_OBJ_COMMON} rpc_client.o -RPC_OBJ_SERVER = ${RPC_OBJ_COMMON} rpc_misc.o rpc_pkey.o - -# Default should be to build the RPC server code, but we haven't -# written even the skeleton of that yet. We'll probably end up -# needing a makefile conditional to handle all this properly -RPC_OBJ = ${RPC_OBJ_SERVER} - -# XXX temporary -$(warning TEMPORARY KLUDGE TO TEST rpc_client) -RPC_OBJ += ${RPC_OBJ_CLIENT} +RPC_OBJ_COMMON = rpc_api.o rpc_hash.o rpc_misc.o rpc_pkey.o rpc_xdr.o +RPC_OBJ_CLIENT = rpc_client.o rpc_client_loopback.o +RPC_OBJ_SERVER = rpc_server.o rpc_server_loopback.o + +# Default should be to build the RPC server code. We'll probably end up +# needing a makefile conditional to handle all this properly. +RPC_OBJ = ${RPC_OBJ_COMMON} ${RPC_OBJ_CLIENT} ${RPC_OBJ_SERVER} KS_OBJ_COMMON = ks.o KS_OBJ_MMAP = ${KS_OBJ_COMMON} ks_mmap.o @@ -125,6 +125,7 @@ DEFINE_HAL_ERROR(HAL_ERROR_PIN_INCORRECT, "PIN incorrect") \ DEFINE_HAL_ERROR(HAL_ERROR_NO_CLIENT_SLOTS_AVAILABLE, "No client slots available") \ DEFINE_HAL_ERROR(HAL_ERROR_FORBIDDEN, "Forbidden") \ + DEFINE_HAL_ERROR(HAL_ERROR_RPC_TRANSPORT, "RPC transport error") \ END_OF_HAL_ERROR_LIST /* Marker to forestall silly line continuation errors */ diff --git a/hal_internal.h b/hal_internal.h index ea760cf..692067e 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -194,9 +194,9 @@ typedef struct { } hal_rpc_pkey_dispatch_t; -extern const hal_rpc_misc_dispatch_t hal_rpc_local_misc_dispatch, hal_rpc_remote_misc_dispatch; -extern const hal_rpc_hash_dispatch_t hal_rpc_local_hash_dispatch, hal_rpc_remote_hash_dispatch; -extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote_pkey_dispatch, hal_rpc_mixed_pkey_dispatch; +extern const hal_rpc_misc_dispatch_t hal_rpc_local_misc_dispatch, hal_rpc_remote_misc_dispatch, *hal_rpc_misc_dispatch; +extern const hal_rpc_hash_dispatch_t hal_rpc_local_hash_dispatch, hal_rpc_remote_hash_dispatch, *hal_rpc_hash_dispatch; +extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote_pkey_dispatch, hal_rpc_mixed_pkey_dispatch, *hal_rpc_pkey_dispatch; /* * Keystore API. @@ -326,6 +326,95 @@ extern hal_error_t hal_ks_get_pin(const hal_user_t user, extern hal_error_t hal_ks_set_pin(const hal_user_t user, const hal_ks_pin_t * const pin); +/* + * RPC serialization/deserialization routines, using XDR (RFC 4506) encoding. + */ + +hal_error_t rpc_encode_int(uint8_t ** const outbuf, + const uint8_t * const limit, + const uint32_t value); + +hal_error_t rpc_decode_int(uint8_t ** const inbuf, + const uint8_t * const limit, + uint32_t * const value); + +hal_error_t rpc_encode_buffer(uint8_t ** const outbuf, + const uint8_t * const limit, + const uint8_t * const value, + const uint32_t len); + +hal_error_t rpc_decode_buffer_in_place(uint8_t ** const inbuf, + const uint8_t * const limit, + uint8_t ** const vptr, + uint32_t * const len); + +hal_error_t rpc_decode_buffer(uint8_t ** const inbuf, + const uint8_t * const limit, + uint8_t * const value, + uint32_t * const len); + +/* XXX move to hal.h? */ +typedef enum { + RPC_LOCAL, + RPC_REMOTE, + RPC_MIXED, +} rpc_locality_t; + +/* + * RPC lowest-level send and receive routines. These are blocking, and + * transport-specific (sockets, USB). + */ + +hal_error_t rpc_send(const uint8_t * const buf, const size_t len); +hal_error_t rpc_recv(uint8_t * const buf, size_t * const len); + +hal_error_t rpc_client_init(rpc_locality_t locality); +hal_error_t rpc_client_close(void); +hal_error_t rpc_client_transport_init(void); +hal_error_t rpc_client_transport_close(void); + +hal_error_t rpc_sendto(const uint8_t * const buf, const size_t len, void *opaque); +hal_error_t rpc_recvfrom(uint8_t * const buf, size_t * const len, void **opaque); + +hal_error_t rpc_server_init(void); +hal_error_t rpc_server_close(void); +hal_error_t rpc_server_transport_init(void); +hal_error_t rpc_server_transport_close(void); +void rpc_server_main(void); + +/* + * RPC function numbers + */ + +typedef enum { + RPC_FUNC_GET_RANDOM, + RPC_FUNC_SET_PIN, + RPC_FUNC_LOGIN, + RPC_FUNC_LOGOUT, + RPC_FUNC_LOGOUT_ALL, + RPC_FUNC_IS_LOGGED_IN, + RPC_FUNC_HASH_GET_DIGEST_LEN, + RPC_FUNC_HASH_GET_DIGEST_ALGORITHM_ID, + RPC_FUNC_HASH_GET_ALGORITHM, + RPC_FUNC_HASH_INITIALIZE, + RPC_FUNC_HASH_UPDATE, + RPC_FUNC_HASH_FINALIZE, + RPC_FUNC_PKEY_LOAD, + RPC_FUNC_PKEY_FIND, + RPC_FUNC_PKEY_GENERATE_RSA, + RPC_FUNC_PKEY_GENERATE_EC, + RPC_FUNC_PKEY_CLOSE, + RPC_FUNC_PKEY_DELETE, + RPC_FUNC_PKEY_GET_KEY_TYPE, + RPC_FUNC_PKEY_GET_KEY_FLAGS, + RPC_FUNC_PKEY_GET_PUBLIC_KEY_LEN, + RPC_FUNC_PKEY_GET_PUBLIC_KEY, + RPC_FUNC_PKEY_REMOTE_SIGN, + RPC_FUNC_PKEY_REMOTE_VERIFY, + RPC_FUNC_PKEY_LIST, +} rpc_func_num_t; + + #endif /* _HAL_INTERNAL_H_ */ /* @@ -294,6 +294,14 @@ hal_error_t hal_ks_get_pin(const hal_user_t user, return HAL_OK; } +hal_error_t hal_ks_get_kek(uint8_t *kek, + size_t *kek_len, + const size_t kek_max) +{ +# warning Stub out hal_ks_get_kek() for now + return HAL_ERROR_IMPOSSIBLE; +} + /* * Local variables: * indent-tabs-mode: nil @@ -4,7 +4,7 @@ * Remote procedure call public API implementation. * * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * 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 @@ -36,32 +36,6 @@ #include "hal.h" #include "hal_internal.h" -#ifndef HAL_RPC_IS_CLIENT -#warning HAL_RPC_IS_CLIENT not set, assuming we're building for the HSM -#define HAL_RPC_IS_CLIENT 0 -#endif - -/* - * Maybe we'll let the client configure this at runtime, later. For - * now, wire in the obvious defaults: hashing is done locally, - * everything else is done via RPC. For the server everything is - * always done locally. - */ - -#if HAL_RPC_IS_CLIENT - -static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_remote_misc_dispatch; -static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_remote_hash_dispatch; -static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_mixed_pkey_dispatch; - -#else - -static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_local_misc_dispatch; -static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_local_hash_dispatch; -static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_local_pkey_dispatch; - -#endif - const hal_hash_handle_t hal_hash_handle_none = {0}; static inline int check_pkey_type(const hal_key_type_t type) @@ -120,7 +94,7 @@ hal_error_t hal_rpc_get_random(void *buffer, const size_t length) return HAL_ERROR_BAD_ARGUMENTS; if (length == 0) return HAL_OK; - return misc_dispatch->get_random(buffer, length); + return hal_rpc_misc_dispatch->get_random(buffer, length); } #warning Perhaps we should be enforcing a minimum PIN length here @@ -131,7 +105,7 @@ hal_error_t hal_rpc_set_pin(const hal_client_handle_t client, { if (newpin == NULL || newpin_len == 0 || (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL)) return HAL_ERROR_BAD_ARGUMENTS; - return misc_dispatch->set_pin(client, user, newpin, newpin_len); + return hal_rpc_misc_dispatch->set_pin(client, user, newpin, newpin_len); } hal_error_t hal_rpc_login(const hal_client_handle_t client, @@ -140,17 +114,17 @@ hal_error_t hal_rpc_login(const hal_client_handle_t client, { if (pin == NULL || pin_len == 0 || (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL)) return HAL_ERROR_BAD_ARGUMENTS; - return misc_dispatch->login(client, user, pin, pin_len); + return hal_rpc_misc_dispatch->login(client, user, pin, pin_len); } hal_error_t hal_rpc_logout(const hal_client_handle_t client) { - return misc_dispatch->logout(client); + return hal_rpc_misc_dispatch->logout(client); } hal_error_t hal_rpc_logout_all(void) { - return misc_dispatch->logout_all(); + return hal_rpc_misc_dispatch->logout_all(); } hal_error_t hal_rpc_is_logged_in(const hal_client_handle_t client, @@ -158,27 +132,27 @@ hal_error_t hal_rpc_is_logged_in(const hal_client_handle_t client, { if (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL) return HAL_ERROR_BAD_ARGUMENTS; - return misc_dispatch->is_logged_in(client, user); + return hal_rpc_misc_dispatch->is_logged_in(client, user); } hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, size_t *length) { if (length == NULL) return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->get_digest_length(alg, length); + return hal_rpc_hash_dispatch->get_digest_length(alg, length); } hal_error_t hal_rpc_hash_get_digest_algorithm_id(const hal_digest_algorithm_t alg, uint8_t *id, size_t *len, const size_t len_max) { - return hash_dispatch->get_digest_algorithm_id(alg, id, len, len_max); + return hal_rpc_hash_dispatch->get_digest_algorithm_id(alg, id, len, len_max); } hal_error_t hal_rpc_hash_get_algorithm(const hal_hash_handle_t hash, hal_digest_algorithm_t *alg) { if (hash.handle == hal_hash_handle_none.handle || alg == NULL) return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->get_algorithm(hash, alg); + return hal_rpc_hash_dispatch->get_algorithm(hash, alg); } hal_error_t hal_rpc_hash_initialize(const hal_client_handle_t client, @@ -189,7 +163,7 @@ hal_error_t hal_rpc_hash_initialize(const hal_client_handle_t client, { if (hash == NULL) return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->initialize(client, session, hash, alg, key, key_len); + return hal_rpc_hash_dispatch->initialize(client, session, hash, alg, key, key_len); } hal_error_t hal_rpc_hash_update(const hal_hash_handle_t hash, @@ -199,7 +173,7 @@ hal_error_t hal_rpc_hash_update(const hal_hash_handle_t hash, return HAL_ERROR_BAD_ARGUMENTS; if (length == 0) return HAL_OK; - return hash_dispatch->update(hash, data, length); + return hal_rpc_hash_dispatch->update(hash, data, length); } hal_error_t hal_rpc_hash_finalize(const hal_hash_handle_t hash, @@ -207,7 +181,7 @@ hal_error_t hal_rpc_hash_finalize(const hal_hash_handle_t hash, { if (hash.handle == hal_hash_handle_none.handle || digest == NULL || length == 0) return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->finalize(hash, digest, length); + return hal_rpc_hash_dispatch->finalize(hash, digest, length); } hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, @@ -224,7 +198,7 @@ hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, der == NULL || der_len == 0 || !check_pkey_type_curve_flags(type, curve, flags)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->load(client, session, pkey, type, curve, name, name_len, der, der_len, flags); + return hal_rpc_pkey_dispatch->load(client, session, pkey, type, curve, name, name_len, der, der_len, flags); } hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, @@ -235,7 +209,7 @@ hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, { if (pkey == NULL || name == NULL || name_len == 0 || !check_pkey_type(type)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->find(client, session, pkey, type, name, name_len); + return hal_rpc_pkey_dispatch->find(client, session, pkey, type, name, name_len); } hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, @@ -249,7 +223,7 @@ hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, if (pkey == NULL || name == NULL || name_len == 0 || key_len == 0 || (key_len & 7) != 0 || exp == NULL || exp_len == 0 || !check_pkey_flags(flags)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->generate_rsa(client, session, pkey, name, name_len, key_len, exp, exp_len, flags); + return hal_rpc_pkey_dispatch->generate_rsa(client, session, pkey, name, name_len, key_len, exp, exp_len, flags); } hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, @@ -262,17 +236,17 @@ hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, if (pkey == NULL || name == NULL || name_len == 0 || !check_pkey_type_curve_flags(HAL_KEY_TYPE_EC_PRIVATE, curve, flags)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->generate_ec(client, session, pkey, name, name_len, curve, flags); + return hal_rpc_pkey_dispatch->generate_ec(client, session, pkey, name, name_len, curve, flags); } hal_error_t hal_rpc_pkey_close(const hal_pkey_handle_t pkey) { - return pkey_dispatch->close(pkey); + return hal_rpc_pkey_dispatch->close(pkey); } hal_error_t hal_rpc_pkey_delete(const hal_pkey_handle_t pkey) { - return pkey_dispatch->delete(pkey); + return hal_rpc_pkey_dispatch->delete(pkey); } hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, @@ -280,7 +254,7 @@ hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, { if (type == NULL) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_key_type(pkey, type); + return hal_rpc_pkey_dispatch->get_key_type(pkey, type); } hal_error_t hal_rpc_pkey_get_key_flags(const hal_pkey_handle_t pkey, @@ -288,12 +262,12 @@ hal_error_t hal_rpc_pkey_get_key_flags(const hal_pkey_handle_t pkey, { if (flags == NULL) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_key_flags(pkey, flags); + return hal_rpc_pkey_dispatch->get_key_flags(pkey, flags); } size_t hal_rpc_pkey_get_public_key_len(const hal_pkey_handle_t pkey) { - return pkey_dispatch->get_public_key_len(pkey); + return hal_rpc_pkey_dispatch->get_public_key_len(pkey); } hal_error_t hal_rpc_pkey_get_public_key(const hal_pkey_handle_t pkey, @@ -301,7 +275,7 @@ hal_error_t hal_rpc_pkey_get_public_key(const hal_pkey_handle_t pkey, { if (der == NULL || der_len == NULL || der_max == 0) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_public_key(pkey, der, der_len, der_max); + return hal_rpc_pkey_dispatch->get_public_key(pkey, der, der_len, der_max); } hal_error_t hal_rpc_pkey_sign(const hal_session_handle_t session, @@ -313,7 +287,7 @@ hal_error_t hal_rpc_pkey_sign(const hal_session_handle_t session, if (signature == NULL || signature_len == NULL || signature_max == 0 || (hash.handle == hal_hash_handle_none.handle) == (input == NULL || input_len == 0)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->sign(session, pkey, hash, input, input_len, signature, signature_len, signature_max); + return hal_rpc_pkey_dispatch->sign(session, pkey, hash, input, input_len, signature, signature_len, signature_max); } hal_error_t hal_rpc_pkey_verify(const hal_session_handle_t session, @@ -325,7 +299,7 @@ hal_error_t hal_rpc_pkey_verify(const hal_session_handle_t session, if (signature == NULL || signature_len == 0 || (hash.handle == hal_hash_handle_none.handle) == (input == NULL || input_len == 0)) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->verify(session, pkey, hash, input, input_len, signature, signature_len); + return hal_rpc_pkey_dispatch->verify(session, pkey, hash, input, input_len, signature, signature_len); } hal_error_t hal_rpc_pkey_list(hal_pkey_info_t *result, @@ -334,7 +308,7 @@ hal_error_t hal_rpc_pkey_list(hal_pkey_info_t *result, { if (result == NULL || result_len == NULL || result_max == 0) return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->list(result, result_len, result_max); + return hal_rpc_pkey_dispatch->list(result, result_len, result_max); } /* diff --git a/rpc_client.c b/rpc_client.c index 3d4fcee..d58cb92 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -3,8 +3,8 @@ * ------------ * Remote procedure call client-side private API implementation. * - * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * 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 @@ -33,25 +33,60 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <assert.h> + #include "hal.h" #include "hal_internal.h" /* - * RPC calls. Not implemented yet. + * RPC calls. */ -#warning These are all placeholders, waiting to be filled in with the real RPC calls +#define check(op) if ((ret = (op)) != HAL_OK) return ret; + +#define pad(n) (((n) + 3) & ~3) static hal_error_t get_random(void *buffer, const size_t length) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(length)], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t rcvlen = length; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_GET_RANDOM)); + check(rpc_encode_int(&optr, olimit, (uint32_t)length)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_buffer(&iptr, ilimit, buffer, &rcvlen)); + // XXX check rcvlen vs length + } + return rpc_ret; } static hal_error_t set_pin(const hal_client_handle_t client, const hal_user_t user, - const char * const newpin, const size_t newpin_len) + const char * const pin, const size_t pin_len) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12 + pad(pin_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_SET_PIN)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, user)); + check(rpc_encode_buffer(&optr, olimit, (const uint8_t *)pin, pin_len)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } /* @@ -72,39 +107,141 @@ static hal_error_t login(const hal_client_handle_t client, const hal_user_t user, const char * const pin, const size_t pin_len) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12 + pad(pin_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_LOGIN)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, user)); + check(rpc_encode_buffer(&optr, olimit, (const uint8_t *)pin, pin_len)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t logout(const hal_client_handle_t client) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_LOGOUT)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t logout_all(void) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[4], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_LOGOUT_ALL)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t is_logged_in(const hal_client_handle_t client, const hal_user_t user) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_IS_LOGGED_IN)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, user)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t hash_get_digest_len(const hal_digest_algorithm_t alg, size_t *length) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t len32; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_GET_DIGEST_LEN)); + check(rpc_encode_int(&optr, olimit, alg)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &len32)); + *length = (size_t)len32; + } + return rpc_ret; } static hal_error_t hash_get_digest_algorithm_id(const hal_digest_algorithm_t alg, uint8_t *id, size_t *len, const size_t len_max) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(len_max)], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t len32 = len_max; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_GET_DIGEST_LEN)); + check(rpc_encode_int(&optr, olimit, alg)); + check(rpc_encode_int(&optr, olimit, len_max)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_buffer(&iptr, ilimit, id, &len32)); + *len = len32; + } + return rpc_ret; } static hal_error_t hash_get_algorithm(const hal_hash_handle_t hash, hal_digest_algorithm_t *alg) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t alg32; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_GET_ALGORITHM)); + check(rpc_encode_int(&optr, olimit, hash.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &alg32)); + *alg = (hal_digest_algorithm_t)alg32; + } + return rpc_ret; } static hal_error_t hash_initialize(const hal_client_handle_t client, @@ -113,19 +250,68 @@ static hal_error_t hash_initialize(const hal_client_handle_t client, const hal_digest_algorithm_t alg, const uint8_t * const key, const size_t key_len) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[20 + pad(key_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_INITIALIZE)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_int(&optr, olimit, alg)); + check(rpc_encode_buffer(&optr, olimit, key, key_len)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &hash->handle)); + } + return rpc_ret; } static hal_error_t hash_update(const hal_hash_handle_t hash, const uint8_t * data, const size_t length) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12 + pad(length)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_UPDATE)); + check(rpc_encode_int(&optr, olimit, hash.handle)); + check(rpc_encode_buffer(&optr, olimit, data, length)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t hash_finalize(const hal_hash_handle_t hash, uint8_t *digest, const size_t length) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(length)], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t digest_len = length; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_HASH_FINALIZE)); + check(rpc_encode_int(&optr, olimit, hash.handle)); + check(rpc_encode_int(&optr, olimit, length)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_buffer(&iptr, ilimit, digest, &digest_len)); + /* XXX check digest_len vs length */ + } + return rpc_ret; } static hal_error_t pkey_load(const hal_client_handle_t client, @@ -137,7 +323,28 @@ static hal_error_t pkey_load(const hal_client_handle_t client, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[32 + pad(name_len) + pad(der_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_LOAD)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_int(&optr, olimit, type)); + check(rpc_encode_int(&optr, olimit, curve)); + check(rpc_encode_buffer(&optr, olimit, name, name_len)); + check(rpc_encode_buffer(&optr, olimit, der, der_len)); + check(rpc_encode_int(&optr, olimit, flags)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) + check(rpc_decode_int(&iptr, ilimit, &pkey->handle)); + + return rpc_ret; } static hal_error_t pkey_find(const hal_client_handle_t client, @@ -146,7 +353,25 @@ static hal_error_t pkey_find(const hal_client_handle_t client, const hal_key_type_t type, const uint8_t * const name, const size_t name_len) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[20 + pad(name_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_FIND)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_int(&optr, olimit, type)); + check(rpc_encode_buffer(&optr, olimit, name, name_len)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) + check(rpc_decode_int(&iptr, ilimit, &pkey->handle)); + + return rpc_ret; } static hal_error_t pkey_generate_rsa(const hal_client_handle_t client, @@ -157,7 +382,27 @@ static hal_error_t pkey_generate_rsa(const hal_client_handle_t client, const uint8_t * const exp, const size_t exp_len, const hal_key_flags_t flags) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[28 + pad(name_len) + pad(exp_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_RSA)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_buffer(&optr, olimit, name, name_len)); + check(rpc_encode_int(&optr, olimit, key_len)); + check(rpc_encode_buffer(&optr, olimit, exp, exp_len)); + check(rpc_encode_int(&optr, olimit, flags)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) + check(rpc_decode_int(&iptr, ilimit, &pkey->handle)); + + return rpc_ret; } static hal_error_t pkey_generate_ec(const hal_client_handle_t client, @@ -167,40 +412,153 @@ static hal_error_t pkey_generate_ec(const hal_client_handle_t client, const hal_curve_name_t curve, const hal_key_flags_t flags) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[24 + pad(name_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_EC)); + check(rpc_encode_int(&optr, olimit, client.handle)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_buffer(&optr, olimit, name, name_len)); + check(rpc_encode_int(&optr, olimit, curve)); + check(rpc_encode_int(&optr, olimit, flags)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) + check(rpc_decode_int(&iptr, ilimit, &pkey->handle)); + + return rpc_ret; } static hal_error_t pkey_close(const hal_pkey_handle_t pkey) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_CLOSE)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t pkey_delete(const hal_pkey_handle_t pkey) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_DELETE)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; } static hal_error_t pkey_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t type32; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_KEY_TYPE)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &type32)); + *type = (hal_key_type_t)type32; + } + return rpc_ret; } static hal_error_t pkey_get_key_flags(const hal_pkey_handle_t pkey, hal_key_flags_t *flags) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t flags32; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_KEY_FLAGS)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &flags32)); + *flags = (hal_key_flags_t)flags32; + } + return rpc_ret; } static size_t pkey_get_public_key_len(const hal_pkey_handle_t pkey) { - return 0; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t len32; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_PUBLIC_KEY_LEN)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_int(&iptr, ilimit, &len32)); + return (size_t)len32; + } + else + return 0; } static hal_error_t pkey_get_public_key(const hal_pkey_handle_t pkey, uint8_t *der, size_t *der_len, const size_t der_max) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[12], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(der_max)], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t dlen32 = der_max; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_PUBLIC_KEY)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_encode_int(&optr, olimit, der_max)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_buffer(&iptr, ilimit, der, &dlen32)); + *der_len = (size_t)dlen32; + } + return rpc_ret; } static hal_error_t pkey_remote_sign(const hal_session_handle_t session, @@ -209,7 +567,28 @@ static hal_error_t pkey_remote_sign(const hal_session_handle_t session, const uint8_t * const input, const size_t input_len, uint8_t * signature, size_t *signature_len, const size_t signature_max) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[24 + pad(input_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(signature_max)], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t slen32 = signature_max; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_REMOTE_SIGN)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_encode_int(&optr, olimit, hash.handle)); + check(rpc_encode_buffer(&optr, olimit, input, input_len)); + check(rpc_encode_int(&optr, olimit, signature_max)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + check(rpc_decode_buffer(&iptr, ilimit, signature, &slen32)); + *signature_len = (size_t)slen32; + } + return rpc_ret; } static hal_error_t pkey_remote_verify(const hal_session_handle_t session, @@ -218,14 +597,66 @@ static hal_error_t pkey_remote_verify(const hal_session_handle_t session, const uint8_t * const input, const size_t input_len, const uint8_t * const signature, const size_t signature_len) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[24 + pad(input_len) + pad(signature_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[4], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_REMOTE_VERIFY)); + check(rpc_encode_int(&optr, olimit, session.handle)); + check(rpc_encode_int(&optr, olimit, pkey.handle)); + check(rpc_encode_int(&optr, olimit, hash.handle)); + check(rpc_encode_buffer(&optr, olimit, input, input_len)); + check(rpc_encode_buffer(&optr, olimit, signature, signature_len)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + return rpc_ret; +} + +static hal_error_t rpc_decode_pkey_info(uint8_t **iptr, const uint8_t * const ilimit, hal_pkey_info_t *info) +{ + uint32_t i32; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &i32)); info->type = i32; + check(rpc_decode_int(iptr, ilimit, &i32)); info->curve = i32; + check(rpc_decode_int(iptr, ilimit, &i32)); info->flags = i32; + check(rpc_decode_buffer(iptr, ilimit, (uint8_t *)&info->name[0], &i32)); info->name_len = i32; + return HAL_OK; } static hal_error_t pkey_list(hal_pkey_info_t *result, unsigned *result_len, const unsigned result_max) { - return HAL_ERROR_IMPOSSIBLE; + uint8_t outbuf[8], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[8 + pad(result_max * sizeof(hal_pkey_info_t))], *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + size_t ilen = sizeof(inbuf); + uint32_t len; + hal_error_t ret, rpc_ret; + + check(rpc_encode_int(&optr, olimit, RPC_FUNC_PKEY_LIST)); + check(rpc_encode_int(&optr, olimit, result_max)); + check(rpc_send(outbuf, optr - outbuf)); + + check(rpc_recv(inbuf, &ilen)); + assert(ilen <= sizeof(inbuf)); + check(rpc_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + int i; + check(rpc_decode_int(&iptr, ilimit, &len)); + *result_len = len; + for (i = 0; i < len; ++i) { + if ((ret = rpc_decode_pkey_info(&iptr, ilimit, &result[i])) != HAL_OK) { + *result_len = 0; + return ret; + } + } + } + return rpc_ret; } @@ -317,6 +748,40 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = { pkey_list }; +const hal_rpc_misc_dispatch_t * hal_rpc_misc_dispatch; +const hal_rpc_hash_dispatch_t * hal_rpc_hash_dispatch; +const hal_rpc_pkey_dispatch_t * hal_rpc_pkey_dispatch; + +hal_error_t rpc_client_init(rpc_locality_t locality) +{ + switch (locality) { + case RPC_LOCAL: + hal_rpc_misc_dispatch = &hal_rpc_local_misc_dispatch; + hal_rpc_hash_dispatch = &hal_rpc_local_hash_dispatch; + hal_rpc_pkey_dispatch = &hal_rpc_local_pkey_dispatch; + break; + case RPC_REMOTE: + hal_rpc_misc_dispatch = &hal_rpc_remote_misc_dispatch; + hal_rpc_hash_dispatch = &hal_rpc_remote_hash_dispatch; + hal_rpc_pkey_dispatch = &hal_rpc_remote_pkey_dispatch; + break; + case RPC_MIXED: + hal_rpc_misc_dispatch = &hal_rpc_remote_misc_dispatch; + hal_rpc_hash_dispatch = &hal_rpc_remote_hash_dispatch; + hal_rpc_pkey_dispatch = &hal_rpc_mixed_pkey_dispatch; + break; + default: + return HAL_ERROR_BAD_ARGUMENTS; + } + return rpc_client_transport_init(); +} + +hal_error_t rpc_client_close(void) +{ + return rpc_client_transport_close(); +} + + /* * Local variables: * indent-tabs-mode: nil diff --git a/rpc_client_loopback.c b/rpc_client_loopback.c new file mode 100644 index 0000000..a3d7e73 --- /dev/null +++ b/rpc_client_loopback.c @@ -0,0 +1,85 @@ +/* + * rpc_client_loopback.c + * --------------------- + * Remote procedure call transport over loopback socket. + * + * Copyright (c) 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> /* close */ + +#include "hal.h" +#include "hal_internal.h" + +static int sock = -1; + +hal_error_t rpc_client_transport_init(void) +{ + struct sockaddr_in sin; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) + return perror("socket"), HAL_ERROR_RPC_TRANSPORT; + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sin.sin_port = 17425; + if (connect(sock, (const struct sockaddr *)&sin, sizeof(sin)) != 0) + return perror("connect"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_client_transport_close(void) +{ + int ret = close(sock); + sock = -1; + if (ret != 0) + return perror("close"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_send(const uint8_t * const buf, const size_t len) +{ + if (send(sock, buf, len, 0) == -1) + return perror("send"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_recv(uint8_t * const buf, size_t * const len) +{ + int ret; + + if ((ret = recv(sock, buf, *len, 0)) == -1) + return HAL_ERROR_RPC_TRANSPORT; + *len = ret; + return HAL_OK; +} @@ -4,7 +4,7 @@ * Remote procedure call server-side hash implementation. * * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * 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 @@ -143,6 +143,12 @@ static inline handle_slot_t *find_handle(const hal_hash_handle_t handle) return NULL; } +static inline free_handle(handle_slot_t *slot) +{ + /* state is a union, so this this works for hash and hmac */ + slot->state.hash = NULL; +} + /* * Translate an algorithm number to a descriptor. */ @@ -234,6 +240,7 @@ static hal_error_t initialize(const hal_client_handle_t client, { const hal_hash_descriptor_t *descriptor; handle_slot_t *slot; + hal_error_t err; if (hash == NULL) return HAL_ERROR_BAD_ARGUMENTS; @@ -241,16 +248,20 @@ static hal_error_t initialize(const hal_client_handle_t client, if ((descriptor = alg_to_descriptor(alg)) == NULL) return HAL_ERROR_BAD_ARGUMENTS; - if ((slot = alloc_handle(key != NULL)) == NULL) + if ((slot = alloc_handle(key_len != 0)) == NULL) return HAL_ERROR_ALLOCATION_FAILURE; slot->client_handle = client; slot->session_handle = session; + *hash = slot->hash_handle; - if (key == NULL) - return hal_hash_initialize(NULL, descriptor, &slot->state.hash, NULL, 0); + if (key_len == 0) + err = hal_hash_initialize(NULL, descriptor, &slot->state.hash, NULL, 0); else - return hal_hmac_initialize(NULL, descriptor, &slot->state.hmac, NULL, 0, key, key_len); + err = hal_hmac_initialize(NULL, descriptor, &slot->state.hmac, NULL, 0, key, key_len); + if (err != HAL_OK) + free_handle(slot); + return err; } static hal_error_t update(const hal_hash_handle_t handle, @@ -286,6 +297,7 @@ static hal_error_t finalize(const hal_hash_handle_t handle, hal_hmac_cleanup(&slot->state.hmac); } + free_handle(slot); return err; } diff --git a/rpc_server.c b/rpc_server.c new file mode 100644 index 0000000..3447c53 --- /dev/null +++ b/rpc_server.c @@ -0,0 +1,709 @@ +/* + * rpc_server.c + * ------------ + * Remote procedure call server-side private API implementation. + * + * Copyright (c) 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 "hal.h" +#include "hal_internal.h" + +/* + * RPC calls. + */ + +#define check(op) if ((ret = (op)) != HAL_OK) return ret; + +#define pad(n) (((n) + 3) & ~3) + +static hal_error_t get_random(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + uint32_t length; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &length)); + /* sanity check length */ + if (length == 0 || length > olimit - *optr - 4) + return HAL_ERROR_IO_BAD_COUNT; /* need a better error */ + + /* call the local function */ + /* get the data directly into the output buffer */ + check(rpc_encode_int(optr, olimit, length)); + ret = hal_rpc_local_misc_dispatch.get_random(*optr, (size_t)length); + if (ret == HAL_OK) + *optr += pad(length); + else + /* don't return data if error */ + *optr -= 4; + + return ret; +} + +static hal_error_t set_pin(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_user_t user; + uint8_t *pin; + uint32_t pin_len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &user)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &pin, &pin_len)); + + /* call the local function */ + ret = hal_rpc_local_misc_dispatch.set_pin(client, user, (const char * const)pin, pin_len); + return ret; +} + +static hal_error_t login(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_user_t user; + uint8_t *pin; + uint32_t pin_len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &user)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &pin, &pin_len)); + + /* call the local function */ + ret = hal_rpc_local_misc_dispatch.login(client, user, (const char * const)pin, pin_len); + return ret; +} + +static hal_error_t logout(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + + /* call the local function */ + ret = hal_rpc_local_misc_dispatch.logout(client); + return ret; +} + +static hal_error_t logout_all(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_error_t ret; + + /* call the local function */ + ret = hal_rpc_local_misc_dispatch.logout_all(); + return ret; +} + +static hal_error_t is_logged_in(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_user_t user; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &user)); + + /* call the local function */ + ret = hal_rpc_local_misc_dispatch.is_logged_in(client, user); + return ret; +} + +static hal_error_t hash_get_digest_len(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_digest_algorithm_t alg; + size_t length; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &alg)); + + /* call the local function */ + ret = hal_rpc_local_hash_dispatch.get_digest_length(alg, &length); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, length)); + return ret; +} + +static hal_error_t hash_get_digest_algorithm_id(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_digest_algorithm_t alg; + size_t len; + uint32_t len_max; + uint8_t *optr_orig = *optr; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &alg)); + check(rpc_decode_int(iptr, ilimit, &len_max)); + /* sanity check len_max */ + if (len_max > olimit - *optr - 4) + return HAL_ERROR_IO_BAD_COUNT; /* need a better error */ + + /* call the local function */ + /* get the data directly into the output buffer */ + *optr += 4; /* reserve 4 bytes for length */ + ret = hal_rpc_local_hash_dispatch.get_digest_algorithm_id(alg, *optr, &len, (size_t)len_max); + if (ret == HAL_OK) { + *optr = optr_orig; + check(rpc_encode_int(optr, olimit, len)); + *optr += pad(len); + } + else { + /* don't return data if error */ + *optr = optr_orig; + } + return ret; +} + +static hal_error_t hash_get_algorithm(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_hash_handle_t hash; + hal_digest_algorithm_t alg; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &hash.handle)); + + /* call the local function */ + ret = hal_rpc_local_hash_dispatch.get_algorithm(hash, &alg); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, alg)); + return ret; +} + +static hal_error_t hash_initialize(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_hash_handle_t hash; + uint32_t alg; + uint8_t *key; + uint32_t key_len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_int(iptr, ilimit, &alg)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &key, &key_len)); + + /* call the local function */ + ret = hal_rpc_local_hash_dispatch.initialize(client, session, &hash, (hal_digest_algorithm_t)alg, key, (size_t)key_len); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, hash.handle)); + return ret; +} + +static hal_error_t hash_update(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_hash_handle_t hash; + uint8_t *data; + uint32_t length; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &hash.handle)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &data, &length)); + + /* call the local function */ + ret = hal_rpc_local_hash_dispatch.update(hash, data, (size_t)length); + return ret; +} + +static hal_error_t hash_finalize(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_hash_handle_t hash; + uint32_t length; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &hash.handle)); + check(rpc_decode_int(iptr, ilimit, &length)); + /* sanity check length */ + if (length == 0 || length > olimit - *optr - 4) + return HAL_ERROR_IO_BAD_COUNT; /* need a better error */ + + /* call the local function */ + /* get the data directly into the output buffer */ + check(rpc_encode_int(optr, olimit, length)); + ret = hal_rpc_local_hash_dispatch.finalize(hash, *optr, (size_t)length); + if (ret == HAL_OK) + *optr += pad(length); + else + /* don't return data if error */ + *optr -= 4; + return ret; +} + +static hal_error_t pkey_load(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_pkey_handle_t pkey; + hal_key_type_t type; + hal_curve_name_t curve; + uint8_t *name, *der; + uint32_t name_len, der_len; + hal_key_flags_t flags; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_int(iptr, ilimit, &type)); + check(rpc_decode_int(iptr, ilimit, &curve)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &der, &der_len)); + check(rpc_decode_int(iptr, ilimit, &flags)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.load(client, session, &pkey, type, curve, name, name_len, der, der_len, flags); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, pkey.handle)); + return ret; +} + +static hal_error_t pkey_find(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_pkey_handle_t pkey; + hal_key_type_t type; + uint8_t *name; + uint32_t name_len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_int(iptr, ilimit, &type)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.find(client, session, &pkey, type, name, name_len); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, pkey.handle)); + return ret; +} + +static hal_error_t pkey_generate_rsa(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_pkey_handle_t pkey; + uint8_t *name; + uint32_t name_len; + unsigned key_len; + uint8_t *exp; + uint32_t exp_len; + hal_key_flags_t flags; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); + check(rpc_decode_int(iptr, ilimit, &key_len)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &exp, &exp_len)); + check(rpc_decode_int(iptr, ilimit, &flags)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.generate_rsa(client, session, &pkey, name, name_len, key_len, exp, exp_len, flags); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, pkey.handle)); + return ret; +} + +static hal_error_t pkey_generate_ec(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + hal_session_handle_t session; + hal_pkey_handle_t pkey; + uint8_t *name; + uint32_t name_len; + hal_curve_name_t curve; + hal_key_flags_t flags; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &client.handle)); + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); + check(rpc_decode_int(iptr, ilimit, &curve)); + check(rpc_decode_int(iptr, ilimit, &flags)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.generate_ec(client, session, &pkey, name, name_len, curve, flags); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, pkey.handle)); + return ret; +} + +static hal_error_t pkey_close(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.close(pkey); + return ret; +} + +static hal_error_t pkey_delete(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.delete(pkey); + return ret; +} + +static hal_error_t pkey_get_key_type(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + hal_key_type_t type; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.get_key_type(pkey, &type); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, type)); + return ret; +} + +static hal_error_t pkey_get_key_flags(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + hal_key_flags_t flags; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.get_key_flags(pkey, &flags); + if (ret == HAL_OK) + check(rpc_encode_int(optr, olimit, flags)); + return ret; +} + +static hal_error_t pkey_get_public_key_len(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + size_t len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + + /* call the local function */ + len = hal_rpc_local_pkey_dispatch.get_public_key_len(pkey); + check(rpc_encode_int(optr, olimit, len)); + return HAL_OK; +} + +static hal_error_t pkey_get_public_key(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_pkey_handle_t pkey; + size_t len; + uint32_t len_max; + uint8_t *optr_orig = *optr; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + check(rpc_decode_int(iptr, ilimit, &len_max)); + /* sanity check len_max */ + if (len_max > olimit - *optr - 4) + return HAL_ERROR_IO_BAD_COUNT; /* need a better error */ + + /* call the local function */ + /* get the data directly into the output buffer */ + *optr += 4; /* reserve 4 bytes for length */ + ret = hal_rpc_local_pkey_dispatch.get_public_key(pkey, *optr, &len, len_max); + if (ret == HAL_OK) { + *optr = optr_orig; + check(rpc_encode_int(optr, olimit, len)); + *optr += pad(len); + } + else { + /* don't return data if error */ + *optr = optr_orig; + } + return ret; +} + +static hal_error_t pkey_remote_sign(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_session_handle_t session; + hal_pkey_handle_t pkey; + hal_hash_handle_t hash; + uint8_t *input; + uint32_t input_len; + uint32_t sig_max; + size_t sig_len; + uint8_t *optr_orig = *optr; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + check(rpc_decode_int(iptr, ilimit, &hash.handle)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &input, &input_len)); + check(rpc_decode_int(iptr, ilimit, &sig_max)); + /* sanity check sig_max */ + if (sig_max > olimit - *optr - 4) + return HAL_ERROR_IO_BAD_COUNT; /* need a better error */ + + /* call the local function */ + /* get the data directly into the output buffer */ + *optr += 4; /* reserve 4 bytes for length */ + ret = hal_rpc_local_pkey_dispatch.sign(session, pkey, hash, input, input_len, *optr, &sig_len, sig_max); + *optr = optr_orig; + if (ret == HAL_OK) { + check(rpc_encode_int(optr, olimit, sig_len)); + *optr += pad(sig_len); + } + return ret; +} + +static hal_error_t pkey_remote_verify(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_session_handle_t session; + hal_pkey_handle_t pkey; + hal_hash_handle_t hash; + uint8_t *input; + uint32_t input_len; + uint8_t *sig; + uint32_t sig_len; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &session.handle)); + check(rpc_decode_int(iptr, ilimit, &pkey.handle)); + check(rpc_decode_int(iptr, ilimit, &hash.handle)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &input, &input_len)); + check(rpc_decode_buffer_in_place(iptr, ilimit, &sig, &sig_len)); + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.verify(session, pkey, hash, input, input_len, sig, sig_len); + return ret; +} + +static hal_error_t rpc_encode_pkey_info(uint8_t **optr, const uint8_t * const olimit, const hal_pkey_info_t *info) +{ + uint8_t *optr_orig = *optr; + hal_error_t ret; + + if ((ret = rpc_encode_int(optr, olimit, info->type)) != HAL_OK || + (ret = rpc_encode_int(optr, olimit, info->curve)) != HAL_OK || + (ret = rpc_encode_int(optr, olimit, info->flags)) != HAL_OK || + (ret = rpc_encode_buffer(optr, olimit, (uint8_t *)&info->name[0], info->name_len)) != HAL_OK) + *optr = optr_orig; + return ret; +} + + +static hal_error_t pkey_list(uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + uint8_t *optr_orig = *optr; + uint32_t result_max; + hal_error_t ret; + + check(rpc_decode_int(iptr, ilimit, &result_max)); + + hal_pkey_info_t result[result_max]; + unsigned result_len; + + /* call the local function */ + ret = hal_rpc_local_pkey_dispatch.list(result, &result_len, result_max); + if (ret == HAL_OK) { + int i; + check(rpc_encode_int(optr, olimit, result_len)); + for (i = 0; i < result_len; ++i) { + if ((ret = rpc_encode_pkey_info(optr, olimit, &result[i])) != HAL_OK) { + *optr = optr_orig; + break; + } + } + } + return ret; +} + +#define MAX_PKT_SIZE 1024 +#define interrupt 0 + +void rpc_server_main(void) +{ + uint8_t inbuf[MAX_PKT_SIZE], outbuf[MAX_PKT_SIZE]; + uint8_t *iptr, *ilimit, *optr, *olimit; + size_t ilen, olen; + rpc_func_num_t rpc_func_num; + void *opaque; + hal_error_t ret; + + while (!interrupt) { + ilen = sizeof(inbuf); + if (rpc_recvfrom(inbuf, &ilen, &opaque) == HAL_OK) { + iptr = inbuf; + ilimit = inbuf + ilen; + optr = outbuf + 4; /* reserve 4 bytes for return code */ + olimit = outbuf + sizeof(outbuf); + rpc_decode_int(&iptr, ilimit, &rpc_func_num); + switch (rpc_func_num) { + case RPC_FUNC_GET_RANDOM: + ret = get_random(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_SET_PIN: + ret = set_pin(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_LOGIN: + ret = login(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_LOGOUT: + ret = logout(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_LOGOUT_ALL: + ret = logout_all(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_IS_LOGGED_IN: + ret = is_logged_in(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_GET_DIGEST_LEN: + ret = hash_get_digest_len(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_GET_DIGEST_ALGORITHM_ID: + ret = hash_get_digest_algorithm_id(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_GET_ALGORITHM: + ret = hash_get_algorithm(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_INITIALIZE: + ret = hash_initialize(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_UPDATE: + ret = hash_update(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_HASH_FINALIZE: + ret = hash_finalize(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_LOAD: + ret = pkey_load(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_FIND: + ret = pkey_find(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GENERATE_RSA: + ret = pkey_generate_rsa(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GENERATE_EC: + ret = pkey_generate_ec(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_CLOSE: + ret = pkey_close(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_DELETE: + ret = pkey_delete(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GET_KEY_TYPE: + ret = pkey_get_key_type(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GET_KEY_FLAGS: + ret = pkey_get_key_flags(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GET_PUBLIC_KEY_LEN: + ret = pkey_get_public_key_len(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GET_PUBLIC_KEY: + ret = pkey_get_public_key(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_REMOTE_SIGN: + ret = pkey_remote_sign(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_REMOTE_VERIFY: + ret = pkey_remote_verify(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_LIST: + ret = pkey_list(&iptr, ilimit, &optr, olimit); + break; + default: + ret = HAL_ERROR_BAD_ARGUMENTS; /* need a better error */ + break; + } + /* encode the return code at the beginning of the payload */ + olen = optr - outbuf; + optr = outbuf; + rpc_encode_int(&optr, olimit, ret); + rpc_sendto(outbuf, olen, opaque); + } + } +} + +/* + * Dispatch vectors. + */ + +const hal_rpc_misc_dispatch_t *hal_rpc_misc_dispatch = &hal_rpc_local_misc_dispatch; +const hal_rpc_hash_dispatch_t *hal_rpc_hash_dispatch = &hal_rpc_local_hash_dispatch; +const hal_rpc_pkey_dispatch_t *hal_rpc_pkey_dispatch = &hal_rpc_local_pkey_dispatch; + +hal_error_t rpc_server_init(void) +{ + return rpc_server_transport_init(); +} + +hal_error_t rpc_server_close(void) +{ + return rpc_server_transport_close(); +} + + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ diff --git a/rpc_server_loopback.c b/rpc_server_loopback.c new file mode 100644 index 0000000..a39e12b --- /dev/null +++ b/rpc_server_loopback.c @@ -0,0 +1,89 @@ +/* + * rpc_server_loopback.c + * --------------------- + * Remote procedure call transport over loopback socket. + * + * Copyright (c) 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> /* close */ + +#include "hal.h" +#include "hal_internal.h" + +static int sock; + +hal_error_t rpc_server_transport_init(void) +{ + struct sockaddr_in sin; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) + return perror("socket"), HAL_ERROR_RPC_TRANSPORT; + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sin.sin_port = 17425; + if (bind(sock, (const struct sockaddr *)&sin, sizeof(sin)) != 0) + return perror("bind"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_server_transport_close(void) +{ + if (close(sock) != 0) + return perror("close"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_sendto(const uint8_t * const buf, const size_t len, void *opaque) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)opaque; + int ret; + + if ((ret = sendto(sock, buf, len, 0, (struct sockaddr *)sin, sizeof(*sin))) == -1) + return perror("sendto"), HAL_ERROR_RPC_TRANSPORT; + return HAL_OK; +} + +hal_error_t rpc_recvfrom(uint8_t * const buf, size_t * const len, void **opaque) +{ + static struct sockaddr_in sin; + socklen_t sin_len = sizeof(sin); + int ret; + + if ((ret = recvfrom(sock, buf, *len, 0, (struct sockaddr *)&sin, &sin_len)) == -1) + return HAL_ERROR_RPC_TRANSPORT; + *opaque = (void *)&sin; + *len = ret; + return HAL_OK; +} diff --git a/rpc_xdr.c b/rpc_xdr.c new file mode 100644 index 0000000..69b8482 --- /dev/null +++ b/rpc_xdr.c @@ -0,0 +1,245 @@ +/* + * rpc_xdr.c + * --------- + * Serialization/deserialization routines, using XDR (RFC 4506) encoding. + * + * Copyright (c) 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> /* memcpy */ +#include <strings.h> /* bzero */ +#include <arpa/inet.h> /* htonl/ntohl */ + +#include "hal.h" + +/* encode/decode_int. This covers int, unsigned int, enum, and bool types, + * which are all encoded as 32-bit big-endian fields. Signed integers are + * defined to use two's complement, but that's universal these days, yes? + */ + +hal_error_t rpc_encode_int(uint8_t ** const outbuf, const uint8_t * const limit, const uint32_t value) +{ + /* arg checks */ + if (outbuf == NULL || *outbuf == NULL || limit == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + /* buffer overflow check */ + if (limit - *outbuf < sizeof(value)) + return HAL_ERROR_IO_BAD_COUNT; + + **(uint32_t **)outbuf = htonl(value); + *outbuf += sizeof(value); + return HAL_OK; +} + +hal_error_t rpc_decode_int(uint8_t **inbuf, const uint8_t * const limit, uint32_t *value) +{ + /* arg checks */ + if (inbuf == NULL || *inbuf == NULL || limit == NULL || value == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + /* buffer overflow check */ + if (limit - *inbuf < sizeof(*value)) + return HAL_ERROR_IO_BAD_COUNT; + + *value = ntohl(**(uint32_t **)inbuf); + *inbuf += sizeof(*value); + return HAL_OK; +} + +/* encode/decode_buffer. This covers variable-length string and opaque types. + * The data is preceded by a 4-byte length word (encoded as above), and padded + * to a multiple of 4 bytes as necessary. + */ + +hal_error_t rpc_encode_buffer(uint8_t **outbuf, const uint8_t * const limit, const uint8_t *value, const uint32_t len) +{ + hal_error_t ret; + + /* arg checks */ + if (outbuf == NULL || *outbuf == NULL || limit == NULL || + (value == NULL && len != 0)) + return HAL_ERROR_BAD_ARGUMENTS; + + /* buffer overflow check */ + if ((limit - *outbuf) < (((len + 3) & ~3) + sizeof(len))) + return HAL_ERROR_IO_BAD_COUNT; + + /* encode length */ + if ((ret = rpc_encode_int(outbuf, limit, len)) != HAL_OK) + return ret; + + /* write the string or opaque data */ + memcpy(*outbuf, value, len); + *outbuf += len; + + /* pad if necessary */ + if (len & 3) { + size_t n = 4 - (len & 3); + bzero(*outbuf, n); + *outbuf += n; + } + + return HAL_OK; +} + +/* This version returns a pointer to the data in the input buffer. + * It is used in the rpc server. + */ +hal_error_t rpc_decode_buffer_in_place(uint8_t **inbuf, const uint8_t * const limit, uint8_t ** const value, uint32_t * const len) +{ + hal_error_t ret; + uint32_t xdr_len; + uint8_t *orig_inbuf = *inbuf; + + /* arg checks */ + if (inbuf == NULL || *inbuf == NULL || limit == NULL || value == NULL || len == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + /* decode the length */ + if ((ret = rpc_decode_int(inbuf, limit, &xdr_len)) != HAL_OK) + return ret; + + /* input and output buffer overflow checks vs decoded length */ + + /* decoded length is past the end of the input buffer; + * we're probably out of sync, but nothing we can do now + */ + if (limit - *inbuf < xdr_len) { + /* undo read of length */ + *inbuf = orig_inbuf; + return HAL_ERROR_IO_BAD_COUNT; + } + + /* user buffer is too small, update *len + */ + if (*len < xdr_len) { + *len = xdr_len; + /* undo read of length */ + *inbuf = orig_inbuf; + return HAL_ERROR_IO_BAD_COUNT; + } + + /* return a pointer to the string or opaque data */ + *value = *inbuf; + *len = xdr_len; + + /* update the buffer pointer, skipping any padding bytes */ + *inbuf += (xdr_len + 3) & ~3; + + return HAL_OK; +} + +/* This version copies the data to the user-supplied buffer. + * It is used in the rpc client. + */ +hal_error_t rpc_decode_buffer(uint8_t **inbuf, const uint8_t * const limit, uint8_t * const value, uint32_t * const len) +{ + hal_error_t ret; + uint8_t *vptr; + + if ((ret = rpc_decode_buffer_in_place(inbuf, limit, &vptr, len)) == HAL_OK) + memcpy(value, vptr, *len); + return ret; +} + +#ifdef TEST +void hexdump(uint8_t *buf, uint32_t len) +{ + int i; + + for (i = 0; i < len; ++i) { + uint8_t c = buf[i]; + printf("%02x ", c); + if ((i & 0x07) == 0x07) + printf("\n"); + } + if ((len & 0x07) != 0) + printf("\n"); +} + +int main(int argc, char *argv[]) +{ + uint32_t i; + uint8_t buf[64] = {0}; + uint8_t *bufptr = buf, *readptr; + uint8_t *limit = buf + sizeof(buf); + hal_error_t ret; + uint8_t alphabet[] = "abcdefghijklmnopqrstuvwxyz"; + uint8_t readbuf[64] = {0}; + + printf("rpc_encode_int: work to failure\n"); + for (i = 1; i < 100; ++i) { + if ((ret = rpc_encode_int(&bufptr, limit, i)) != HAL_OK) { + printf("%d: %s\n", i, hal_error_string(ret)); + break; + } + } + hexdump(buf, ((uint8_t *)bufptr - buf)); + + printf("\nrpc_decode_int:\n"); + readptr = buf; + while (readptr < bufptr) { + if ((ret = rpc_decode_int(&readptr, limit, &i)) != HAL_OK) { + printf("%s\n", hal_error_string(ret)); + break; + } + printf("%u ", i); + } + printf("\n"); + + printf("\nrpc_encode_buffer: work to failure\n"); + bzero(buf, sizeof(buf)); + bufptr = buf; + for (i = 1; i < 10; ++i) { + if ((ret = rpc_encode_buffer(&bufptr, limit, alphabet, i)) != HAL_OK) { + printf("%d: %s\n", i, hal_error_string(ret)); + break; + } + } + hexdump(buf, ((uint8_t *)bufptr - buf)); + + printf("\nrpc_decode_buffer:\n"); + readptr = buf; + i = sizeof(readbuf); + while (readptr < bufptr) { + if ((ret = rpc_decode_buffer(&readptr, limit, readbuf, &i)) != HAL_OK) { + printf("%s\n", hal_error_string(ret)); + break; + } + printf("%u: ", i); for (int j = 0; j < i; ++j) putchar(readbuf[j]); putchar('\n'); + i = sizeof(readbuf); + bzero(readbuf, sizeof(readbuf)); + } + + return 0; +} +#endif diff --git a/tests/GNUmakefile b/tests/GNUmakefile index ba515f7..2f026a1 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -30,6 +30,7 @@ INC = ../hal.h LIB = ../libhal.a BIN = test-aes-key-wrap test-hash test-pbkdf2 test-ecdsa test-bus test-trng test-rsa +BIN += test-rpc_hash test-rpc_server CFLAGS = -g3 -Wall -fPIC -std=c99 -I.. diff --git a/tests/test-rpc_hash.c b/tests/test-rpc_hash.c new file mode 100644 index 0000000..d59e341 --- /dev/null +++ b/tests/test-rpc_hash.c @@ -0,0 +1,698 @@ +/* + * 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> +#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_server.c b/tests/test-rpc_server.c new file mode 100644 index 0000000..6eff755 --- /dev/null +++ b/tests/test-rpc_server.c @@ -0,0 +1,16 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include <hal.h> +#include <hal_internal.h> + +int main (int argc, char *argv[]) +{ + if (rpc_server_init() != HAL_OK) + return 1; + + rpc_server_main(); + return 0; +} |