From 306c1dec5eb20da03bc9569aab83ae97a2ca9e7a Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sat, 19 Nov 2016 21:16:52 -0500 Subject: Support queries for attribute length and presence. Calling hal_rpc_pkey_get_attributes() with attribute_buffer_len = 0 now changes the return behavior so that it reports the lengths of attributes listed in the query, with a length of zero for attributes not present at all. This is mostly to support C_GetAttributeValue() in PKCS #11, but we also use it to make the Python interface a bit kinder to the user. --- hal_internal.h | 3 +-- ks_flash.c | 14 +++++++++----- ks_volatile.c | 23 ++++++++++++++--------- libhal.py | 14 +++++++++++--- rpc_client.c | 17 ++++++++++++----- rpc_server.c | 5 ++++- 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/hal_internal.h b/hal_internal.h index 9685b0c..0794d37 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -649,8 +649,7 @@ static inline hal_error_t hal_ks_get_attributes(hal_ks_t *ks, const size_t attributes_buffer_len) { if (ks == NULL || ks->driver == NULL || slot == NULL || - attributes == NULL || attributes_len == 0 || - attributes_buffer == NULL || attributes_buffer_len == 0) + attributes == NULL || attributes_len == 0) return HAL_ERROR_BAD_ARGUMENTS; if (ks->driver->get_attributes == NULL) diff --git a/ks_flash.c b/ks_flash.c index 5b38ec5..9b1bf7c 100644 --- a/ks_flash.c +++ b/ks_flash.c @@ -1579,7 +1579,7 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, const size_t attributes_buffer_len) { if (ks != &db.ks || slot == NULL || attributes == NULL || attributes_len == 0 || - attributes_buffer == NULL || attributes_buffer_len == 0) + attributes_buffer == NULL) return HAL_ERROR_BAD_ARGUMENTS; for (int i = 0; i < attributes_len; i++) { @@ -1626,7 +1626,7 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, for (int i = 0; i < attributes_len; i++) { - if (attributes[i].value != NULL) + if (attributes[i].length > 0) continue; int j = 0; @@ -1634,20 +1634,24 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, j++; if (j >= *attrs_len) continue; + found++; + + attributes[i].length = attrs[j].length; + + if (attributes_buffer_len == 0) + continue; if (attrs[j].length > attributes_buffer + attributes_buffer_len - abuf) return HAL_ERROR_RESULT_TOO_LONG; memcpy(abuf, attrs[j].value, attrs[j].length); attributes[i].value = abuf; - attributes[i].length = attrs[j].length; abuf += attrs[j].length; - found++; } } while (found < attributes_len && ++chunk < block->header.total_chunks); - if (found < attributes_len) + if (found < attributes_len && attributes_buffer_len > 0) return HAL_ERROR_ATTRIBUTE_NOT_FOUND; return HAL_OK; diff --git a/ks_volatile.c b/ks_volatile.c index e23aefe..9588639 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -493,7 +493,7 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, const size_t attributes_buffer_len) { if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0 || - attributes_buffer == NULL || attributes_buffer_len == 0) + attributes_buffer == NULL) return HAL_ERROR_BAD_ARGUMENTS; ks_t *ksv = ks_to_ksv(ks); @@ -511,10 +511,7 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, if (!key_visible_to_session(ksv, slot->client_handle, slot->session_handle, k)) return HAL_ERROR_KEY_NOT_FOUND; - if (k->attributes_len == 0) - return HAL_ERROR_ATTRIBUTE_NOT_FOUND; - - hal_rpc_pkey_attribute_t attrs[k->attributes_len]; + hal_rpc_pkey_attribute_t attrs[k->attributes_len > 0 ? k->attributes_len : 1]; if ((err = hal_ks_attribute_scan(k->der + k->der_len, sizeof(k->der) - k->der_len, attrs, k->attributes_len, NULL)) != HAL_OK) @@ -523,11 +520,19 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, uint8_t *abuf = attributes_buffer; for (int i = 0; i < attributes_len; i++) { - int j = 0; - while (attrs[j].type != attributes[i].type) - if (++j >= k->attributes_len) - return HAL_ERROR_ATTRIBUTE_NOT_FOUND; + while (j < k->attributes_len && attrs[j].type != attributes[i].type) + j++; + const int found = j < k->attributes_len; + + if (attributes_buffer_len == 0) { + attributes[i].value = NULL; + attributes[i].length = found ? attrs[j].length : 0; + continue; + } + + if (!found) + return HAL_ERROR_ATTRIBUTE_NOT_FOUND; if (attrs[j].length > attributes_buffer + attributes_buffer_len - abuf) return HAL_ERROR_RESULT_TOO_LONG; diff --git a/libhal.py b/libhal.py index 8dad622..dc8d07d 100644 --- a/libhal.py +++ b/libhal.py @@ -382,8 +382,13 @@ class PKey(Handle): def set_attributes(self, attributes): self.hsm.pkey_set_attributes(self, attributes) - def get_attributes(self, attributes, attributes_buffer_len = 2048): - return self.hsm.pkey_get_attributes(self, attributes, attributes_buffer_len) + def get_attributes(self, attributes): + lengths = self.hsm.pkey_get_attributes(self, attributes, 0) + attributes = (k for k, v in lengths.iteritems() if v > 0) + buffer_length = sum(lengths.itervalues()) + result = dict((a, None) for a in lengths) + result.update(self.hsm.pkey_get_attributes(self, attributes, buffer_length)) + return result class HSM(object): @@ -650,4 +655,7 @@ class HSM(object): n = r.unpack_uint() if n != len(attributes): raise HAL_ERROR_RPC_PROTOCOL_ERROR - return dict((r.unpack_uint(), r.unpack_bytes()) for i in xrange(n)) + if attributes_buffer_len > 0: + return dict((r.unpack_uint(), r.unpack_bytes()) for i in xrange(n)) + else: + return dict((r.unpack_uint(), r.unpack_uint()) for i in xrange(n)) diff --git a/rpc_client.c b/rpc_client.c index 0c57d51..4da0cb9 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -895,11 +895,18 @@ static hal_error_t pkey_remote_get_attributes(const hal_pkey_handle_t pkey, check(hal_xdr_decode_int(&iptr, ilimit, &u32)); if (u32 != attributes[i].type) return HAL_ERROR_RPC_PROTOCOL_ERROR; - u32 = attributes_buffer + attributes_buffer_len - abuf; - check(hal_xdr_decode_buffer(&iptr, ilimit, abuf, &u32)); - attributes[i].value = abuf; - attributes[i].length = u32; - abuf += u32; + if (attributes_buffer_len == 0) { + check(hal_xdr_decode_int(&iptr, ilimit, &u32)); + attributes[i].value = NULL; + attributes[i].length = u32; + } + else { + u32 = attributes_buffer + attributes_buffer_len - abuf; + check(hal_xdr_decode_buffer(&iptr, ilimit, abuf, &u32)); + attributes[i].value = abuf; + attributes[i].length = u32; + abuf += u32; + } } } return rpc_ret; diff --git a/rpc_server.c b/rpc_server.c index ed9a8d5..ae891a4 100644 --- a/rpc_server.c +++ b/rpc_server.c @@ -759,7 +759,10 @@ static hal_error_t pkey_get_attributes(const uint8_t **iptr, const uint8_t * con ret = hal_xdr_encode_int(optr, olimit, attributes[i].type); if (ret != HAL_OK) break; - ret = hal_xdr_encode_buffer(optr, olimit, attributes[i].value, attributes[i].length); + if (attributes_buffer_len == 0) + ret = hal_xdr_encode_int(optr, olimit, attributes[i].length); + else + ret = hal_xdr_encode_buffer(optr, olimit, attributes[i].value, attributes[i].length); } } -- cgit v1.2.3