[Openvpn-devel] travis-ci: add pkcs11-helper patch identical to openvpn-build

Message ID 20180220162231.28897-1-chipitsine@gmail.com
State Rejected, archived
Headers show
Series [Openvpn-devel] travis-ci: add pkcs11-helper patch identical to openvpn-build | expand

Commit Message

Ilya Shipitsin Feb. 20, 2018, 5:22 a.m. UTC
currently patch of implementing RFC7512 URI Scheme is added during
building windows installer. The same patch was added to travis-ci
cross builds

Signed-off-by: Ilya Shipitsin <chipitsine@gmail.com>
---
 .travis/build-deps.sh                   |  17 +-
 .travis/pkcs11-helper-001-RFC7512.patch | 656 ++++++++++++++++++++++++++++++++
 2 files changed, 669 insertions(+), 4 deletions(-)
 create mode 100644 .travis/pkcs11-helper-001-RFC7512.patch

Comments

Steffan Karger Feb. 20, 2018, 9:37 a.m. UTC | #1
Hi,

On 20-02-18 17:22, Ilya Shipitsin wrote:
> currently patch of implementing RFC7512 URI Scheme is added during
> building windows installer. The same patch was added to travis-ci
> cross builds

I don't think this is a good idea.  Most pkcs11-helper builds out in the
world are *without* this patch, so I'd rather test building against a
pkcs11-helper without the patch.

Also, we don't test pkcs11 functionality in this test suite at all, so I
don't see the gain in adding the patch here.

-Steffan

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Patch

diff --git a/.travis/build-deps.sh b/.travis/build-deps.sh
index 96a030cc..6270a945 100755
--- a/.travis/build-deps.sh
+++ b/.travis/build-deps.sh
@@ -4,6 +4,11 @@  set -eux
 # Set defaults
 PREFIX="${PREFIX:-${HOME}/opt}"
 
