From 6b0c67ace3678325443aa21a32b2b10daa018e27 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 2 Apr 2019 00:58:41 -0400 Subject: 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. --- rpc_api.c | 8 +++- rpc_client.c | 64 +++++++++++++------------- rpc_pkey.c | 135 +++++++++++++++++++++---------------------------------- rpc_server.c | 16 +++++-- tests/test-xdr.c | 4 +- xdr.c | 7 ++- xdr_internal.h | 2 +- 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, -- cgit v1.2.3