199ebb4caSwyllys /* 299ebb4caSwyllys * CDDL HEADER START 399ebb4caSwyllys * 499ebb4caSwyllys * The contents of this file are subject to the terms of the 599ebb4caSwyllys * Common Development and Distribution License (the "License"). 699ebb4caSwyllys * You may not use this file except in compliance with the License. 799ebb4caSwyllys * 899ebb4caSwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 999ebb4caSwyllys * or http://www.opensolaris.org/os/licensing. 1099ebb4caSwyllys * See the License for the specific language governing permissions 1199ebb4caSwyllys * and limitations under the License. 1299ebb4caSwyllys * 1399ebb4caSwyllys * When distributing Covered Code, include this CDDL HEADER in each 1499ebb4caSwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1599ebb4caSwyllys * If applicable, add the following below this CDDL HEADER, with the 1699ebb4caSwyllys * fields enclosed by brackets "[]" replaced with your own identifying 1799ebb4caSwyllys * information: Portions Copyright [yyyy] [name of copyright owner] 1899ebb4caSwyllys * 1999ebb4caSwyllys * CDDL HEADER END 2099ebb4caSwyllys * 21*47e946e7SWyllys Ingersoll * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2271593db2Swyllys * Use is subject to license terms. 2399ebb4caSwyllys */ 2499ebb4caSwyllys 2599ebb4caSwyllys #include <stdio.h> 2699ebb4caSwyllys #include <stdlib.h> 2799ebb4caSwyllys #include <string.h> 2899ebb4caSwyllys #include <ctype.h> 2999ebb4caSwyllys #include <security/cryptoki.h> 3099ebb4caSwyllys #include <kmfapi.h> 3199ebb4caSwyllys #include <kmfapiP.h> 3299ebb4caSwyllys #include <cryptoutil.h> 3399ebb4caSwyllys 3499ebb4caSwyllys /* 3599ebb4caSwyllys * memcmp_pad_max() is a specialized version of memcmp() which 3699ebb4caSwyllys * compares two pieces of data up to a maximum length. If the 3799ebb4caSwyllys * the two data match up the maximum length, they are considered 3899ebb4caSwyllys * matching. Trailing blanks do not cause the match to fail if 3999ebb4caSwyllys * one of the data is shorted. 4099ebb4caSwyllys * 4199ebb4caSwyllys * Examples of matches: 4299ebb4caSwyllys * "one" | 4399ebb4caSwyllys * "one " | 4499ebb4caSwyllys * ^maximum length 4599ebb4caSwyllys * 4699ebb4caSwyllys * "Number One | X" (X is beyond maximum length) 4799ebb4caSwyllys * "Number One " | 4899ebb4caSwyllys * ^maximum length 4999ebb4caSwyllys * 5099ebb4caSwyllys * Examples of mismatches: 5199ebb4caSwyllys * " one" 5299ebb4caSwyllys * "one" 5399ebb4caSwyllys * 5499ebb4caSwyllys * "Number One X|" 5599ebb4caSwyllys * "Number One |" 5699ebb4caSwyllys * ^maximum length 5799ebb4caSwyllys */ 5899ebb4caSwyllys static int 5999ebb4caSwyllys memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz) 6099ebb4caSwyllys { 6199ebb4caSwyllys uint_t len, extra_len; 6299ebb4caSwyllys char *marker; 6399ebb4caSwyllys 6499ebb4caSwyllys /* No point in comparing anything beyond max_sz */ 6599ebb4caSwyllys if (d1_len > max_sz) 6699ebb4caSwyllys d1_len = max_sz; 6799ebb4caSwyllys if (d2_len > max_sz) 6899ebb4caSwyllys d2_len = max_sz; 6999ebb4caSwyllys 7099ebb4caSwyllys /* Find shorter of the two data. */ 7199ebb4caSwyllys if (d1_len <= d2_len) { 7299ebb4caSwyllys len = d1_len; 7399ebb4caSwyllys extra_len = d2_len; 7499ebb4caSwyllys marker = d2; 7599ebb4caSwyllys } else { /* d1_len > d2_len */ 7699ebb4caSwyllys len = d2_len; 7799ebb4caSwyllys extra_len = d1_len; 7899ebb4caSwyllys marker = d1; 7999ebb4caSwyllys } 8099ebb4caSwyllys 8199ebb4caSwyllys /* Have a match in the shortest length of data? */ 8299ebb4caSwyllys if (memcmp(d1, d2, len) != 0) 8399ebb4caSwyllys /* CONSTCOND */ 8499ebb4caSwyllys return (1); 8599ebb4caSwyllys 8699ebb4caSwyllys /* If the rest of longer data is nulls or blanks, call it a match. */ 870fb5f8a6SWyllys Ingersoll while (len < extra_len && marker[len]) 8899ebb4caSwyllys if (!isspace(marker[len++])) 8999ebb4caSwyllys /* CONSTCOND */ 9099ebb4caSwyllys return (1); 9199ebb4caSwyllys return (0); 9299ebb4caSwyllys } 9399ebb4caSwyllys 9499ebb4caSwyllys static KMF_RETURN 9599ebb4caSwyllys kmf_get_token_slots(KMF_HANDLE *handle, CK_SLOT_ID_PTR *slot_list, 9699ebb4caSwyllys CK_ULONG *slot_count) 9799ebb4caSwyllys { 9899ebb4caSwyllys 9999ebb4caSwyllys KMF_RETURN kmf_rv = KMF_OK; 10099ebb4caSwyllys CK_RV ck_rv = CKR_OK; 10199ebb4caSwyllys CK_ULONG tmp_count = 0; 10299ebb4caSwyllys CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 10399ebb4caSwyllys 10499ebb4caSwyllys ck_rv = C_GetSlotList(1, NULL_PTR, &tmp_count); 10530a5e8faSwyllys if (ck_rv == CKR_CRYPTOKI_NOT_INITIALIZED) { 10630a5e8faSwyllys ck_rv = C_Initialize(NULL); 10730a5e8faSwyllys if ((ck_rv != CKR_OK) && 10830a5e8faSwyllys (ck_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 10930a5e8faSwyllys return (KMF_ERR_UNINITIALIZED); 11030a5e8faSwyllys if (ck_rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) 11130a5e8faSwyllys ck_rv = CKR_OK; 11230a5e8faSwyllys 11330a5e8faSwyllys ck_rv = C_GetSlotList(1, NULL_PTR, &tmp_count); 11430a5e8faSwyllys } 11599ebb4caSwyllys if (ck_rv != CKR_OK) { 11699ebb4caSwyllys if (handle != NULL) { 11799ebb4caSwyllys handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 11899ebb4caSwyllys handle->lasterr.errcode = ck_rv; 11999ebb4caSwyllys } 12099ebb4caSwyllys return (KMF_ERR_INTERNAL); 12199ebb4caSwyllys } 12299ebb4caSwyllys 12399ebb4caSwyllys if (tmp_count == 0) { 12499ebb4caSwyllys *slot_list = NULL_PTR; 12599ebb4caSwyllys *slot_count = 0; 12699ebb4caSwyllys return (KMF_OK); 12799ebb4caSwyllys } 12899ebb4caSwyllys 12999ebb4caSwyllys /* Allocate initial space for the slot list. */ 13099ebb4caSwyllys if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 13199ebb4caSwyllys sizeof (CK_SLOT_ID))) == NULL) 13299ebb4caSwyllys return (KMF_ERR_MEMORY); 13399ebb4caSwyllys 13499ebb4caSwyllys /* Then get the slot list itself. */ 13599ebb4caSwyllys for (;;) { 13699ebb4caSwyllys ck_rv = C_GetSlotList(1, tmp_list, &tmp_count); 13799ebb4caSwyllys if (ck_rv == CKR_OK) { 13899ebb4caSwyllys *slot_list = tmp_list; 13999ebb4caSwyllys *slot_count = tmp_count; 14099ebb4caSwyllys kmf_rv = KMF_OK; 14199ebb4caSwyllys break; 14299ebb4caSwyllys } 14399ebb4caSwyllys 14499ebb4caSwyllys if (ck_rv != CKR_BUFFER_TOO_SMALL) { 14599ebb4caSwyllys free(tmp_list); 14699ebb4caSwyllys if (handle != NULL) { 14799ebb4caSwyllys handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 14899ebb4caSwyllys handle->lasterr.errcode = ck_rv; 14999ebb4caSwyllys } 15099ebb4caSwyllys kmf_rv = KMF_ERR_INTERNAL; 15199ebb4caSwyllys break; 15299ebb4caSwyllys } 15399ebb4caSwyllys 15499ebb4caSwyllys /* 15599ebb4caSwyllys * If the number of slots grew, try again. This 15699ebb4caSwyllys * is to be consistent with pktool in ONNV. 15799ebb4caSwyllys */ 15899ebb4caSwyllys if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 15999ebb4caSwyllys tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 16099ebb4caSwyllys free(tmp_list); 16199ebb4caSwyllys kmf_rv = KMF_ERR_MEMORY; 16299ebb4caSwyllys break; 16399ebb4caSwyllys } 16499ebb4caSwyllys tmp_list = tmp2_list; 16599ebb4caSwyllys } 16699ebb4caSwyllys 16799ebb4caSwyllys return (kmf_rv); 16899ebb4caSwyllys } 16999ebb4caSwyllys 17099ebb4caSwyllys /* 17199ebb4caSwyllys * Returns pointer to either null-terminator or next unescaped colon. The 17299ebb4caSwyllys * string to be extracted starts at the beginning and goes until one character 17399ebb4caSwyllys * before this pointer. If NULL is returned, the string itself is NULL. 17499ebb4caSwyllys */ 17599ebb4caSwyllys static char * 17699ebb4caSwyllys find_unescaped_colon(char *str) 17799ebb4caSwyllys { 17899ebb4caSwyllys char *end; 17999ebb4caSwyllys 18099ebb4caSwyllys if (str == NULL) 18199ebb4caSwyllys return (NULL); 18299ebb4caSwyllys 18399ebb4caSwyllys while ((end = strchr(str, ':')) != NULL) { 18499ebb4caSwyllys if (end != str && *(end-1) != '\\') 18599ebb4caSwyllys return (end); 18699ebb4caSwyllys str = end + 1; /* could point to null-terminator */ 18799ebb4caSwyllys } 18899ebb4caSwyllys if (end == NULL) 18999ebb4caSwyllys end = strchr(str, '\0'); 19099ebb4caSwyllys return (end); 19199ebb4caSwyllys } 19299ebb4caSwyllys 19399ebb4caSwyllys /* 19499ebb4caSwyllys * Compresses away any characters escaped with backslash from given string. 19599ebb4caSwyllys * The string is altered in-place. Example, "ab\:\\e" becomes "ab:\e". 19699ebb4caSwyllys */ 19799ebb4caSwyllys static void 19899ebb4caSwyllys unescape_str(char *str) 19999ebb4caSwyllys { 20099ebb4caSwyllys boolean_t escaped = B_FALSE; 20199ebb4caSwyllys char *mark; 20299ebb4caSwyllys 20399ebb4caSwyllys if (str == NULL) 20499ebb4caSwyllys return; 20599ebb4caSwyllys 20699ebb4caSwyllys for (mark = str; *str != '\0'; str++) { 20799ebb4caSwyllys if (*str != '\\' || escaped == B_TRUE) { 20899ebb4caSwyllys *mark++ = *str; 20999ebb4caSwyllys escaped = B_FALSE; 21099ebb4caSwyllys } else { 21199ebb4caSwyllys escaped = B_TRUE; 21299ebb4caSwyllys } 21399ebb4caSwyllys } 21499ebb4caSwyllys *mark = '\0'; 21599ebb4caSwyllys } 21699ebb4caSwyllys 21799ebb4caSwyllys 21899ebb4caSwyllys /* 21999ebb4caSwyllys * Given a colon-separated token specifier, this functions splits it into 22099ebb4caSwyllys * its label, manufacturer ID (if any), and serial number (if any). Literal 22199ebb4caSwyllys * colons within the label/manuf/serial can be escaped with a backslash. 22299ebb4caSwyllys * Fields can left blank and trailing colons can be omitted, however leading 22399ebb4caSwyllys * colons are required as placeholders. For example, these are equivalent: 22499ebb4caSwyllys * (a) "lbl", "lbl:", "lbl::" (b) "lbl:man", "lbl:man:" 22599ebb4caSwyllys * but these are not: 22699ebb4caSwyllys * (c) "man", ":man" (d) "ser", "::ser" 22799ebb4caSwyllys * Furthermore, the token label is required always. 22899ebb4caSwyllys * 22999ebb4caSwyllys * The buffer containing the token specifier is altered by replacing the 23099ebb4caSwyllys * colons to null-terminators, and pointers returned are pointers into this 23199ebb4caSwyllys * string. No new memory is allocated. 23299ebb4caSwyllys */ 23399ebb4caSwyllys static int 23499ebb4caSwyllys parse_token_spec(char *token_spec, char **token_name, char **manuf_id, 23599ebb4caSwyllys char **serial_no) 23699ebb4caSwyllys { 23799ebb4caSwyllys char *mark; 23899ebb4caSwyllys 23999ebb4caSwyllys if (token_spec == NULL || *token_spec == '\0') { 24099ebb4caSwyllys return (-1); 24199ebb4caSwyllys } 24299ebb4caSwyllys 24399ebb4caSwyllys *token_name = NULL; 24499ebb4caSwyllys *manuf_id = NULL; 24599ebb4caSwyllys *serial_no = NULL; 24699ebb4caSwyllys 24799ebb4caSwyllys /* Token label (required) */ 24899ebb4caSwyllys mark = find_unescaped_colon(token_spec); 24999ebb4caSwyllys *token_name = token_spec; 25099ebb4caSwyllys if (*mark != '\0') 25199ebb4caSwyllys *mark++ = '\0'; /* mark points to next field, if any */ 25299ebb4caSwyllys unescape_str(*token_name); 25399ebb4caSwyllys 25499ebb4caSwyllys if (*(*token_name) == '\0') { /* token label is required */ 25599ebb4caSwyllys return (-1); 25699ebb4caSwyllys } 25799ebb4caSwyllys 25899ebb4caSwyllys if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */ 25999ebb4caSwyllys return (0); 26099ebb4caSwyllys token_spec = mark; 26199ebb4caSwyllys 26299ebb4caSwyllys /* Manufacturer identifier (optional) */ 26399ebb4caSwyllys mark = find_unescaped_colon(token_spec); 26499ebb4caSwyllys *manuf_id = token_spec; 26599ebb4caSwyllys if (*mark != '\0') 26699ebb4caSwyllys *mark++ = '\0'; /* mark points to next field, if any */ 26799ebb4caSwyllys unescape_str(*manuf_id); 26899ebb4caSwyllys 26999ebb4caSwyllys if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */ 27099ebb4caSwyllys return (0); 27199ebb4caSwyllys token_spec = mark; 27299ebb4caSwyllys 27399ebb4caSwyllys /* Serial number (optional) */ 27499ebb4caSwyllys mark = find_unescaped_colon(token_spec); 27599ebb4caSwyllys *serial_no = token_spec; 27699ebb4caSwyllys if (*mark != '\0') 27799ebb4caSwyllys *mark++ = '\0'; /* null-terminate, just in case */ 27899ebb4caSwyllys unescape_str(*serial_no); 27999ebb4caSwyllys 28099ebb4caSwyllys return (0); 28199ebb4caSwyllys } 28299ebb4caSwyllys 28399ebb4caSwyllys /* 28499ebb4caSwyllys * Find slots that match a token identifier. Token labels take the 28599ebb4caSwyllys * form of: 28699ebb4caSwyllys * token_name:manufacturer:serial_number 28799ebb4caSwyllys * manufacterer and serial number are optional. If used, the fields 28899ebb4caSwyllys * are delimited by the colon ':' character. 28999ebb4caSwyllys */ 29099ebb4caSwyllys KMF_RETURN 29130a5e8faSwyllys kmf_pk11_token_lookup(KMF_HANDLE_T handle, char *label, CK_SLOT_ID *slot_id) 29299ebb4caSwyllys { 29399ebb4caSwyllys KMF_RETURN kmf_rv = KMF_OK; 29499ebb4caSwyllys CK_RV rv; 29599ebb4caSwyllys CK_SLOT_ID_PTR slot_list = NULL; 29699ebb4caSwyllys CK_TOKEN_INFO token_info; 29799ebb4caSwyllys CK_ULONG slot_count = 0; 29899ebb4caSwyllys int i; 29999ebb4caSwyllys uint_t len, max_sz; 30099ebb4caSwyllys boolean_t metaslot_status_enabled; 30199ebb4caSwyllys boolean_t metaslot_migrate_enabled; 30299ebb4caSwyllys char *metaslot_slot_info; 30399ebb4caSwyllys char *metaslot_token_info; 30499ebb4caSwyllys char *tmplabel = NULL; 30599ebb4caSwyllys char *token_name = NULL; 30699ebb4caSwyllys char *manuf_id = NULL; 30799ebb4caSwyllys char *serial_no = NULL; 30830a5e8faSwyllys boolean_t tok_match = B_FALSE; 30930a5e8faSwyllys boolean_t man_match = B_FALSE; 31030a5e8faSwyllys boolean_t ser_match = B_FALSE; 31199ebb4caSwyllys 31299ebb4caSwyllys if (slot_id == NULL || label == NULL || !strlen(label)) 31399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 31499ebb4caSwyllys 31599ebb4caSwyllys if (handle == NULL) { 31699ebb4caSwyllys rv = C_Initialize(NULL); 31799ebb4caSwyllys if ((rv != CKR_OK) && 31899ebb4caSwyllys (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 31999ebb4caSwyllys return (KMF_ERR_UNINITIALIZED); 32099ebb4caSwyllys } 32199ebb4caSwyllys } 32299ebb4caSwyllys 32399ebb4caSwyllys /* 32499ebb4caSwyllys * Parse token specifier into token_name, manuf_id, serial_no. 32599ebb4caSwyllys * Token_name is required; manuf_id and serial_no are optional. 32699ebb4caSwyllys */ 32799ebb4caSwyllys tmplabel = strdup(label); 32899ebb4caSwyllys if (tmplabel == NULL) 32999ebb4caSwyllys return (KMF_ERR_MEMORY); 33099ebb4caSwyllys 33199ebb4caSwyllys if (parse_token_spec(tmplabel, &token_name, &manuf_id, 33299ebb4caSwyllys &serial_no) < 0) { 33399ebb4caSwyllys free(tmplabel); 33499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 33599ebb4caSwyllys } 33699ebb4caSwyllys 33799ebb4caSwyllys /* Get a list of all slots with tokens present. */ 33899ebb4caSwyllys kmf_rv = kmf_get_token_slots(handle, &slot_list, &slot_count); 33999ebb4caSwyllys if (kmf_rv != KMF_OK) { 34099ebb4caSwyllys free(tmplabel); 34199ebb4caSwyllys return (kmf_rv); 34299ebb4caSwyllys } 34399ebb4caSwyllys 34499ebb4caSwyllys /* If there are no such slots, the desired token won't be found. */ 34599ebb4caSwyllys if (slot_count == 0) { 34699ebb4caSwyllys free(tmplabel); 34799ebb4caSwyllys return (KMF_ERR_TOKEN_NOT_PRESENT); 34899ebb4caSwyllys } 34999ebb4caSwyllys 35099ebb4caSwyllys /* Search the slot list for the token. */ 35199ebb4caSwyllys for (i = 0; i < slot_count; i++) { 35299ebb4caSwyllys if (C_GetTokenInfo(slot_list[i], &token_info) != CKR_OK) { 35399ebb4caSwyllys continue; 35499ebb4caSwyllys } 35599ebb4caSwyllys 35699ebb4caSwyllys /* See if the token label matches. */ 35799ebb4caSwyllys len = strlen(token_name); 35899ebb4caSwyllys max_sz = sizeof (token_info.label); 35999ebb4caSwyllys if (memcmp_pad_max(&(token_info.label), max_sz, token_name, 36099ebb4caSwyllys len, max_sz) == 0) 36199ebb4caSwyllys tok_match = B_TRUE; 36299ebb4caSwyllys /* 36399ebb4caSwyllys * If manufacturer id was given, see if it actually matches. 36499ebb4caSwyllys * If no manufacturer id was given, assume match is true. 36599ebb4caSwyllys */ 36699ebb4caSwyllys if (manuf_id) { 36799ebb4caSwyllys len = strlen(manuf_id); 36899ebb4caSwyllys max_sz = sizeof ((char *)(token_info.manufacturerID)); 36999ebb4caSwyllys if (memcmp_pad_max(&(token_info.manufacturerID), max_sz, 37099ebb4caSwyllys manuf_id, len, max_sz) == 0) 37199ebb4caSwyllys man_match = B_TRUE; 37299ebb4caSwyllys } else { 37399ebb4caSwyllys man_match = B_TRUE; 37499ebb4caSwyllys } 37599ebb4caSwyllys 37699ebb4caSwyllys /* 37799ebb4caSwyllys * If serial number was given, see if it actually matches. 37899ebb4caSwyllys * If no serial number was given, assume match is true. 37999ebb4caSwyllys */ 38099ebb4caSwyllys if (serial_no) { 38199ebb4caSwyllys len = strlen(serial_no); 38299ebb4caSwyllys max_sz = sizeof ((char *)(token_info.serialNumber)); 38399ebb4caSwyllys if (memcmp_pad_max(&(token_info.serialNumber), max_sz, 38499ebb4caSwyllys serial_no, len, max_sz) == 0) 38599ebb4caSwyllys ser_match = B_TRUE; 38699ebb4caSwyllys } else { 38799ebb4caSwyllys ser_match = B_TRUE; 38899ebb4caSwyllys } 38999ebb4caSwyllys 39099ebb4caSwyllys if (tok_match && man_match && ser_match) 39199ebb4caSwyllys break; /* found it! */ 39299ebb4caSwyllys } 39399ebb4caSwyllys 39499ebb4caSwyllys if (i < slot_count) { 39599ebb4caSwyllys /* found the desired token from the slotlist */ 39699ebb4caSwyllys *slot_id = slot_list[i]; 39799ebb4caSwyllys free(slot_list); 39899ebb4caSwyllys free(tmplabel); 39999ebb4caSwyllys return (KMF_OK); 40099ebb4caSwyllys } 40199ebb4caSwyllys 40299ebb4caSwyllys /* 40399ebb4caSwyllys * If we didn't find the token from the slotlist, check if this token 40499ebb4caSwyllys * is the one currently hidden by the metaslot. If that's case, 40599ebb4caSwyllys * we can just use the metaslot, the slot 0. 40699ebb4caSwyllys */ 40799ebb4caSwyllys kmf_rv = get_metaslot_info(&metaslot_status_enabled, 40899ebb4caSwyllys &metaslot_migrate_enabled, &metaslot_slot_info, 40999ebb4caSwyllys &metaslot_token_info); 41099ebb4caSwyllys if (kmf_rv) { 41199ebb4caSwyllys /* 41299ebb4caSwyllys * Failed to get the metaslot info. This usually means that 41399ebb4caSwyllys * metaslot is disabled from the system. 41499ebb4caSwyllys */ 41599ebb4caSwyllys kmf_rv = KMF_ERR_TOKEN_NOT_PRESENT; 41699ebb4caSwyllys } else { 41799ebb4caSwyllys max_sz = strlen(metaslot_token_info); 41899ebb4caSwyllys if (memcmp_pad_max(metaslot_token_info, max_sz, token_name, len, 41999ebb4caSwyllys max_sz) == 0) { 42099ebb4caSwyllys *slot_id = slot_list[0]; 42199ebb4caSwyllys } else { 42299ebb4caSwyllys kmf_rv = KMF_ERR_TOKEN_NOT_PRESENT; 42399ebb4caSwyllys } 42499ebb4caSwyllys free(metaslot_slot_info); 42599ebb4caSwyllys free(metaslot_token_info); 42699ebb4caSwyllys } 42799ebb4caSwyllys 42899ebb4caSwyllys free(slot_list); 42999ebb4caSwyllys free(tmplabel); 43099ebb4caSwyllys return (kmf_rv); 43199ebb4caSwyllys } 43299ebb4caSwyllys 43399ebb4caSwyllys KMF_RETURN 43430a5e8faSwyllys kmf_set_token_pin(KMF_HANDLE_T handle, 43530a5e8faSwyllys int num_attr, 43630a5e8faSwyllys KMF_ATTRIBUTE *attrlist) 43799ebb4caSwyllys { 43830a5e8faSwyllys KMF_RETURN ret = KMF_OK; 43999ebb4caSwyllys KMF_PLUGIN *plugin; 44030a5e8faSwyllys KMF_ATTRIBUTE_TESTER required_attrs[] = { 44130a5e8faSwyllys {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)}, 44230a5e8faSwyllys {KMF_CREDENTIAL_ATTR, FALSE, sizeof (KMF_CREDENTIAL), 44330a5e8faSwyllys sizeof (KMF_CREDENTIAL)}, 44430a5e8faSwyllys {KMF_NEWPIN_ATTR, FALSE, sizeof (KMF_CREDENTIAL), 44530a5e8faSwyllys sizeof (KMF_CREDENTIAL)}, 44630a5e8faSwyllys }; 44799ebb4caSwyllys 44830a5e8faSwyllys int num_req_attrs = sizeof (required_attrs) / 44930a5e8faSwyllys sizeof (KMF_ATTRIBUTE_TESTER); 45030a5e8faSwyllys uint32_t len; 45130a5e8faSwyllys KMF_KEYSTORE_TYPE kstype; 45299ebb4caSwyllys 45330a5e8faSwyllys if (handle == NULL) 45499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 45599ebb4caSwyllys 45630a5e8faSwyllys CLEAR_ERROR(handle, ret); 45730a5e8faSwyllys if (ret != KMF_OK) 45830a5e8faSwyllys return (ret); 45999ebb4caSwyllys 46030a5e8faSwyllys ret = test_attributes(num_req_attrs, required_attrs, 46130a5e8faSwyllys 0, NULL, num_attr, attrlist); 46230a5e8faSwyllys if (ret != KMF_OK) 46330a5e8faSwyllys return (ret); 46430a5e8faSwyllys 46530a5e8faSwyllys len = sizeof (kstype); 46630a5e8faSwyllys ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_attr, 46730a5e8faSwyllys &kstype, &len); 46830a5e8faSwyllys if (ret != KMF_OK) 46930a5e8faSwyllys return (ret); 47030a5e8faSwyllys 47130a5e8faSwyllys plugin = FindPlugin(handle, kstype); 47230a5e8faSwyllys if (plugin != NULL) { 47330a5e8faSwyllys if (plugin->funclist->SetTokenPin != NULL) 47430a5e8faSwyllys return (plugin->funclist->SetTokenPin(handle, num_attr, 47530a5e8faSwyllys attrlist)); 47630a5e8faSwyllys else 47799ebb4caSwyllys return (KMF_ERR_FUNCTION_NOT_FOUND); 47830a5e8faSwyllys } 47930a5e8faSwyllys return (KMF_ERR_PLUGIN_NOTFOUND); 48099ebb4caSwyllys } 48199ebb4caSwyllys 48299ebb4caSwyllys /* 48330a5e8faSwyllys * Name: kmf_select_token 48499ebb4caSwyllys * 48599ebb4caSwyllys * Description: 48699ebb4caSwyllys * This function enables the user of PKCS#11 plugin to select a 48799ebb4caSwyllys * particular PKCS#11 token. Valid token label are required in order to 48899ebb4caSwyllys * successfully complete this function. 48999ebb4caSwyllys * All subsequent KMF APIs, which specify PKCS#11 keystore as 49099ebb4caSwyllys * the backend, will be performed at the selected token. 49199ebb4caSwyllys * 49299ebb4caSwyllys * Parameters: 49399ebb4caSwyllys * label(input) - pointer to the token label 49499ebb4caSwyllys * 49599ebb4caSwyllys * Returns: 49699ebb4caSwyllys * A KMF_RETURN value indicating success or specifying a particular 49799ebb4caSwyllys * error condition. 49899ebb4caSwyllys * The value KMF_OK indicates success. All other values represent 49999ebb4caSwyllys * an error condition. 50099ebb4caSwyllys */ 50199ebb4caSwyllys KMF_RETURN 50230a5e8faSwyllys kmf_select_token(KMF_HANDLE_T handle, char *label, int readonly) 50399ebb4caSwyllys { 50499ebb4caSwyllys KMF_RETURN kmf_rv = KMF_OK; 50599ebb4caSwyllys CK_RV ck_rv = CKR_OK; 50699ebb4caSwyllys CK_SLOT_ID slot_id; 50799ebb4caSwyllys CK_SESSION_HANDLE hSession; 50899ebb4caSwyllys CK_FLAGS openflags; 50999ebb4caSwyllys 51099ebb4caSwyllys CLEAR_ERROR(handle, kmf_rv); 51199ebb4caSwyllys if (kmf_rv != KMF_OK) 51299ebb4caSwyllys return (kmf_rv); 51399ebb4caSwyllys 51499ebb4caSwyllys if (label == NULL) { 51599ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 51699ebb4caSwyllys } 51799ebb4caSwyllys 5189b37d296Swyllys kmf_rv = init_pk11(); 5199b37d296Swyllys if (kmf_rv != KMF_OK) { 5209b37d296Swyllys return (kmf_rv); 52199ebb4caSwyllys } 52299ebb4caSwyllys 52399ebb4caSwyllys /* Only one token can be active per thread */ 52499ebb4caSwyllys if (handle->pk11handle != NULL) { 52599ebb4caSwyllys return (KMF_ERR_TOKEN_SELECTED); 52699ebb4caSwyllys } 52799ebb4caSwyllys 52899ebb4caSwyllys /* Find the token with matching label */ 52930a5e8faSwyllys kmf_rv = kmf_pk11_token_lookup(handle, label, &slot_id); 53099ebb4caSwyllys if (kmf_rv != KMF_OK) { 53199ebb4caSwyllys return (kmf_rv); 53299ebb4caSwyllys } 53399ebb4caSwyllys 53499ebb4caSwyllys openflags = CKF_SERIAL_SESSION; 53599ebb4caSwyllys if (!readonly) 53699ebb4caSwyllys openflags |= CKF_RW_SESSION; 53799ebb4caSwyllys 53899ebb4caSwyllys /* Open a session then log the user into the token */ 53999ebb4caSwyllys ck_rv = C_OpenSession(slot_id, openflags, NULL, NULL, &hSession); 54099ebb4caSwyllys if (ck_rv != CKR_OK) { 54199ebb4caSwyllys handle->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 54299ebb4caSwyllys handle->lasterr.errcode = ck_rv; 54399ebb4caSwyllys return (KMF_ERR_INTERNAL); 54499ebb4caSwyllys } 54599ebb4caSwyllys 54699ebb4caSwyllys handle->pk11handle = hSession; 54799ebb4caSwyllys 54899ebb4caSwyllys return (kmf_rv); 54999ebb4caSwyllys } 55071593db2Swyllys 55171593db2Swyllys CK_SESSION_HANDLE 55230a5e8faSwyllys kmf_get_pk11_handle(KMF_HANDLE_T kmfh) 55371593db2Swyllys { 55471593db2Swyllys return (kmfh->pk11handle); 55571593db2Swyllys } 556*47e946e7SWyllys Ingersoll 557*47e946e7SWyllys Ingersoll KMF_RETURN 558*47e946e7SWyllys Ingersoll kmf_pk11_init_token(KMF_HANDLE_T handle, 559*47e946e7SWyllys Ingersoll char *currlabel, char *newlabel, 560*47e946e7SWyllys Ingersoll CK_UTF8CHAR_PTR sopin, CK_ULONG sopinlen) 561*47e946e7SWyllys Ingersoll { 562*47e946e7SWyllys Ingersoll KMF_RETURN ret = KMF_OK; 563*47e946e7SWyllys Ingersoll CK_RV ckrv; 564*47e946e7SWyllys Ingersoll CK_SLOT_ID slot_id = 0; 565*47e946e7SWyllys Ingersoll 566*47e946e7SWyllys Ingersoll CLEAR_ERROR(handle, ret); 567*47e946e7SWyllys Ingersoll if (ret != KMF_OK) 568*47e946e7SWyllys Ingersoll return (ret); 569*47e946e7SWyllys Ingersoll 570*47e946e7SWyllys Ingersoll /* 571*47e946e7SWyllys Ingersoll * It is best to try and lookup tokens by label. 572*47e946e7SWyllys Ingersoll */ 573*47e946e7SWyllys Ingersoll if (currlabel != NULL) { 574*47e946e7SWyllys Ingersoll ret = kmf_pk11_token_lookup(handle, currlabel, &slot_id); 575*47e946e7SWyllys Ingersoll if (ret != KMF_OK) 576*47e946e7SWyllys Ingersoll return (ret); 577*47e946e7SWyllys Ingersoll } else { 578*47e946e7SWyllys Ingersoll /* We can't determine which slot to initialize */ 579*47e946e7SWyllys Ingersoll return (KMF_ERR_TOKEN_NOT_PRESENT); 580*47e946e7SWyllys Ingersoll } 581*47e946e7SWyllys Ingersoll 582*47e946e7SWyllys Ingersoll /* Initialize and set the new label (if given) */ 583*47e946e7SWyllys Ingersoll ckrv = C_InitToken(slot_id, sopin, sopinlen, 584*47e946e7SWyllys Ingersoll (CK_UTF8CHAR_PTR)(newlabel ? newlabel : currlabel)); 585*47e946e7SWyllys Ingersoll 586*47e946e7SWyllys Ingersoll if (ckrv != CKR_OK) { 587*47e946e7SWyllys Ingersoll if (ckrv == CKR_PIN_INCORRECT) 588*47e946e7SWyllys Ingersoll return (KMF_ERR_AUTH_FAILED); 589*47e946e7SWyllys Ingersoll else 590*47e946e7SWyllys Ingersoll return (KMF_ERR_INTERNAL); 591*47e946e7SWyllys Ingersoll } 592*47e946e7SWyllys Ingersoll 593*47e946e7SWyllys Ingersoll return (ret); 594*47e946e7SWyllys Ingersoll } 595