+die() {
+        echo "FATAL: $1" >&2
+        exit 1
+}
+
 download_tap_windows () {
     if [ ! -f "download-cache/tap-windows-${TAP_WINDOWS_VERSION}.zip" ]; then
        wget -P download-cache/ \
@@ -15,12 +20,12 @@  download_lzo () {
     if [ ! -f "download-cache/lzo-${LZO_VERSION}.tar.gz" ]; then
         wget -P download-cache/ \
             "http://www.oberhumer.com/opensource/lzo/download/lzo-${LZO_VERSION}.tar.gz"
+        tar zxf download-cache/lzo-${LZO_VERSION}.tar.gz
     fi
 }
 
 build_lzo () {
     if [ "$(cat ${PREFIX}/.lzo-version)" != "${LZO_VERSION}" ]; then
-        tar zxf download-cache/lzo-${LZO_VERSION}.tar.gz
         (
             cd "lzo-${LZO_VERSION}"
 
@@ -36,12 +41,12 @@  download_pkcs11_helper () {
     if [ ! -f "pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2" ]; then
         wget -P download-cache/ \
             "https://github.com/OpenSC/pkcs11-helper/releases/download/pkcs11-helper-${PKCS11_HELPER_VERSION}/pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2"
+        tar jxf download-cache/pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2
     fi
 }
 
 build_pkcs11_helper () {
     if [ "$(cat ${PREFIX}/.pkcs11_helper-version)" != "${PKCS11_HELPER_VERSION}" ]; then
-        tar jxf download-cache/pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2
         (
             cd "pkcs11-helper-${PKCS11_HELPER_VERSION}"
 
@@ -158,8 +163,12 @@  if [ ! -z ${CHOST+x} ]; then
       unzip download-cache/tap-windows-${TAP_WINDOWS_VERSION}.zip
 
       download_lzo
-      build_lzo
-
       download_pkcs11_helper
+
+      for f in .travis/*.patch; do
+          patch -p1 < "${f}" || die "Patch '${f}'"
+      done
+
+      build_lzo
       build_pkcs11_helper
 fi
diff --git a/.travis/pkcs11-helper-001-RFC7512.patch b/.travis/pkcs11-helper-001-RFC7512.patch
new file mode 100644
index 00000000..ad21c854
--- /dev/null
+++ b/.travis/pkcs11-helper-001-RFC7512.patch
@@ -0,0 +1,656 @@ 
+diff --git a/pkcs11-helper-1.22/lib/pkcs11h-serialization.c b/pkcs11-helper-1.22/lib/pkcs11h-serialization.c
+index ad275f8..1d077e4 100644
+--- a/pkcs11-helper-1.22/lib/pkcs11h-serialization.c
++++ b/pkcs11-helper-1.22/lib/pkcs11h-serialization.c
+@@ -61,29 +61,127 @@
+ 
+ #if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
+ 
++#define URI_SCHEME "pkcs11:"
++
++#define token_field_ofs(field) ((unsigned long)&(((struct pkcs11h_token_id_s *)0)->field))
++#define token_field_size(field) sizeof((((struct pkcs11h_token_id_s *)0)->field))
++#define token_field(name, field) { name "=", sizeof(name), \
++				   token_field_ofs(field), token_field_size(field) }
++
++static struct {
++	const char const *name;
++	size_t namelen;
++	unsigned long field_ofs;
++	size_t field_size;
++} __token_fields[] = {
++	token_field ("model", model),
++	token_field ("token", label),
++	token_field ("manufacturer", manufacturerID ),
++	token_field ("serial", serialNumber ),
++	{ NULL },
++};
++
++#define               P11_URL_VERBATIM      "abcdefghijklmnopqrstuvwxyz" \
++                                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
++                                            "0123456789_-."
++
++static
++int
++__token_attr_escape(char *uri, char *attr, size_t attrlen)
++{
++	int len = 0, i;
++
++	for (i = 0; i < attrlen; i++) {
++		if (strchr(P11_URL_VERBATIM, attr[i])) {
++			if (uri) {
++				*(uri++) = attr[i];
++			}
++			len++;
++		} else {
++			if (uri) {
++				sprintf(uri, "%%%02x", (unsigned char)attr[i]);
++				uri += 3;
++			}
++			len += 3;
++		}
++	}
++	return len;
++}
++
++static
++CK_RV
++__generate_pkcs11_uri (
++	OUT char * const sz,
++	IN OUT size_t *max,
++	IN const pkcs11h_certificate_id_t certificate_id,
++	IN const pkcs11h_token_id_t token_id
++) {
++	size_t _max;
++	char *p = sz;
++	int i;
++
++	_PKCS11H_ASSERT (max!=NULL);
++	_PKCS11H_ASSERT (token_id!=NULL);
++
++	_max = strlen(URI_SCHEME);
++	for (i = 0; __token_fields[i].name; i++) {
++		char *field = ((char *)token_id) + __token_fields[i].field_ofs;
++
++		_max += __token_fields[i].namelen;
++		_max += __token_attr_escape (NULL, field, strlen(field));
++		_max++; /* For a semicolon or trailing NUL */
++	}
++	if (certificate_id) {
++		_max += strlen (";id=");
++		_max += __token_attr_escape (NULL,
++					     (char *)certificate_id->attrCKA_ID,
++					     certificate_id->attrCKA_ID_size);
++	}
++
++	if (!sz) {
++		*max = _max;
++		return CKR_OK;
++	}
++
++	if (sz && *max < _max)
++		return CKR_ATTRIBUTE_VALUE_INVALID;
++
++	p += sprintf(p, URI_SCHEME);
++	for (i = 0; __token_fields[i].name; i++) {
++		char *field = ((char *)token_id) + __token_fields[i].field_ofs;
++
++		p += sprintf (p, "%s", __token_fields[i].name);
++		p += __token_attr_escape (p, field, strlen(field));
++		*(p++) = ';';
++	}
++	if (certificate_id) {
++		p += sprintf (p, "id=");
++		p += __token_attr_escape (p,
++					  (char *)certificate_id->attrCKA_ID,
++					  certificate_id->attrCKA_ID_size);
++	} else {
++		/* Remove the unneeded trailing semicolon */
++		p--;
++	}
++	*(p++) = 0;
++
++	*max = _max;
++
++	return CKR_OK;
++}
++
+ CK_RV
+ pkcs11h_token_serializeTokenId (
+ 	OUT char * const sz,
+ 	IN OUT size_t *max,
+ 	IN const pkcs11h_token_id_t token_id
+ ) {
+-	const char *sources[5];
+ 	CK_RV rv = CKR_FUNCTION_FAILED;
+-	size_t n;
+-	int e;
+ 
+ 	/*_PKCS11H_ASSERT (sz!=NULL); Not required*/
+ 	_PKCS11H_ASSERT (max!=NULL);
+ 	_PKCS11H_ASSERT (token_id!=NULL);
+ 
+-	{ /* Must be after assert */
+-		sources[0] = token_id->manufacturerID;
+-		sources[1] = token_id->model;
+-		sources[2] = token_id->serialNumber;
+-		sources[3] = token_id->label;
+-		sources[4] = NULL;
+-	}
+-
+ 	_PKCS11H_DEBUG (
+ 		PKCS11H_LOG_DEBUG2,
+ 		"PKCS#11: pkcs11h_token_serializeTokenId entry sz=%p, *max="P_Z", token_id=%p",
+@@ -92,67 +190,161 @@ pkcs11h_token_serializeTokenId (
+ 		(void *)token_id
+ 	);
+ 
+-	n = 0;
+-	for (e=0;sources[e] != NULL;e++) {
+-		size_t t;
+-		if (
+-			(rv = _pkcs11h_util_escapeString (
+-				NULL,
+-				sources[e],
+-				&t,
+-				__PKCS11H_SERIALIZE_INVALID_CHARS
+-			)) != CKR_OK
+-		) {
+-			goto cleanup;
++	rv = __generate_pkcs11_uri(sz, max, NULL, token_id);
++
++	_PKCS11H_DEBUG (
++		PKCS11H_LOG_DEBUG2,
++		"PKCS#11: pkcs11h_token_serializeTokenId return rv=%lu-'%s', *max="P_Z", sz='%s'",
++		rv,
++		pkcs11h_getMessage (rv),
++		*max,
++		sz
++	);
++
++	return rv;
++}
++
++static
++CK_RV
++__parse_token_uri_attr (
++	const char *uri,
++	size_t urilen,
++	char *tokstr,
++	size_t toklen,
++	size_t *parsed_len
++) {
++	size_t orig_toklen = toklen;
++	CK_RV rv = CKR_OK;
++
++	while (urilen && toklen > 1) {
++		if (*uri == '%') {
++			size_t size = 1;
++
++			if (urilen < 3) {
++				rv = CKR_ATTRIBUTE_VALUE_INVALID;
++				goto done;
++			}
++
++			rv = _pkcs11h_util_hexToBinary ((unsigned char *)tokstr,
++							uri + 1, &size);
++			if (rv != CKR_OK) {
++				goto done;
++			}
++
++			uri += 2;
++			urilen -= 2;
++		} else {
++			*tokstr = *uri;
+ 		}
+-		n+=t;
++		tokstr++;
++		uri++;
++		toklen--;
++		urilen--;
++		tokstr[1] = 0;
+ 	}
+ 
+-	if (sz != NULL) {
+-		if (*max < n) {
+-			rv = CKR_ATTRIBUTE_VALUE_INVALID;
+-			goto cleanup;
++	if (urilen) {
++		rv = CKR_ATTRIBUTE_VALUE_INVALID;
++	} else if (parsed_len) {
++		*parsed_len = orig_toklen - toklen;
++	}
++
++ done:
++	return rv;
++}
++
++static
++CK_RV
++__parse_pkcs11_uri (
++	OUT pkcs11h_token_id_t token_id,
++	OUT pkcs11h_certificate_id_t certificate_id,
++	IN const char * const sz
++) {
++	const char *end, *p;
++	CK_RV rv = CKR_OK;
++
++	_PKCS11H_ASSERT (token_id!=NULL);
++	_PKCS11H_ASSERT (sz!=NULL);
++
++	if (strncmp (sz, URI_SCHEME, strlen (URI_SCHEME)))
++		return CKR_ATTRIBUTE_VALUE_INVALID;
++
++	end = sz + strlen (URI_SCHEME) - 1;
++	while (rv == CKR_OK && end[0] && end[1]) {
++		int i;
++
++		p = end + 1;
++	        end = strchr (p, ';');
++		if (!end)
++			end = p + strlen(p);
++
++		for (i = 0; __token_fields[i].name; i++) {
++			/* Parse the token=, label=, manufacturer= and serial= fields */
++			if (!strncmp(p, __token_fields[i].name, __token_fields[i].namelen)) {
++				char *field = ((char *)token_id) + __token_fields[i].field_ofs;
++
++				p += __token_fields[i].namelen;
++				rv = __parse_token_uri_attr (p, end - p, field,
++							     __token_fields[i].field_size,
++							     NULL);
++				if (rv != CKR_OK) {
++					goto cleanup;
++				}
++
++				goto matched;
++			}
+ 		}
++		if (certificate_id && !strncmp(p, "id=", 3)) {
++			p += 3;
++
++			rv = _pkcs11h_mem_malloc ((void *)&certificate_id->attrCKA_ID,
++						  end - p + 1);
++			if (rv != CKR_OK) {
++				goto cleanup;
++			}
+ 
+-		n = 0;
+-		for (e=0;sources[e] != NULL;e++) {
+-			size_t t = *max-n;
+-			if (
+-				(rv = _pkcs11h_util_escapeString (
+-					sz+n,
+-					sources[e],
+-					&t,
+-					__PKCS11H_SERIALIZE_INVALID_CHARS
+-				)) != CKR_OK
+-			) {
++			rv = __parse_token_uri_attr (p, end - p,
++						     (char *)certificate_id->attrCKA_ID,
++						     end - p + 1,
++						     &certificate_id->attrCKA_ID_size);
++			if (rv != CKR_OK) {
+ 				goto cleanup;
+ 			}
+-			n+=t;
+-			sz[n-1] = '/';
++
++			goto matched;
+ 		}
+-		sz[n-1] = '\x0';
+-	}
+ 
+-	*max = n;
+-	rv = CKR_OK;
++		/* We don't parse object= because the match code doesn't support
++		   matching by label. */
++
++		/* Failed to parse PKCS#11 URI element. */
++		return CKR_ATTRIBUTE_VALUE_INVALID;
+ 
++		matched:
++		    ;
++	}
+ cleanup:
++	/* The matching code doesn't support support partial matches; it needs
++	 * *all* of manufacturer, model, serial and label attributes to be
++	 * defined. So reject partial URIs early instead of letting it do the
++	 * wrong thing. We can maybe improve this later. */
++	if (!token_id->model[0] || !token_id->label[0] ||
++	    !token_id->manufacturerID[0] || !token_id->serialNumber[0]) {
++		return CKR_ATTRIBUTE_VALUE_INVALID;
++	}
+ 
+-	_PKCS11H_DEBUG (
+-		PKCS11H_LOG_DEBUG2,
+-		"PKCS#11: pkcs11h_token_serializeTokenId return rv=%lu-'%s', *max="P_Z", sz='%s'",
+-		rv,
+-		pkcs11h_getMessage (rv),
+-		*max,
+-		sz
+-	);
++	/* For a certificate ID we need CKA_ID */
++	if (certificate_id && !certificate_id->attrCKA_ID_size) {
++		return CKR_ATTRIBUTE_VALUE_INVALID;
++	}
+ 
+ 	return rv;
+ }
+ 
++static
+ CK_RV
+-pkcs11h_token_deserializeTokenId (
+-	OUT pkcs11h_token_id_t *p_token_id,
++__pkcs11h_token_legacy_deserializeTokenId (
++	OUT pkcs11h_token_id_t token_id,
+ 	IN const char * const sz
+ ) {
+ #define __PKCS11H_TARGETS_NUMBER 4
+@@ -161,24 +353,11 @@ pkcs11h_token_deserializeTokenId (
+ 		size_t s;
+ 	} targets[__PKCS11H_TARGETS_NUMBER];
+ 
+-	pkcs11h_token_id_t token_id = NULL;
+ 	char *p1 = NULL;
+ 	char *_sz = NULL;
+ 	int e;
+ 	CK_RV rv = CKR_FUNCTION_FAILED;
+ 
+-	_PKCS11H_ASSERT (p_token_id!=NULL);
+-	_PKCS11H_ASSERT (sz!=NULL);
+-
+-	_PKCS11H_DEBUG (
+-		PKCS11H_LOG_DEBUG2,
+-		"PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
+-		(void *)p_token_id,
+-		sz
+-	);
+-
+-	*p_token_id = NULL;
+-
+ 	if (
+ 		(rv = _pkcs11h_mem_strdup (
+ 			(void *)&_sz,
+@@ -190,10 +369,6 @@ pkcs11h_token_deserializeTokenId (
+ 
+ 	p1 = _sz;
+ 
+-	if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) {
+-		goto cleanup;
+-	}
+-
+ 	targets[0].p = token_id->manufacturerID;
+ 	targets[0].s = sizeof (token_id->manufacturerID);
+ 	targets[1].p = token_id->model;
+@@ -252,6 +427,51 @@ pkcs11h_token_deserializeTokenId (
+ 		p1 = p2+1;
+ 	}
+ 
++	rv = CKR_OK;
++
++cleanup:
++
++	if (_sz != NULL) {
++		_pkcs11h_mem_free ((void *)&_sz);
++	}
++
++	return rv;
++#undef __PKCS11H_TARGETS_NUMBER
++}
++
++CK_RV
++pkcs11h_token_deserializeTokenId (
++	OUT pkcs11h_token_id_t *p_token_id,
++	IN const char * const sz
++) {
++	pkcs11h_token_id_t token_id = NULL;
++	CK_RV rv = CKR_FUNCTION_FAILED;
++
++	_PKCS11H_ASSERT (p_token_id!=NULL);
++	_PKCS11H_ASSERT (sz!=NULL);
++
++	_PKCS11H_DEBUG (
++		PKCS11H_LOG_DEBUG2,
++		"PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
++		(void *)p_token_id,
++		sz
++	);
++
++	*p_token_id = NULL;
++
++	if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) {
++		goto cleanup;
++	}
++
++	if (!strncmp (sz, URI_SCHEME, strlen (URI_SCHEME))) {
++		rv = __parse_pkcs11_uri(token_id, NULL, sz);
++	} else {
++		rv = __pkcs11h_token_legacy_deserializeTokenId(token_id, sz);
++	}
++	if (rv != CKR_OK) {
++		goto cleanup;
++	}
++
+ 	strncpy (
+ 		token_id->display,
+ 		token_id->label,
+@@ -264,11 +484,6 @@ pkcs11h_token_deserializeTokenId (
+ 	rv = CKR_OK;
+ 
+ cleanup:
+-
+-	if (_sz != NULL) {
+-		_pkcs11h_mem_free ((void *)&_sz);
+-	}
+-
+ 	if (token_id != NULL) {
+ 		pkcs11h_token_freeTokenId (token_id);
+ 	}
+@@ -281,7 +496,6 @@ cleanup:
+ 	);
+ 
+ 	return rv;
+-#undef __PKCS11H_TARGETS_NUMBER
+ }
+ 
+ #endif				/* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
+@@ -295,9 +509,6 @@ pkcs11h_certificate_serializeCertificateId (
+ 	IN const pkcs11h_certificate_id_t certificate_id
+ ) {
+ 	CK_RV rv = CKR_FUNCTION_FAILED;
+-	size_t saved_max = 0;
+-	size_t n = 0;
+-	size_t _max = 0;
+ 
+ 	/*_PKCS11H_ASSERT (sz!=NULL); Not required */
+ 	_PKCS11H_ASSERT (max!=NULL);
+@@ -311,42 +522,7 @@ pkcs11h_certificate_serializeCertificateId (
+ 		(void *)certificate_id
+ 	);
+ 
+-	if (sz != NULL) {
+-		saved_max = n = *max;
+-	}
+-	*max = 0;
+-
+-	if (
+-		(rv = pkcs11h_token_serializeTokenId (
+-			sz,
+-			&n,
+-			certificate_id->token_id
+-		)) != CKR_OK
+-	) {
+-		goto cleanup;
+-	}
+-
+-	_max = n + certificate_id->attrCKA_ID_size*2 + 1;
+-
+-	if (sz != NULL) {
+-		if (saved_max < _max) {
+-			rv = CKR_ATTRIBUTE_VALUE_INVALID;
+-			goto cleanup;
+-		}
+-
+-		sz[n-1] = '/';
+-		rv = _pkcs11h_util_binaryToHex (
+-			sz+n,
+-			saved_max-n,
+-			certificate_id->attrCKA_ID,
+-			certificate_id->attrCKA_ID_size
+-		);
+-	}
+-
+-	*max = _max;
+-	rv = CKR_OK;
+-
+-cleanup:
++	rv = __generate_pkcs11_uri(sz, max, certificate_id, certificate_id->token_id);
+ 
+ 	_PKCS11H_DEBUG (
+ 		PKCS11H_LOG_DEBUG2,
+@@ -360,27 +536,16 @@ cleanup:
+ 	return rv;
+ }
+ 
++static
+ CK_RV
+-pkcs11h_certificate_deserializeCertificateId (
+-	OUT pkcs11h_certificate_id_t * const p_certificate_id,
++__pkcs11h_certificate_legacy_deserializeCertificateId (
++	OUT pkcs11h_certificate_id_t certificate_id,
+ 	IN const char * const sz
+ ) {
+-	pkcs11h_certificate_id_t certificate_id = NULL;
+ 	CK_RV rv = CKR_FUNCTION_FAILED;
+ 	char *p = NULL;
+ 	char *_sz = NULL;
+-
+-	_PKCS11H_ASSERT (p_certificate_id!=NULL);
+-	_PKCS11H_ASSERT (sz!=NULL);
+-
+-	*p_certificate_id = NULL;
+-
+-	_PKCS11H_DEBUG (
+-		PKCS11H_LOG_DEBUG2,
+-		"PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
+-		(void *)p_certificate_id,
+-		sz
+-	);
++	size_t id_hex_len;
+ 
+ 	if (
+ 		(rv = _pkcs11h_mem_strdup (
+@@ -393,10 +558,6 @@ pkcs11h_certificate_deserializeCertificateId (
+ 
+ 	p = _sz;
+ 
+-	if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) {
+-		goto cleanup;
+-	}
+-
+ 	if ((p = strrchr (_sz, '/')) == NULL) {
+ 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ 		goto cleanup;
+@@ -414,7 +575,12 @@ pkcs11h_certificate_deserializeCertificateId (
+ 		goto cleanup;
+ 	}
+ 
+-	certificate_id->attrCKA_ID_size = strlen (p)/2;
++	id_hex_len = strlen (p);
++	if (id_hex_len & 1) {
++		rv = CKR_ATTRIBUTE_VALUE_INVALID;
++		goto cleanup;
++	}
++	certificate_id->attrCKA_ID_size = id_hex_len/2;
+ 
+ 	if (
+ 		(rv = _pkcs11h_mem_malloc (
+@@ -430,21 +596,64 @@ pkcs11h_certificate_deserializeCertificateId (
+ 		goto cleanup;
+ 	}
+ 
++	rv = CKR_OK;
++
++cleanup:
++
++	if (_sz != NULL) {
++		_pkcs11h_mem_free ((void *)&_sz);
++	}
++
++	return rv;
++
++}
++
++CK_RV
++pkcs11h_certificate_deserializeCertificateId (
++	OUT pkcs11h_certificate_id_t * const p_certificate_id,
++	IN const char * const sz
++) {
++	pkcs11h_certificate_id_t certificate_id = NULL;
++	CK_RV rv = CKR_FUNCTION_FAILED;
++
++	_PKCS11H_ASSERT (p_certificate_id!=NULL);
++	_PKCS11H_ASSERT (sz!=NULL);
++
++	*p_certificate_id = NULL;
++
++	_PKCS11H_DEBUG (
++		PKCS11H_LOG_DEBUG2,
++		"PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
++		(void *)p_certificate_id,
++		sz
++	);
++
++	if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) {
++		goto cleanup;
++	}
++	if ((rv = _pkcs11h_token_newTokenId (&certificate_id->token_id)) != CKR_OK) {
++		goto cleanup;
++	}
++
++	if (!strncmp(sz, URI_SCHEME, strlen (URI_SCHEME))) {
++		rv = __parse_pkcs11_uri (certificate_id->token_id, certificate_id, sz);
++	} else {
++		rv = __pkcs11h_certificate_legacy_deserializeCertificateId (certificate_id, sz);
++	}
++	if (rv != CKR_OK) {
++		goto cleanup;
++	}
++
+ 	*p_certificate_id = certificate_id;
+ 	certificate_id = NULL;
+ 	rv = CKR_OK;
+ 
+ cleanup:
+-
+ 	if (certificate_id != NULL) {
+ 		pkcs11h_certificate_freeCertificateId (certificate_id);
+ 		certificate_id = NULL;
+ 	}
+ 
+-	if (_sz != NULL) {
+-		_pkcs11h_mem_free ((void *)&_sz);
+-	}
+-
+ 	_PKCS11H_DEBUG (
+ 		PKCS11H_LOG_DEBUG2,
+ 		"PKCS#11: pkcs11h_certificate_deserializeCertificateId return rv=%lu-'%s'",
+diff --git a/pkcs11-helper-1.22/lib/pkcs11h-util.c b/pkcs11-helper-1.22/lib/pkcs11h-util.c
+index 0743fd1..f90e443 100644
+--- a/pkcs11-helper-1.22/lib/pkcs11h-util.c
++++ b/pkcs11-helper-1.22/lib/pkcs11h-util.c
+@@ -110,12 +110,7 @@ _pkcs11h_util_hexToBinary (
+ 		p++;
+ 	}
+ 
+-	if (*p != '\x0') {
+-		return CKR_ATTRIBUTE_VALUE_INVALID;
+-	}
+-	else {
+-		return CKR_OK;
+-	}
++	return CKR_OK;
+ }
+ 
+ CK_RV