aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2019-04-02 00:58:41 -0400
committerPaul Selkirk <paul@psgd.org>2019-04-02 00:58:41 -0400
commit6b0c67ace3678325443aa21a32b2b10daa018e27 (patch)
tree65d49218a1c57ca67aff2859a4e5a4530b7daeaa
parent5e420cb84a401a04557d63a60d30f42699270509 (diff)
Small cleanups in RPC code, e.g. to support null arguments.
- Add support for null pointer arguments in RPCs for get_digest_algorithm_id and get_public_key. This is years overdue, and would have obviated the need for get_public_key_len as a separate RPC. - Refactor pkey_local_get_public_key_len in terms of pkey_local_get_public_key. - Add more parameter sanity checks to rpc_api.c. - Add a len_max parameter to hal_xdr_decode_variable_opaque, rather than having len be an in/out parameter. This brings xdr slightly more in line with the rest of the code base (again after literal years), and slightly simplifies several calls in rpc_client.c.
-rw-r--r--rpc_api.c8
-rw-r--r--rpc_client.c64
-rw-r--r--rpc_pkey.c135
-rw-r--r--rpc_server.c16
-rw-r--r--tests/test-xdr.c4
-rw-r--r--xdr.c7
-rw-r--r--xdr_internal.h2
7 files changed, 111 insertions, 125 deletions
diff --git a/rpc_api.c b/rpc_api.c
index f468d63..97c8e99 100644
--- a/rpc_api.c
+++ b/rpc_api.c
@@ -120,6 +120,8 @@ static inline int check_pkey_type_curve_flags(const hal_key_type_t type,
hal_error_t hal_rpc_get_version(uint32_t *version)
{
+ if (version == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
return hal_rpc_misc_dispatch->get_version(version);
}
@@ -184,6 +186,8 @@ hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, siz
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)
{
+ if (id == NULL && len_max != 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
return hal_rpc_hash_dispatch->get_digest_algorithm_id(alg, id, len, len_max);
}
@@ -200,7 +204,7 @@ hal_error_t hal_rpc_hash_initialize(const hal_client_handle_t client,
const hal_digest_algorithm_t alg,
const uint8_t * const key, const size_t key_len)
{
- if (hash == NULL)
+ if (hash == NULL || (key == NULL && key_len != 0))
return HAL_ERROR_BAD_ARGUMENTS;
return hal_rpc_hash_dispatch->initialize(client, session, hash, alg, key, key_len);
}
@@ -328,7 +332,7 @@ size_t hal_rpc_pkey_get_public_key_len(const hal_pkey_handle_t pkey)
hal_error_t hal_rpc_pkey_get_public_key(const hal_pkey_handle_t pkey,
uint8_t *der, size_t *der_len, const size_t der_max)
{
- if (der == NULL || der_len == NULL || der_max == 0)
+ if (der == NULL && der_max != 0)
return HAL_ERROR_BAD_ARGUMENTS;
return hal_rpc_pkey_dispatch->get_public_key(pkey, der, der_len, der_max);
}
diff --git a/rpc_client.c b/rpc_client.c
index 547f929..c9ac9b7 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -137,7 +137,7 @@ static hal_error_t get_random(void *buffer, const size_t length)
uint8_t outbuf[nargs(3)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(4) + pad(length)];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t rcvlen = length;
+ size_t rcvlen;
hal_client_handle_t dummy_client = {0};
hal_error_t rpc_ret;
@@ -150,7 +150,7 @@ static hal_error_t get_random(void *buffer, const size_t length)
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, buffer, &rcvlen));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, buffer, &rcvlen, length));
// XXX check rcvlen vs length
}
return rpc_ret;
@@ -310,8 +310,12 @@ static hal_error_t hash_get_digest_algorithm_id(const hal_digest_algorithm_t alg
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- *len = len_max;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, id, len));
+ uint32_t len32;
+ check(hal_xdr_decode_int(&iptr, ilimit, &len32));
+ if (len != NULL)
+ *len = len32;
+ if (id != NULL)
+ check(hal_xdr_decode_fixed_opaque(&iptr, ilimit, id, len32));
}
return rpc_ret;
}
@@ -394,7 +398,7 @@ static hal_error_t hash_finalize(const hal_hash_handle_t hash,
uint8_t outbuf[nargs(4)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(4) + pad(length)];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t digest_len = length;
+ size_t digest_len;
hal_client_handle_t dummy_client = {0};
hal_error_t rpc_ret;
@@ -408,7 +412,7 @@ static hal_error_t hash_finalize(const hal_hash_handle_t hash,
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, digest, &digest_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, digest, &digest_len, length));
/* XXX check digest_len vs length */
}
return rpc_ret;
@@ -424,7 +428,7 @@ static hal_error_t pkey_remote_load(const hal_client_handle_t client,
uint8_t outbuf[nargs(5) + pad(der_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t name_len = sizeof(name->uuid);
+ size_t name_len;
hal_error_t rpc_ret;
check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_LOAD));
@@ -439,7 +443,7 @@ static hal_error_t pkey_remote_load(const hal_client_handle_t client,
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
if (name_len != sizeof(name->uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
@@ -483,7 +487,7 @@ static hal_error_t pkey_remote_generate_rsa(const hal_client_handle_t client,
uint8_t outbuf[nargs(6) + pad(exp_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t name_len = sizeof(name->uuid);
+ size_t name_len;
hal_error_t rpc_ret;
check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_RSA));
@@ -500,7 +504,7 @@ static hal_error_t pkey_remote_generate_rsa(const hal_client_handle_t client,
if (rpc_ret == HAL_OK) {
check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
if (name_len != sizeof(name->uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
@@ -518,7 +522,7 @@ static hal_error_t pkey_remote_generate_ec(const hal_client_handle_t client,
uint8_t outbuf[nargs(5)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t name_len = sizeof(name->uuid);
+ size_t name_len;
hal_error_t rpc_ret;
check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_EC));
@@ -534,7 +538,7 @@ static hal_error_t pkey_remote_generate_ec(const hal_client_handle_t client,
if (rpc_ret == HAL_OK) {
check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
if (name_len != sizeof(name->uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
@@ -554,7 +558,7 @@ static hal_error_t pkey_remote_generate_hashsig(const hal_client_handle_t client
uint8_t outbuf[nargs(7)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t name_len = sizeof(name->uuid);
+ size_t name_len;
hal_error_t rpc_ret;
check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_HASHSIG));
@@ -572,7 +576,7 @@ static hal_error_t pkey_remote_generate_hashsig(const hal_client_handle_t client
if (rpc_ret == HAL_OK) {
check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
if (name_len != sizeof(name->uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
@@ -736,8 +740,12 @@ static hal_error_t pkey_remote_get_public_key(const hal_pkey_handle_t pkey,
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- *der_len = der_max;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, der, der_len));
+ uint32_t len32;
+ check(hal_xdr_decode_int(&iptr, ilimit, &len32));
+ if (der_len != NULL)
+ *der_len = len32;
+ if (der != NULL)
+ check(hal_xdr_decode_fixed_opaque(&iptr, ilimit, der, len32));
}
return rpc_ret;
}
@@ -764,10 +772,8 @@ static hal_error_t pkey_remote_sign(const hal_pkey_handle_t pkey,
check(read_matching_packet(RPC_FUNC_PKEY_SIGN, inbuf, sizeof(inbuf), &iptr, &ilimit));
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
- if (rpc_ret == HAL_OK) {
- *signature_len = signature_max;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, signature, signature_len));
- }
+ if (rpc_ret == HAL_OK)
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, signature, signature_len, signature_max));
return rpc_ret;
}
@@ -850,8 +856,8 @@ static hal_error_t pkey_remote_match(const hal_client_handle_t client,
*state = ustate;
check(hal_xdr_decode_int(&iptr, ilimit, &array_len));
for (int i = 0; i < array_len; ++i) {
- size_t uuid_len = sizeof(result[i].uuid);
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, result[i].uuid, &uuid_len));
+ size_t uuid_len;
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, result[i].uuid, &uuid_len, sizeof(result[i].uuid)));
if (uuid_len != sizeof(result[i].uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
@@ -934,8 +940,8 @@ static hal_error_t pkey_remote_get_attributes(const hal_pkey_handle_t pkey,
attributes[i].length = u32;
}
else {
- size_t len = attributes_buffer + attributes_buffer_len - abuf;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, abuf, &len));
+ size_t len;
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, abuf, &len, attributes_buffer + attributes_buffer_len - abuf));
attributes[i].value = abuf;
attributes[i].length = len;
abuf += len;
@@ -968,10 +974,8 @@ static hal_error_t pkey_remote_export(const hal_pkey_handle_t pkey,
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- *pkcs8_len = pkcs8_max;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, pkcs8, pkcs8_len));
- *kek_len = kek_max;
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, kek, kek_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, pkcs8, pkcs8_len, pkcs8_max));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, kek, kek_len, kek_max));
}
return rpc_ret;
}
@@ -988,7 +992,7 @@ static hal_error_t pkey_remote_import(const hal_client_handle_t client,
uint8_t outbuf[nargs(7) + pad(pkcs8_len) + pad(kek_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
- size_t name_len = sizeof(name->uuid);
+ size_t name_len;
hal_error_t rpc_ret;
check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_IMPORT));
@@ -1006,7 +1010,7 @@ static hal_error_t pkey_remote_import(const hal_client_handle_t client,
if (rpc_ret == HAL_OK) {
check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
- check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len));
+ check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
if (name_len != sizeof(name->uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
}
diff --git a/rpc_pkey.c b/rpc_pkey.c
index dfaef93..a6a5734 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -684,131 +684,98 @@ static hal_error_t pkey_local_get_key_flags(const hal_pkey_handle_t pkey,
}
/*
- * Get length of public key associated with handle.
+ * Get public key associated with handle.
*/
-static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey)
+static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey,
+ uint8_t *der, size_t *der_len, const size_t der_max)
{
hal_pkey_slot_t *slot = find_handle(pkey);
if (slot == NULL)
- return 0;
-
- size_t result = 0;
+ return HAL_ERROR_KEY_NOT_FOUND;
-#ifndef max
-#define max(a, b) ((a) >= (b) ? (a) : (b))
-#endif
- size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size);
- keybuf_size = max(keybuf_size, hal_hashsig_key_t_size);
- uint8_t keybuf[keybuf_size];
- hal_rsa_key_t *rsa_key = NULL;
- hal_ecdsa_key_t *ecdsa_key = NULL;
- hal_hashsig_key_t *hashsig_key = NULL;
- uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
- size_t der_len;
+ uint8_t buf[HAL_KS_WRAPPED_KEYSIZE];
+ size_t buf_len;
hal_error_t err;
- if ((err = ks_fetch_from_flags(slot, der, &der_len, sizeof(der))) == HAL_OK) {
+ if ((err = ks_fetch_from_flags(slot, buf, &buf_len, sizeof(buf))) == HAL_OK) {
switch (slot->type) {
case HAL_KEY_TYPE_RSA_PUBLIC:
case HAL_KEY_TYPE_EC_PUBLIC:
case HAL_KEY_TYPE_HASHSIG_PUBLIC:
- result = der_len;
+ if (der_len != NULL)
+ *der_len = buf_len;
+ if (der != NULL) {
+ if (der_max < buf_len)
+ err = HAL_ERROR_RESULT_TOO_LONG;
+ else
+ memcpy(der, buf, buf_len);
+ }
break;
case HAL_KEY_TYPE_RSA_PRIVATE:
- if (hal_rsa_private_key_from_der(&rsa_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK)
- result = hal_rsa_public_key_to_der_len(rsa_key);
- break;
+ {
+ uint8_t keybuf[hal_rsa_key_t_size];
+ hal_rsa_key_t *key;
+ if ((err = hal_rsa_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
+ err = hal_rsa_public_key_to_der(key, der, der_len, der_max);
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
case HAL_KEY_TYPE_EC_PRIVATE:
- if (hal_ecdsa_private_key_from_der(&ecdsa_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK)
- result = hal_ecdsa_public_key_to_der_len(ecdsa_key);
- break;
+ {
+ uint8_t keybuf[hal_ecdsa_key_t_size];
+ hal_ecdsa_key_t *key;
+ if ((err = hal_ecdsa_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
+ err = hal_ecdsa_public_key_to_der(key, der, der_len, der_max);
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
case HAL_KEY_TYPE_HASHSIG_PRIVATE:
- if (hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK) {
- result = hal_hashsig_public_key_to_der_len(hashsig_key);
- hashsig_key = NULL;
+ {
+ uint8_t keybuf[hal_hashsig_key_t_size];
+ hal_hashsig_key_t *key;
+ if ((err = hal_hashsig_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK) {
+ err = hal_hashsig_public_key_to_der(key, der, der_len, der_max);
+ key = NULL;
}
- break;
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
default:
+ err = HAL_ERROR_UNSUPPORTED_KEY;
break;
}
}
- memset(keybuf, 0, sizeof(keybuf));
- memset(der, 0, sizeof(der));
+ memset(buf, 0, sizeof(buf));
- return result;
+ return err;
}
/*
- * Get public key associated with handle.
+ * Get length of public key associated with handle.
*/
-static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey,
- uint8_t *der, size_t *der_len, const size_t der_max)
+static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey)
{
hal_pkey_slot_t *slot = find_handle(pkey);
if (slot == NULL)
- return HAL_ERROR_KEY_NOT_FOUND;
+ return 0;
- size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size);
- keybuf_size = max(keybuf_size, hal_hashsig_key_t_size);
- uint8_t keybuf[keybuf_size];
- hal_rsa_key_t *rsa_key = NULL;
- hal_ecdsa_key_t *ecdsa_key = NULL;
- hal_hashsig_key_t *hashsig_key = NULL;
- uint8_t buf[HAL_KS_WRAPPED_KEYSIZE];
- size_t buf_len;
+ size_t der_len;
hal_error_t err;
- if ((err = ks_fetch_from_flags(slot, buf, &buf_len, sizeof(buf))) == HAL_OK) {
- switch (slot->type) {
-
- case HAL_KEY_TYPE_RSA_PUBLIC:
- case HAL_KEY_TYPE_EC_PUBLIC:
- case HAL_KEY_TYPE_HASHSIG_PUBLIC:
- if (der_len != NULL)
- *der_len = buf_len;
- if (der != NULL && der_max < buf_len)
- err = HAL_ERROR_RESULT_TOO_LONG;
- else if (der != NULL)
- memcpy(der, buf, buf_len);
- break;
-
- case HAL_KEY_TYPE_RSA_PRIVATE:
- if ((err = hal_rsa_private_key_from_der(&rsa_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
- err = hal_rsa_public_key_to_der(rsa_key, der, der_len, der_max);
- break;
-
- case HAL_KEY_TYPE_EC_PRIVATE:
- if ((err = hal_ecdsa_private_key_from_der(&ecdsa_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
- err = hal_ecdsa_public_key_to_der(ecdsa_key, der, der_len, der_max);
- break;
-
- case HAL_KEY_TYPE_HASHSIG_PRIVATE:
- if ((err = hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK) {
- err = hal_hashsig_public_key_to_der(hashsig_key, der, der_len, der_max);
- hashsig_key = NULL;
- }
- break;
-
- default:
- err = HAL_ERROR_UNSUPPORTED_KEY;
- break;
- }
- }
-
- memset(keybuf, 0, sizeof(keybuf));
- memset(buf, 0, sizeof(buf));
-
- return err;
+ if ((err = pkey_local_get_public_key(pkey, NULL, &der_len, 0)) == HAL_OK)
+ return der_len;
+ else
+ return 0;
}
/*
diff --git a/rpc_server.c b/rpc_server.c
index b363f23..9598413 100644
--- a/rpc_server.c
+++ b/rpc_server.c
@@ -170,10 +170,16 @@ static hal_error_t hash_get_digest_algorithm_id(const uint8_t **iptr, const uint
if (nargs(1) + pad(len_max) > (uint32_t)(olimit - *optr))
return HAL_ERROR_RPC_PACKET_OVERFLOW;
- /* get the data directly into the output buffer */
- if ((err = hal_rpc_hash_get_digest_algorithm_id(alg, *optr + nargs(1), &len, (size_t)len_max)) == HAL_OK) {
- check(hal_xdr_encode_int(optr, olimit, len));
- *optr += pad(len);
+ if (len_max == 0) {
+ if ((err = hal_rpc_hash_get_digest_algorithm_id(alg, NULL, &len, 0)) == HAL_OK)
+ check(hal_xdr_encode_int(optr, olimit, len));
+ }
+ else {
+ /* get the data directly into the output buffer */
+ if ((err = hal_rpc_hash_get_digest_algorithm_id(alg, *optr + nargs(1), &len, (size_t)len_max)) == HAL_OK) {
+ check(hal_xdr_encode_int(optr, olimit, len));
+ *optr += pad(len);
+ }
}
return err;
@@ -209,6 +215,8 @@ static hal_error_t hash_initialize(const uint8_t **iptr, const uint8_t * const i
check(hal_xdr_decode_int(iptr, ilimit, &session.handle));
check(hal_xdr_decode_int(iptr, ilimit, &alg));
check(hal_xdr_decode_variable_opaque_ptr(iptr, ilimit, &key, &key_len));
+ if (key_len == 0)
+ key = NULL;
check(hal_rpc_hash_initialize(client, session, &hash, (hal_digest_algorithm_t)alg, key, (size_t)key_len));
diff --git a/tests/test-xdr.c b/tests/test-xdr.c
index eedf48d..f084e01 100644
--- a/tests/test-xdr.c
+++ b/tests/test-xdr.c
@@ -95,8 +95,8 @@ int main(int argc, char *argv[])
printf("\nhal_xdr_decode_variable_opaque:\n");
readptr = buf;
while (readptr < bufptr) {
- size_t len = bufptr - readptr;
- if ((ret = hal_xdr_decode_variable_opaque(&readptr, limit, readbuf, &len)) != HAL_OK) {
+ size_t len;
+ if ((ret = hal_xdr_decode_variable_opaque(&readptr, limit, readbuf, &len, bufptr - readptr)) != HAL_OK) {
printf("%s\n", hal_error_string(ret));
break;
}
diff --git a/xdr.c b/xdr.c
index 2b42be9..92c2b64 100644
--- a/xdr.c
+++ b/xdr.c
@@ -190,16 +190,19 @@ hal_error_t hal_xdr_decode_variable_opaque_ptr(const uint8_t ** const inbuf, con
/* This version copies the data to the user-supplied buffer.
* It is used in the rpc client.
*/
-hal_error_t hal_xdr_decode_variable_opaque(const uint8_t ** const inbuf, const uint8_t * const limit, uint8_t * const value, size_t * const len)
+hal_error_t hal_xdr_decode_variable_opaque(const uint8_t ** const inbuf, const uint8_t * const limit, uint8_t * const value, size_t * const len, const size_t len_max)
{
hal_error_t err;
size_t xdr_len;
const uint8_t *p;
+ /* arg checks */
+ hal_assert(value != NULL && len != NULL && len_max != 0);
+
/* read data pointer and length */
if ((err = hal_xdr_decode_variable_opaque_ptr(inbuf, limit, &p, &xdr_len)) == HAL_OK) {
/* user buffer overflow check */
- if (*len < xdr_len)
+ if (len_max < xdr_len)
return HAL_ERROR_XDR_BUFFER_OVERFLOW;
/* read the data */
memcpy(value, p, xdr_len);
diff --git a/xdr_internal.h b/xdr_internal.h
index aa3a1e9..6cdc064 100644
--- a/xdr_internal.h
+++ b/xdr_internal.h
@@ -68,7 +68,7 @@ hal_error_t hal_xdr_encode_variable_opaque(uint8_t ** const outbuf,
hal_error_t hal_xdr_decode_variable_opaque(const uint8_t ** const inbuf,
const uint8_t * const limit,
uint8_t * const value,
- size_t * const len);
+ size_t * const len, const size_t len_max);
hal_error_t hal_xdr_decode_variable_opaque_ptr(const uint8_t ** const inbuf,
const uint8_t * const limit,