static int are_attributes_empty (P11KitUri *uri) { return (p11_kit_uri_get_attribute (uri, CKA_LABEL) == NULL && p11_kit_uri_get_attribute (uri, CKA_ID) == NULL && p11_kit_uri_get_attribute (uri, CKA_CLASS) == NULL); }
static void test_uri_parse_with_empty_id (void) { CK_ATTRIBUTE_PTR attr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:id=;type=cert", P11_KIT_URI_FOR_ANY, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_ID); assert_ptr_not_null (attr); p11_kit_uri_free (uri); /* really empty */ uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:type=cert", P11_KIT_URI_FOR_ANY, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_ID); assert (attr == NULL); p11_kit_uri_free (uri); }
static void test_uri_parse_with_label_and_new_klass (void) { CK_ATTRIBUTE_PTR attr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:object=Test%20Label;type=cert", P11_KIT_URI_FOR_ANY, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_not_null (attr); assert (attr->ulValueLen == strlen ("Test Label")); assert (memcmp (attr->pValue, "Test Label", attr->ulValueLen) == 0); attr = p11_kit_uri_get_attribute (uri, CKA_CLASS); assert_ptr_not_null (attr); assert (attr->ulValueLen == sizeof (CK_OBJECT_CLASS)); assert (*((CK_OBJECT_CLASS_PTR)attr->pValue) == CKO_CERTIFICATE); p11_kit_uri_free (uri); }
static void test_uri_get_set_attribute (void) { CK_ATTRIBUTE attr; CK_ATTRIBUTE_PTR ptr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_eq (NULL, ptr); ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL); assert_num_eq (P11_KIT_URI_OK, ret); ret = p11_kit_uri_clear_attribute (uri, CKA_COLOR); assert_num_eq (P11_KIT_URI_NOT_FOUND, ret); attr.type = CKA_LABEL; attr.pValue = "Test"; attr.ulValueLen = 4; ret = p11_kit_uri_set_attribute (uri, &attr); assert_num_eq (P11_KIT_URI_OK, ret); /* We can set other attributes */ attr.type = CKA_COLOR; ret = p11_kit_uri_set_attribute (uri, &attr); assert_num_eq (P11_KIT_URI_OK, ret); /* And get them too */ ptr = p11_kit_uri_get_attribute (uri, CKA_COLOR); assert_ptr_not_null (ptr); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_not_null (ptr); assert (ptr->type == CKA_LABEL); assert (ptr->ulValueLen == 4); assert (memcmp (ptr->pValue, "Test", 4) == 0); ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL); assert_num_eq (P11_KIT_URI_OK, ret); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_eq (NULL, ptr); p11_kit_uri_free (uri); }
static void test_uri_parse_parse_unknown_object_type (void) { P11KitUri *uri; CK_ATTRIBUTE_PTR attr; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:type=unknown", P11_KIT_URI_FOR_OBJECT, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_CLASS); assert_ptr_eq (NULL, attr); p11_kit_uri_free (uri); }
static void test_uri_parse_secret_key (void) { P11KitUri *uri; CK_ATTRIBUTE_PTR attr; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:type=secret-key", P11_KIT_URI_FOR_OBJECT, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_CLASS); assert_ptr_not_null (attr); assert (attr->ulValueLen == sizeof (CK_OBJECT_CLASS)); assert (*((CK_OBJECT_CLASS_PTR)attr->pValue) == CKO_SECRET_KEY); p11_kit_uri_free (uri); }
static void test_uri_parse_with_id (void) { CK_ATTRIBUTE_PTR attr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:id=%54%45%53%54%00", P11_KIT_URI_FOR_OBJECT, uri); assert_num_eq (P11_KIT_URI_OK, ret); /* Note that there's a NULL in the attribute (end) */ attr = p11_kit_uri_get_attribute (uri, CKA_ID); assert_ptr_not_null (attr); assert (attr->ulValueLen == 5); assert (memcmp (attr->pValue, "TEST", 5) == 0); p11_kit_uri_free (uri); }
static void test_uri_parse_with_label (void) { CK_ATTRIBUTE_PTR attr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:object=Test%20Label", P11_KIT_URI_FOR_ANY, uri); assert_num_eq (P11_KIT_URI_OK, ret); assert (is_module_empty (uri)); assert (is_slot_empty (uri)); assert (is_token_empty (uri)); attr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_not_null (attr); assert (attr->ulValueLen == strlen ("Test Label")); assert (memcmp (attr->pValue, "Test Label", attr->ulValueLen) == 0); p11_kit_uri_free (uri); }
/** * gnutls_pkcs11_privkey_import_url: * @pkey: The private key * @url: a PKCS 11 url identifying the key * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags * * This function will "import" a PKCS 11 URL identifying a private * key to the #gnutls_pkcs11_privkey_t type. In reality since * in most cases keys cannot be exported, the private key structure * is being associated with the available operations on the token. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; struct ck_attribute *attr; struct ck_attribute a[4]; ck_key_type_t key_type; ck_bool_t reauth = 0; PKCS11_CHECK_INIT; memset(&pkey->sinfo, 0, sizeof(pkey->sinfo)); if (pkey->url) { gnutls_free(pkey->url); pkey->url = NULL; } if (pkey->uinfo) { p11_kit_uri_free(pkey->uinfo); pkey->uinfo = NULL; } pkey->url = gnutls_strdup(url); if (pkey->url == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY); if (ret < 0) { gnutls_assert(); goto cleanup; } pkey->flags = flags; attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS); if (!attr || attr->value_len != sizeof(ck_object_class_t) || *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) { gnutls_assert(); ret = GNUTLS_E_INVALID_REQUEST; goto cleanup; } attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID); if (!attr) { attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL); if (!attr) { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } } FIND_OBJECT(pkey); pkey->pk_algorithm = GNUTLS_PK_UNKNOWN; a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof(key_type); if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1) == CKR_OK) { pkey->pk_algorithm = key_type_to_pk(key_type); } if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log ("Cannot determine PKCS #11 key algorithm\n"); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } a[0].type = CKA_ALWAYS_AUTHENTICATE; a[0].value = &reauth; a[0].value_len = sizeof(reauth); if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1) == CKR_OK) { pkey->reauth = reauth; } ret = 0; return ret; cleanup: if (pkey->uinfo != NULL) { p11_kit_uri_free(pkey->uinfo); pkey->uinfo = NULL; } gnutls_free(pkey->url); pkey->url = NULL; return ret; }
/** * gnutls_pkcs11_privkey_import_url: * @pkey: The structure to store the parsed key * @url: a PKCS 11 url identifying the key * @flags: sequence of GNUTLS_PKCS_PRIVKEY_* * * This function will "import" a PKCS 11 URL identifying a private * key to the #gnutls_pkcs11_privkey_t structure. In reality since * in most cases keys cannot be exported, the private key structure * is being associated with the available operations on the token. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; struct ck_attribute *attr; ck_object_handle_t obj; struct ck_attribute a[4]; ck_key_type_t key_type; struct pkcs11_session_info sinfo; PKCS11_CHECK_INIT; memset(&sinfo, 0, sizeof(sinfo)); ret = pkcs11_url_to_info(url, &pkey->info); if (ret < 0) { gnutls_assert(); return ret; } pkey->flags = flags; attr = p11_kit_uri_get_attribute(pkey->info, CKA_CLASS); if (!attr || attr->value_len != sizeof(ck_object_class_t) || *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } attr = p11_kit_uri_get_attribute(pkey->info, CKA_ID); if (!attr || !attr->value_len) { attr = p11_kit_uri_get_attribute(pkey->info, CKA_LABEL); if (!attr || !attr->value_len) { gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } } FIND_OBJECT(&sinfo, &pkey->pin, obj, pkey); a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof(key_type); if (pkcs11_get_attribute_value(sinfo.module, sinfo.pks, obj, a, 1) == CKR_OK) { pkey->pk_algorithm = mech_to_pk(key_type); if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log ("Cannot determine PKCS #11 key algorithm\n"); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } } ret = 0; if (pkey->sinfo.init) pkcs11_close_session(&pkey->sinfo); if (sinfo.tinfo.max_session_count != 1) { /* We do not keep the session open in tokens that can * only support a single session. */ memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo)); pkey->obj = obj; return ret; } cleanup: pkcs11_close_session(&sinfo); return ret; }
/** * p11_kit_uri_format: * @uri: The URI. * @uri_type: The type of URI that should be produced. * @string: Location to store a newly allocated string. * * Format a PKCS\#11 URI into a string. * * Fields which are zeroed out will not be included in the resulting string. * Attributes which are not present will also not be included. * * The uri_type of URI specified limits the different parts of the resulting * URI. To format a URI containing all possible information use * %P11_KIT_URI_FOR_ANY * * The resulting string should be freed with free(). * * Returns: %P11_KIT_URI_OK if the URI was formatted successfully. * %P11_KIT_URI_NO_MEMORY if memory allocation failed. */ int p11_kit_uri_format (P11KitUri *uri, P11KitUriType uri_type, char **string) { char *result = NULL; size_t length = 0; int is_first = 1; result = malloc (128); if (!result) return P11_KIT_URI_NO_MEMORY; length = P11_KIT_URI_SCHEME_LEN; memcpy (result, P11_KIT_URI_SCHEME, length); result[length] = ':'; result[++length] = 0; if ((uri_type & P11_KIT_URI_FOR_MODULE) == P11_KIT_URI_FOR_MODULE) { if (!format_struct_string (&result, &length, &is_first, "library-description", uri->module.libraryDescription, sizeof (uri->module.libraryDescription)) || !format_struct_string (&result, &length, &is_first, "library-manufacturer", uri->module.manufacturerID, sizeof (uri->module.manufacturerID))) { free (result); return P11_KIT_URI_NO_MEMORY; } } if ((uri_type & P11_KIT_URI_FOR_MODULE_WITH_VERSION) == P11_KIT_URI_FOR_MODULE_WITH_VERSION) { if (!format_struct_version (&result, &length, &is_first, "library-version", &uri->module.libraryVersion)) { free (result); return P11_KIT_URI_NO_MEMORY; } } if ((uri_type & P11_KIT_URI_FOR_TOKEN) == P11_KIT_URI_FOR_TOKEN) { if (!format_struct_string (&result, &length, &is_first, "model", uri->token.model, sizeof (uri->token.model)) || !format_struct_string (&result, &length, &is_first, "manufacturer", uri->token.manufacturerID, sizeof (uri->token.manufacturerID)) || !format_struct_string (&result, &length, &is_first, "serial", uri->token.serialNumber, sizeof (uri->token.serialNumber)) || !format_struct_string (&result, &length, &is_first, "token", uri->token.label, sizeof (uri->token.label))) { free (result); return P11_KIT_URI_NO_MEMORY; } } if ((uri_type & P11_KIT_URI_FOR_OBJECT) == P11_KIT_URI_FOR_OBJECT) { if (!format_attribute_string (&result, &length, &is_first, "id", p11_kit_uri_get_attribute (uri, CKA_ID)) || !format_attribute_string (&result, &length, &is_first, "object", p11_kit_uri_get_attribute (uri, CKA_LABEL))) { free (result); return P11_KIT_URI_NO_MEMORY; } if (!format_attribute_class (&result, &length, &is_first, "object-type", p11_kit_uri_get_attribute (uri, CKA_CLASS))) { free (result); return P11_KIT_URI_NO_MEMORY; } } if (uri->pin_source) { format_encode_string (&result, &length, &is_first, "pin-source", (const unsigned char*)uri->pin_source, strlen (uri->pin_source)); } *string = result; return P11_KIT_URI_OK; }
/** * gnutls_pkcs11_privkey_import_url: * @pkey: The structure to store the parsed key * @url: a PKCS 11 url identifying the key * @flags: sequence of GNUTLS_PKCS_PRIVKEY_* * * This function will "import" a PKCS 11 URL identifying a private * key to the #gnutls_pkcs11_privkey_t structure. In reality since * in most cases keys cannot be exported, the private key structure * is being associated with the available operations on the token. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; struct ck_function_list *module; struct ck_attribute *attr; ck_session_handle_t pks; ck_object_handle_t obj; struct ck_attribute a[4]; ck_key_type_t key_type; ret = pkcs11_url_to_info (url, &pkey->info); if (ret < 0) { gnutls_assert (); return ret; } pkey->flags = flags; attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS); if (!attr || attr->value_len != sizeof (ck_object_class_t) || *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID); if (!attr || !attr->value_len) { attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL); if (!attr || !attr->value_len) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } } FIND_OBJECT (module, pks, obj, pkey); a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof (key_type); if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) { pkey->pk_algorithm = mech_to_pk(key_type); if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n"); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } } ret = 0; cleanup: pkcs11_close_session (module, pks); return ret; }
static void test_uri_build_with_attributes (void) { char *string = NULL; P11KitUri *uri; P11KitUri *check; CK_OBJECT_CLASS klass; CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE at; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); at.type = CKA_LABEL; at.pValue = "The Label"; at.ulValueLen = 9; ret = p11_kit_uri_set_attribute (uri, &at); assert_num_eq (P11_KIT_URI_OK, ret); at.type = CKA_ID; at.pValue = "HELLO"; at.ulValueLen = 5; ret = p11_kit_uri_set_attribute (uri, &at); assert_num_eq (P11_KIT_URI_OK, ret); klass = CKO_DATA; at.type = CKA_CLASS; at.pValue = &klass; at.ulValueLen = sizeof (klass); ret = p11_kit_uri_set_attribute (uri, &at); assert_num_eq (P11_KIT_URI_OK, ret); ret = p11_kit_uri_format (uri, P11_KIT_URI_FOR_ANY, &string); assert_num_eq (P11_KIT_URI_OK, ret); check = p11_kit_uri_new (); assert_ptr_not_null (check); ret = p11_kit_uri_parse (string, P11_KIT_URI_FOR_ANY, check); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (check, CKA_LABEL); assert_ptr_not_null (attr); assert (attr->ulValueLen == 9); assert (memcmp (attr->pValue, "The Label", attr->ulValueLen) == 0); attr = p11_kit_uri_get_attribute (check, CKA_CLASS); assert_ptr_not_null (attr); assert (attr->ulValueLen == sizeof (klass)); assert (*((CK_OBJECT_CLASS_PTR)attr->pValue) == klass); attr = p11_kit_uri_get_attribute (check, CKA_ID); assert_ptr_not_null (attr); assert (attr->ulValueLen == 5); assert (memcmp (attr->pValue, "HELLO", attr->ulValueLen) == 0); p11_kit_uri_free (check); assert (strstr (string, "object=The%20Label") != NULL); assert (strstr (string, "type=data") != NULL); assert (strstr (string, "id=%48%45%4c%4c%4f") != NULL); free (string); p11_kit_uri_free (uri); }