| From 2a092116026030014c4e88430adabdf2651af78e Mon Sep 17 00:00:00 2001 |
| From: Sam Leffler <sleffler@chromium.org> |
| Date: Sun, 30 Apr 2017 09:12:23 -0700 |
| Subject: [PATCH 2/4] CHROMIUM: add fallback search for pkcs11 cert |
| |
| Openvpn expects the PKCS11 ID to be specified using an ID suitable |
| for the PKCS11 helper functions (as displayed by --show-pkcs11-ids). |
| But for Chrome OS this is not how things are done; instead clients pass |
| the PKCS11 slot number and short-form ID. To cope with this, if the |
| specified ID cannot be serialized due to a missing token ID, search the |
| certificate list for the first entry with the specified ID. |
| |
| BUG=none |
| TEST=manual:provision openvpn and use the UI to connect |
| |
| Signed-off-by: Sam Leffler <sleffler@chromium.org> |
| Signed-off-by: Kevin Cernekee <cernekee@chromium.org> |
| --- |
| src/openvpn/pkcs11.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++-- |
| 1 file changed, 111 insertions(+), 4 deletions(-) |
| |
| diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c |
| index 3e494e51f1a6..292a94871cbe 100644 |
| --- a/src/openvpn/pkcs11.c |
| +++ b/src/openvpn/pkcs11.c |
| @@ -665,6 +665,115 @@ cleanup: |
| return success; |
| } |
| |
| +static CK_RV |
| +_hexToBinary( |
| + unsigned char * const target, |
| + const char * const source, |
| + size_t * const p_target_size |
| +) { |
| + size_t target_max_size = *p_target_size; |
| + const char *p; |
| + char buf[3] = { 0, 0, 0 }; |
| + int i; |
| + |
| + i = 0; |
| + *p_target_size = 0; |
| + for (p = source; *p != '\0' && *p_target_size < target_max_size; p++) { |
| + if (!isxdigit (*p)) |
| + continue; |
| + buf[i%2] = *p; |
| + if ((i%2) == 1) { |
| + unsigned v; |
| + if (sscanf (buf, "%x", &v) != 1) |
| + v = 0; |
| + target[*p_target_size] = v & 0xff; |
| + (*p_target_size)++; |
| + } |
| + i++; |
| + } |
| + return (*p == '\0' ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID); |
| +} |
| + |
| +static CK_RV |
| +get_certificate_id( |
| + pkcs11h_certificate_id_t *p_certificate_id, |
| + const char * const pkcs11_id |
| +) { |
| + pkcs11h_certificate_id_list_t user_certificates = NULL; |
| + pkcs11h_certificate_id_list_t current = NULL; |
| + char *cka_id = NULL; |
| + size_t cka_id_size; |
| + CK_RV rv; |
| + |
| + rv = pkcs11h_certificate_deserializeCertificateId ( |
| + p_certificate_id, |
| + pkcs11_id |
| + ); |
| + if (rv == CKR_OK) |
| + return rv; |
| + if (rv != CKR_ATTRIBUTE_VALUE_INVALID) { |
| + msg (M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv)); |
| + return rv; |
| + } |
| + |
| + /* |
| + * The specified certificate id lacks the token id, search the |
| + * cert list for first matching id. |
| + */ |
| + cka_id_size = strlen(pkcs11_id)/2; |
| + if ( |
| + (cka_id = (char *)malloc (cka_id_size)) == NULL || |
| + (rv = _hexToBinary (cka_id, pkcs11_id, &cka_id_size)) != CKR_OK |
| + ) { |
| + msg (M_FATAL, "PKCS#11: get_certificate_id: Cannot convert id %ld-'%s'", rv, pkcs11h_getMessage (rv)); |
| + goto cleanup; |
| + } |
| + |
| + if ( |
| + (rv = pkcs11h_certificate_enumCertificateIds ( |
| + PKCS11H_ENUM_METHOD_CACHE_EXIST, |
| + NULL, |
| + PKCS11H_PROMPT_MASK_ALLOW_ALL, |
| + NULL, |
| + &user_certificates |
| + )) != CKR_OK |
| + ) { |
| + msg (M_FATAL, "PKCS#11: get_certificate_id: Cannot enumerate certificates %ld-'%s'", rv, pkcs11h_getMessage (rv)); |
| + goto cleanup; |
| + } |
| + |
| + rv = CKR_ATTRIBUTE_VALUE_INVALID; |
| + for (current = user_certificates;current != NULL; current = current->next) { |
| + pkcs11h_certificate_id_t cid = current->certificate_id; |
| + |
| + if ( |
| + cka_id_size == cid->attrCKA_ID_size && |
| + memcmp( |
| + cka_id, |
| + cid->attrCKA_ID, |
| + cid->attrCKA_ID_size |
| + ) == 0 |
| + ) { |
| + rv = pkcs11h_certificate_duplicateCertificateId( |
| + p_certificate_id, |
| + cid |
| + ); |
| + break; |
| + } |
| + } |
| + |
| +cleanup: |
| + if (user_certificates != NULL) { |
| + pkcs11h_certificate_freeCertificateIdList (user_certificates); |
| + user_certificates = NULL; |
| + } |
| + if (cka_id != NULL) { |
| + free (cka_id); |
| + cka_id = NULL; |
| + } |
| + return rv; |
| +} |
| + |
| int |
| tls_ctx_use_pkcs11( |
| struct tls_root_ctx *const ssl_ctx, |
| @@ -716,26 +825,24 @@ tls_ctx_use_pkcs11( |
| } |
| |
| if ( |
| - (rv = pkcs11h_certificate_deserializeCertificateId( |
| + (rv = get_certificate_id( |
| &certificate_id, |
| id_resp.password |
| )) != CKR_OK |
| ) |
| { |
| - msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv)); |
| goto cleanup; |
| } |
| } |
| else |
| { |
| if ( |
| - (rv = pkcs11h_certificate_deserializeCertificateId( |
| + (rv = get_certificate_id( |
| &certificate_id, |
| pkcs11_id |
| )) != CKR_OK |
| ) |
| { |
| - msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv)); |
| goto cleanup; |
| } |
| } |
| -- |
| 2.13.0.rc0.306.g87b477812d-goog |
| |