[Cryptech-Commits] [sw/libhal] 01/02: Small cleanups in RPC code, e.g. to support null arguments.

git at cryptech.is git at cryptech.is
Tue Apr 2 05:08:10 UTC 2019


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch master
in repository sw/libhal.

commit 6b0c67ace3678325443aa21a32b2b10daa018e27
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Tue Apr 2 00:58:41 2019 -0400

    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,



More information about the Commits mailing list