17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*7711facfSdinak * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * This file contains the functions that are shared among 317c478bd9Sstevel@tonic-gate * the various services this tool will ultimately provide. 32*7711facfSdinak * The functions in this file return PKCS#11 CK_RV errors. 33*7711facfSdinak * Only one session and one login per token is supported 34*7711facfSdinak * at this time. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <string.h> 407c478bd9Sstevel@tonic-gate #include <ctype.h> 417c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 427c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 437c478bd9Sstevel@tonic-gate #include "common.h" 44*7711facfSdinak #include "biginteger.h" 457c478bd9Sstevel@tonic-gate 46*7711facfSdinak /* True and false for attribute templates. */ 47*7711facfSdinak CK_BBOOL pk_true = B_TRUE; 48*7711facfSdinak CK_BBOOL pk_false = B_FALSE; 49*7711facfSdinak 50*7711facfSdinak /* Local status variables. */ 51*7711facfSdinak static boolean_t initialized = B_FALSE; 52*7711facfSdinak static boolean_t session_opened = B_FALSE; 53*7711facfSdinak static boolean_t session_writable = B_FALSE; 54*7711facfSdinak static boolean_t logged_in = B_FALSE; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 57*7711facfSdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 58*7711facfSdinak * along with setting/resetting state variables. 597c478bd9Sstevel@tonic-gate */ 60*7711facfSdinak CK_RV 61*7711facfSdinak init_pk11(void) 627c478bd9Sstevel@tonic-gate { 63*7711facfSdinak CK_RV rv = CKR_OK; 64*7711facfSdinak 65*7711facfSdinak cryptodebug("inside init_pk11"); 66*7711facfSdinak 67*7711facfSdinak /* If C_Initialize() already called, nothing to do here. */ 68*7711facfSdinak if (initialized == B_TRUE) 69*7711facfSdinak return (CKR_OK); 707c478bd9Sstevel@tonic-gate 71*7711facfSdinak /* Reset state variables because C_Initialize() not yet done. */ 72*7711facfSdinak session_opened = B_FALSE; 73*7711facfSdinak session_writable = B_FALSE; 74*7711facfSdinak logged_in = B_FALSE; 757c478bd9Sstevel@tonic-gate 76*7711facfSdinak /* Initialize PKCS#11 library. */ 77*7711facfSdinak cryptodebug("calling C_Initialize()"); 78*7711facfSdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 79*7711facfSdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 80*7711facfSdinak return (rv); 81*7711facfSdinak } 827c478bd9Sstevel@tonic-gate 83*7711facfSdinak initialized = B_TRUE; 84*7711facfSdinak return (CKR_OK); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 88*7711facfSdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 89*7711facfSdinak * if any, are closed, and thereby any logins are logged out also. 907c478bd9Sstevel@tonic-gate */ 91*7711facfSdinak void 92*7711facfSdinak final_pk11(CK_SESSION_HANDLE sess) 937c478bd9Sstevel@tonic-gate { 94*7711facfSdinak cryptodebug("inside final_pk11"); 957c478bd9Sstevel@tonic-gate 96*7711facfSdinak /* If the library wasn't initialized, nothing to do here. */ 97*7711facfSdinak if (!initialized) 98*7711facfSdinak return; 997c478bd9Sstevel@tonic-gate 100*7711facfSdinak /* Make sure the sesion is closed first. */ 101*7711facfSdinak close_sess(sess); 102*7711facfSdinak 103*7711facfSdinak cryptodebug("calling C_Finalize()"); 104*7711facfSdinak (void) C_Finalize(NULL); 105*7711facfSdinak initialized = B_FALSE; 106*7711facfSdinak } 107*7711facfSdinak 108*7711facfSdinak /* 109*7711facfSdinak * Create a PKCS#11 session on the given slot, and set state information. 110*7711facfSdinak * If session is already open, check that the read-only/read-write state 111*7711facfSdinak * requested matches that of the session. If it doesn't, make it so. 112*7711facfSdinak */ 113*7711facfSdinak CK_RV 114*7711facfSdinak open_sess(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_SESSION_HANDLE_PTR sess) 115*7711facfSdinak { 116*7711facfSdinak CK_RV rv = CKR_OK; 117*7711facfSdinak 118*7711facfSdinak cryptodebug("inside open_sess"); 119*7711facfSdinak 120*7711facfSdinak /* If the session is already open, check the session flags. */ 121*7711facfSdinak if (session_opened) { 122*7711facfSdinak /* 123*7711facfSdinak * If requesting R/W session and it is currently R/O, 124*7711facfSdinak * need to close the session and reopen it R/W. The 125*7711facfSdinak * other cases are considered acceptable: 126*7711facfSdinak * sess_flags current state 127*7711facfSdinak * ---------- ------------- 128*7711facfSdinak * ~CKF_RW_SESSION !session_writable 129*7711facfSdinak * ~CKF_RW_SESSION session_writable 130*7711facfSdinak * CKF_RW_SESSION session_writable 131*7711facfSdinak */ 132*7711facfSdinak if ((sess_flags & CKF_RW_SESSION) && !session_writable) 133*7711facfSdinak close_sess(*sess); 134*7711facfSdinak else 135*7711facfSdinak return (CKR_OK); 136*7711facfSdinak } 137*7711facfSdinak 138*7711facfSdinak /* Make sure the PKCS#11 is already initialized. */ 139*7711facfSdinak if (!initialized) 140*7711facfSdinak if ((rv = init_pk11()) != CKR_OK) 141*7711facfSdinak return (rv); 142*7711facfSdinak 143*7711facfSdinak /* Create a session for subsequent operations. */ 144*7711facfSdinak cryptodebug("calling C_OpenSession()"); 145*7711facfSdinak if ((rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION|sess_flags, 146*7711facfSdinak NULL, NULL, sess)) != CKR_OK) 147*7711facfSdinak return (rv); 148*7711facfSdinak session_opened = B_TRUE; 149*7711facfSdinak session_writable = (sess_flags & CKF_RW_SESSION) ? B_TRUE : B_FALSE; 150*7711facfSdinak return (CKR_OK); 151*7711facfSdinak } 152*7711facfSdinak 153*7711facfSdinak /* 154*7711facfSdinak * Close PKCS#11 session and reset state variables. Any logins are 155*7711facfSdinak * logged out. 156*7711facfSdinak */ 157*7711facfSdinak void 158*7711facfSdinak close_sess(CK_SESSION_HANDLE sess) 159*7711facfSdinak { 160*7711facfSdinak cryptodebug("inside close_sess"); 161*7711facfSdinak 162*7711facfSdinak if (sess == NULL) { 163*7711facfSdinak cryptodebug("session handle is null"); 164*7711facfSdinak return; 165*7711facfSdinak } 166*7711facfSdinak 167*7711facfSdinak /* If session is already closed, nothing to do here. */ 168*7711facfSdinak session_writable = B_FALSE; 169*7711facfSdinak if (!session_opened) 170*7711facfSdinak return; 171*7711facfSdinak 172*7711facfSdinak /* Make sure user is logged out of token. */ 173*7711facfSdinak logout_token(sess); 174*7711facfSdinak 175*7711facfSdinak cryptodebug("calling C_CloseSession()"); 176*7711facfSdinak (void) C_CloseSession(sess); 177*7711facfSdinak session_opened = B_FALSE; 178*7711facfSdinak } 179*7711facfSdinak 180*7711facfSdinak /* 181*7711facfSdinak * Log user into token in given slot. If this first login ever for this 182*7711facfSdinak * token, the initial PIN is "changeme", C_Login() will succeed, but all 183*7711facfSdinak * PKCS#11 calls following the C_Login() will fail with CKR_PIN_EXPIRED. 184*7711facfSdinak */ 185*7711facfSdinak CK_RV 186*7711facfSdinak login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pinlen, 187*7711facfSdinak CK_SESSION_HANDLE_PTR sess) 188*7711facfSdinak { 189*7711facfSdinak CK_RV rv = CKR_OK; 190*7711facfSdinak 191*7711facfSdinak cryptodebug("inside login_token"); 192*7711facfSdinak 193*7711facfSdinak /* If already logged in, nothing to do here. */ 194*7711facfSdinak if (logged_in) 195*7711facfSdinak return (CKR_OK); 196*7711facfSdinak 197*7711facfSdinak /* Make sure we have a session first, assume R/O is enough. */ 198*7711facfSdinak if (!session_opened) 199*7711facfSdinak if ((rv = open_sess(slot_id, CKF_SERIAL_SESSION, sess)) != 200*7711facfSdinak CKR_OK) 201*7711facfSdinak return (rv); 202*7711facfSdinak 203*7711facfSdinak /* Log the user into the token. */ 204*7711facfSdinak cryptodebug("calling C_Login()"); 205*7711facfSdinak if ((rv = C_Login(*sess, CKU_USER, pin, pinlen)) != CKR_OK) { 206*7711facfSdinak cryptodebug("C_Login returns %s", pkcs11_strerror(rv)); 207*7711facfSdinak return (rv); 208*7711facfSdinak } 209*7711facfSdinak 210*7711facfSdinak logged_in = B_TRUE; 211*7711facfSdinak return (CKR_OK); 212*7711facfSdinak } 213*7711facfSdinak 214*7711facfSdinak /* 215*7711facfSdinak * Log user out of token and reset status variable. 216*7711facfSdinak */ 217*7711facfSdinak void 218*7711facfSdinak logout_token(CK_SESSION_HANDLE sess) 219*7711facfSdinak { 220*7711facfSdinak cryptodebug("inside logout_token"); 221*7711facfSdinak 222*7711facfSdinak if (sess == NULL) { 223*7711facfSdinak cryptodebug("session handle is null"); 224*7711facfSdinak return; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 227*7711facfSdinak /* If already logged out, nothing to do here. */ 228*7711facfSdinak if (!logged_in) 229*7711facfSdinak return; 230*7711facfSdinak 231*7711facfSdinak cryptodebug("calling C_Logout()"); 232*7711facfSdinak (void) C_Logout(sess); 233*7711facfSdinak logged_in = B_FALSE; 234*7711facfSdinak } 235*7711facfSdinak 236*7711facfSdinak /* 237*7711facfSdinak * Shortcut function to get from an uninitialized state to user logged in. 238*7711facfSdinak * If the library is already initialized, the session is already opened, 239*7711facfSdinak * or the user is already logged in, those steps are skipped and the next 240*7711facfSdinak * step is checked. 241*7711facfSdinak */ 242*7711facfSdinak CK_RV 243*7711facfSdinak quick_start(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_UTF8CHAR_PTR pin, 244*7711facfSdinak CK_ULONG pinlen, CK_SESSION_HANDLE_PTR sess) 245*7711facfSdinak { 246*7711facfSdinak CK_RV rv = CKR_OK; 247*7711facfSdinak 248*7711facfSdinak cryptodebug("inside quick_start"); 249*7711facfSdinak 250*7711facfSdinak /* Call open_sess() explicitly if R/W session is needed. */ 251*7711facfSdinak if (sess_flags & CKF_RW_SESSION) 252*7711facfSdinak if ((rv = open_sess(slot_id, sess_flags, sess)) != CKR_OK) 253*7711facfSdinak return (rv); 254*7711facfSdinak 255*7711facfSdinak if ((rv = login_token(slot_id, pin, pinlen, sess)) != CKR_OK) 256*7711facfSdinak return (rv); 257*7711facfSdinak 258*7711facfSdinak return (CKR_OK); 259*7711facfSdinak } 260*7711facfSdinak 261*7711facfSdinak /* 262*7711facfSdinak * Shortcut function to go from any state to uninitialized PKCS#11 library. 263*7711facfSdinak */ 264*7711facfSdinak void 265*7711facfSdinak quick_finish(CK_SESSION_HANDLE sess) 266*7711facfSdinak { 267*7711facfSdinak cryptodebug("inside quick_finish"); 268*7711facfSdinak 269*7711facfSdinak /* All the needed calls are done implicitly. */ 270*7711facfSdinak final_pk11(sess); 271*7711facfSdinak } 272*7711facfSdinak 273*7711facfSdinak /* 274*7711facfSdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 275*7711facfSdinak * If two prompts are given, the PIN is confirmed with second prompt. 276*7711facfSdinak * Note that getphassphrase() may return data in static memory area. 277*7711facfSdinak */ 278*7711facfSdinak CK_RV 279*7711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 280*7711facfSdinak { 281*7711facfSdinak char *save_phrase, *phrase1, *phrase2; 282*7711facfSdinak 283*7711facfSdinak cryptodebug("inside get_pin"); 284*7711facfSdinak 285*7711facfSdinak /* Prompt user for a PIN. */ 286*7711facfSdinak if (prompt1 == NULL) { 287*7711facfSdinak cryptodebug("no passphrase prompt given"); 288*7711facfSdinak return (CKR_ARGUMENTS_BAD); 289*7711facfSdinak } 290*7711facfSdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 291*7711facfSdinak cryptodebug("getpassphrase() failed"); 292*7711facfSdinak return (CKR_FUNCTION_FAILED); 293*7711facfSdinak } 294*7711facfSdinak 295*7711facfSdinak /* Duplicate 1st PIN in separate chunk of memory. */ 296*7711facfSdinak if ((save_phrase = strdup(phrase1)) == NULL) 297*7711facfSdinak return (CKR_HOST_MEMORY); 298*7711facfSdinak 299*7711facfSdinak /* If second prompt given, PIN confirmation is requested. */ 300*7711facfSdinak if (prompt2 != NULL) { 301*7711facfSdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 302*7711facfSdinak cryptodebug("getpassphrase() confirmation failed"); 303*7711facfSdinak free(save_phrase); 304*7711facfSdinak return (CKR_FUNCTION_FAILED); 305*7711facfSdinak } 306*7711facfSdinak if (strcmp(save_phrase, phrase2) != 0) { 307*7711facfSdinak cryptodebug("passphrases do not match"); 308*7711facfSdinak free(save_phrase); 309*7711facfSdinak return (CKR_PIN_INCORRECT); 310*7711facfSdinak } 311*7711facfSdinak } 312*7711facfSdinak 313*7711facfSdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 314*7711facfSdinak *pinlen = strlen(save_phrase); 315*7711facfSdinak return (CKR_OK); 316*7711facfSdinak } 317*7711facfSdinak 318*7711facfSdinak /* 319*7711facfSdinak * Gets yes/no response from user. If either no prompt is supplied, a 320*7711facfSdinak * default prompt is used. If not message for invalid input is supplied, 321*7711facfSdinak * a default will not be provided. If the user provides no response, 322*7711facfSdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 323*7711facfSdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 324*7711facfSdinak */ 325*7711facfSdinak boolean_t 326*7711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt) 327*7711facfSdinak { 328*7711facfSdinak char *response, buf[1024]; 329*7711facfSdinak char *yes = gettext("yes"); 330*7711facfSdinak char *no = gettext("no"); 331*7711facfSdinak 332*7711facfSdinak cryptodebug("inside yesno"); 333*7711facfSdinak 334*7711facfSdinak if (prompt == NULL) 335*7711facfSdinak prompt = gettext("Enter (y)es or (n)o? "); 336*7711facfSdinak 337*7711facfSdinak for (;;) { 338*7711facfSdinak /* Prompt user. */ 339*7711facfSdinak (void) printf("%s", prompt); 340*7711facfSdinak (void) fflush(stdout); 341*7711facfSdinak 342*7711facfSdinak /* Get the response. */ 343*7711facfSdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 344*7711facfSdinak break; /* go to default response */ 345*7711facfSdinak 346*7711facfSdinak /* Skip any leading white space. */ 347*7711facfSdinak while (isspace(*response)) 348*7711facfSdinak response++; 349*7711facfSdinak if (*response == '\0') 350*7711facfSdinak break; /* go to default response */ 351*7711facfSdinak 352*7711facfSdinak /* Is it valid input? Return appropriately. */ 353*7711facfSdinak if (strncasecmp(response, yes, 1) == 0) 354*7711facfSdinak return (B_TRUE); 355*7711facfSdinak if (strncasecmp(response, no, 1) == 0) 356*7711facfSdinak return (B_FALSE); 357*7711facfSdinak 358*7711facfSdinak /* Indicate invalid input, and try again. */ 359*7711facfSdinak if (invalid != NULL) 360*7711facfSdinak (void) printf("%s", invalid); 361*7711facfSdinak } 362*7711facfSdinak return (dflt); 363*7711facfSdinak } 364*7711facfSdinak 365*7711facfSdinak /* 366*7711facfSdinak * Gets the list of slots which have tokens in them. Keeps adjusting 367*7711facfSdinak * the size of the slot list buffer until the call is successful or an 368*7711facfSdinak * irrecoverable error occurs. 369*7711facfSdinak */ 370*7711facfSdinak CK_RV 371*7711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 372*7711facfSdinak { 373*7711facfSdinak CK_ULONG tmp_count = 0; 374*7711facfSdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 375*7711facfSdinak int rv = CKR_OK; 376*7711facfSdinak 377*7711facfSdinak cryptodebug("inside get_token_slots"); 378*7711facfSdinak 379*7711facfSdinak if (!initialized) 380*7711facfSdinak if ((rv = init_pk11()) != CKR_OK) 381*7711facfSdinak return (rv); 382*7711facfSdinak 383*7711facfSdinak /* 384*7711facfSdinak * Get the slot count first because we don't know how many 385*7711facfSdinak * slots there are and how many of those slots even have tokens. 386*7711facfSdinak * Don't specify an arbitrary buffer size for the slot list; 387*7711facfSdinak * it may be too small (see section 11.5 of PKCS#11 spec). 388*7711facfSdinak * Also select only those slots that have tokens in them, 389*7711facfSdinak * because this tool has no need to know about empty slots. 390*7711facfSdinak */ 391*7711facfSdinak cryptodebug("calling C_GetSlotList() for slot count"); 392*7711facfSdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 393*7711facfSdinak return (rv); 394*7711facfSdinak 395*7711facfSdinak if (tmp_count == 0) { 396*7711facfSdinak cryptodebug("no slots with tokens found"); 397*7711facfSdinak *slot_list = NULL_PTR; 398*7711facfSdinak *slot_count = 0; 399*7711facfSdinak return (CKR_OK); 400*7711facfSdinak } 401*7711facfSdinak 402*7711facfSdinak /* Allocate initial space for the slot list. */ 403*7711facfSdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 404*7711facfSdinak sizeof (CK_SLOT_ID))) == NULL) 405*7711facfSdinak return (CKR_HOST_MEMORY); 406*7711facfSdinak 407*7711facfSdinak /* Then get the slot list itself. */ 408*7711facfSdinak for (;;) { 409*7711facfSdinak cryptodebug("calling C_GetSlotList()"); 410*7711facfSdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 411*7711facfSdinak *slot_list = tmp_list; 412*7711facfSdinak *slot_count = tmp_count; 413*7711facfSdinak break; 414*7711facfSdinak } 415*7711facfSdinak 416*7711facfSdinak if (rv != CKR_BUFFER_TOO_SMALL) { 417*7711facfSdinak free(tmp_list); 418*7711facfSdinak break; 419*7711facfSdinak } 420*7711facfSdinak 421*7711facfSdinak /* If the number of slots grew, try again. */ 422*7711facfSdinak cryptodebug("number of tokens present increased"); 423*7711facfSdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 424*7711facfSdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 425*7711facfSdinak free(tmp_list); 426*7711facfSdinak rv = CKR_HOST_MEMORY; 427*7711facfSdinak break; 428*7711facfSdinak } 429*7711facfSdinak tmp_list = tmp2_list; 430*7711facfSdinak } 431*7711facfSdinak 432*7711facfSdinak return (rv); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * memcmp_pad_max() is a specialized version of memcmp() which 4377c478bd9Sstevel@tonic-gate * compares two pieces of data up to a maximum length. If the 4387c478bd9Sstevel@tonic-gate * the two data match up the maximum length, they are considered 4397c478bd9Sstevel@tonic-gate * matching. Trailing blanks do not cause the match to fail if 4407c478bd9Sstevel@tonic-gate * one of the data is shorted. 4417c478bd9Sstevel@tonic-gate * 4427c478bd9Sstevel@tonic-gate * Examples of matches: 4437c478bd9Sstevel@tonic-gate * "one" | 4447c478bd9Sstevel@tonic-gate * "one " | 4457c478bd9Sstevel@tonic-gate * ^maximum length 4467c478bd9Sstevel@tonic-gate * 4477c478bd9Sstevel@tonic-gate * "Number One | X" (X is beyond maximum length) 4487c478bd9Sstevel@tonic-gate * "Number One " | 4497c478bd9Sstevel@tonic-gate * ^maximum length 4507c478bd9Sstevel@tonic-gate * 4517c478bd9Sstevel@tonic-gate * Examples of mismatches: 4527c478bd9Sstevel@tonic-gate * " one" 4537c478bd9Sstevel@tonic-gate * "one" 4547c478bd9Sstevel@tonic-gate * 4557c478bd9Sstevel@tonic-gate * "Number One X|" 4567c478bd9Sstevel@tonic-gate * "Number One |" 4577c478bd9Sstevel@tonic-gate * ^maximum length 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static int 4607c478bd9Sstevel@tonic-gate memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate uint_t len, extra_len; 4637c478bd9Sstevel@tonic-gate char *marker; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* No point in comparing anything beyond max_sz */ 4667c478bd9Sstevel@tonic-gate if (d1_len > max_sz) 4677c478bd9Sstevel@tonic-gate d1_len = max_sz; 4687c478bd9Sstevel@tonic-gate if (d2_len > max_sz) 4697c478bd9Sstevel@tonic-gate d2_len = max_sz; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* Find shorter of the two data. */ 4727c478bd9Sstevel@tonic-gate if (d1_len <= d2_len) { 4737c478bd9Sstevel@tonic-gate len = d1_len; 4747c478bd9Sstevel@tonic-gate extra_len = d2_len; 4757c478bd9Sstevel@tonic-gate marker = d2; 4767c478bd9Sstevel@tonic-gate } else { /* d1_len > d2_len */ 4777c478bd9Sstevel@tonic-gate len = d2_len; 4787c478bd9Sstevel@tonic-gate extra_len = d1_len; 4797c478bd9Sstevel@tonic-gate marker = d1; 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* Have a match in the shortest length of data? */ 4837c478bd9Sstevel@tonic-gate if (memcmp(d1, d2, len) != 0) 4847c478bd9Sstevel@tonic-gate /* CONSTCOND */ 4857c478bd9Sstevel@tonic-gate return (!0); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* If the rest of longer data is nulls or blanks, call it a match. */ 4887c478bd9Sstevel@tonic-gate while (len < extra_len) 4897c478bd9Sstevel@tonic-gate if (!isspace(marker[len++])) 4907c478bd9Sstevel@tonic-gate /* CONSTCOND */ 4917c478bd9Sstevel@tonic-gate return (!0); 4927c478bd9Sstevel@tonic-gate return (0); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 496*7711facfSdinak * Locate a token slot whose token matches the label, manufacturer ID, and 497*7711facfSdinak * serial number given. Token label must be specified, manufacturer ID and 498*7711facfSdinak * serial number are optional. When the token is located, the PIN state 499*7711facfSdinak * is also returned to determine if it still has the default PIN. 5007c478bd9Sstevel@tonic-gate */ 501*7711facfSdinak CK_RV 5027c478bd9Sstevel@tonic-gate find_token_slot(char *token_name, char *manuf_id, char *serial_no, 5037c478bd9Sstevel@tonic-gate CK_SLOT_ID *slot_id, CK_FLAGS *pin_state) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate CK_SLOT_ID_PTR slot_list; 5067c478bd9Sstevel@tonic-gate CK_TOKEN_INFO token_info; 5077c478bd9Sstevel@tonic-gate CK_ULONG slot_count = 0; 508*7711facfSdinak int rv = CKR_OK; 5097c478bd9Sstevel@tonic-gate int i; 5107c478bd9Sstevel@tonic-gate uint_t len, max_sz; 5117c478bd9Sstevel@tonic-gate boolean_t tok_match = B_FALSE, 5127c478bd9Sstevel@tonic-gate man_match = B_FALSE, 5137c478bd9Sstevel@tonic-gate ser_match = B_FALSE; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate cryptodebug("inside find_token_slot"); 5167c478bd9Sstevel@tonic-gate 517*7711facfSdinak if (token_name == NULL) 518*7711facfSdinak return (CKR_ARGUMENTS_BAD); 5197c478bd9Sstevel@tonic-gate 520*7711facfSdinak /* Get a list of all slots with tokens present. */ 521*7711facfSdinak if ((rv = get_token_slots(&slot_list, &slot_count)) != CKR_OK) 522*7711facfSdinak return (rv); 5237c478bd9Sstevel@tonic-gate 524*7711facfSdinak /* If there are no such slots, the desired token won't be found. */ 525*7711facfSdinak if (slot_count == 0) 526*7711facfSdinak return (CKR_TOKEN_NOT_PRESENT); 5277c478bd9Sstevel@tonic-gate 528*7711facfSdinak /* Search the slot list for the token. */ 5297c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 530*7711facfSdinak cryptodebug("calling C_GetTokenInfo()"); 531*7711facfSdinak if ((rv = C_GetTokenInfo(slot_list[i], &token_info)) != 532*7711facfSdinak CKR_OK) { 533*7711facfSdinak cryptodebug("token in slot %d returns %s", i, 534*7711facfSdinak pkcs11_strerror(rv)); 5357c478bd9Sstevel@tonic-gate continue; 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate 538*7711facfSdinak /* See if the token label matches. */ 5397c478bd9Sstevel@tonic-gate len = strlen(token_name); 5407c478bd9Sstevel@tonic-gate max_sz = sizeof (token_info.label); 5417c478bd9Sstevel@tonic-gate if (memcmp_pad_max(&(token_info.label), max_sz, token_name, len, 5427c478bd9Sstevel@tonic-gate max_sz) == 0) 5437c478bd9Sstevel@tonic-gate tok_match = B_TRUE; 5447c478bd9Sstevel@tonic-gate 545*7711facfSdinak /* 546*7711facfSdinak * If manufacturer id was given, see if it actually matches. 547*7711facfSdinak * If no manufacturer id was given, assume match is true. 548*7711facfSdinak */ 5497c478bd9Sstevel@tonic-gate if (manuf_id) { 5507c478bd9Sstevel@tonic-gate len = strlen(manuf_id); 5517c478bd9Sstevel@tonic-gate max_sz = sizeof ((char *)(token_info.manufacturerID)); 5527c478bd9Sstevel@tonic-gate if (memcmp_pad_max(&(token_info.manufacturerID), max_sz, 5537c478bd9Sstevel@tonic-gate manuf_id, len, max_sz) == 0) 5547c478bd9Sstevel@tonic-gate man_match = B_TRUE; 555*7711facfSdinak } else 556*7711facfSdinak man_match = B_TRUE; 5577c478bd9Sstevel@tonic-gate 558*7711facfSdinak /* 559*7711facfSdinak * If serial number was given, see if it actually matches. 560*7711facfSdinak * If no serial number was given, assume match is true. 561*7711facfSdinak */ 5627c478bd9Sstevel@tonic-gate if (serial_no) { 5637c478bd9Sstevel@tonic-gate len = strlen(serial_no); 5647c478bd9Sstevel@tonic-gate max_sz = sizeof ((char *)(token_info.serialNumber)); 5657c478bd9Sstevel@tonic-gate if (memcmp_pad_max(&(token_info.serialNumber), max_sz, 5667c478bd9Sstevel@tonic-gate serial_no, len, max_sz) == 0) 5677c478bd9Sstevel@tonic-gate ser_match = B_TRUE; 568*7711facfSdinak } else 569*7711facfSdinak ser_match = B_TRUE; 570*7711facfSdinak 571*7711facfSdinak cryptodebug("slot %d:", i); 572*7711facfSdinak cryptodebug("\tlabel = \"%.32s\"%s", token_info.label, 573*7711facfSdinak tok_match ? " match" : ""); 574*7711facfSdinak cryptodebug("\tmanuf = \"%.32s\"%s", token_info.manufacturerID, 575*7711facfSdinak man_match ? " match" : ""); 576*7711facfSdinak cryptodebug("\tserno = \"%.16s\"%s", token_info.serialNumber, 577*7711facfSdinak ser_match ? " match" : ""); 578*7711facfSdinak cryptodebug("\tmodel = \"%.16s\"", token_info.model); 5797c478bd9Sstevel@tonic-gate 580*7711facfSdinak cryptodebug("\tCKF_USER_PIN_INITIALIZED = %s", 581*7711facfSdinak (token_info.flags & CKF_USER_PIN_INITIALIZED) ? 582*7711facfSdinak "true" : "false"); 583*7711facfSdinak cryptodebug("\tCKF_USER_PIN_TO_BE_CHANGED = %s", 584*7711facfSdinak (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED) ? 585*7711facfSdinak "true" : "false"); 586*7711facfSdinak 587*7711facfSdinak if (tok_match && man_match && ser_match) 588*7711facfSdinak break; /* found it! */ 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 591*7711facfSdinak /* Scanned the whole list without finding the token. */ 5927c478bd9Sstevel@tonic-gate if (i == slot_count) { 593*7711facfSdinak cryptodebug("token not found"); 5947c478bd9Sstevel@tonic-gate free(slot_list); 595*7711facfSdinak return (CKR_TOKEN_NOT_PRESENT); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 598*7711facfSdinak /* Return slot id where token was found and its PIN state. */ 599*7711facfSdinak cryptodebug("token found at slot %d", i); 6007c478bd9Sstevel@tonic-gate *slot_id = slot_list[i]; 6017c478bd9Sstevel@tonic-gate *pin_state = (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED); 6027c478bd9Sstevel@tonic-gate free(slot_list); 603*7711facfSdinak return (CKR_OK); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* 607*7711facfSdinak * Constructs a fully qualified token name from its label, manufacturer ID 608*7711facfSdinak * (if any), and its serial number (if any). Note that the given buf must 609*7711facfSdinak * be big enough. Do NOT i18n/l10n. 610*7711facfSdinak * 611*7711facfSdinak * FULL_NAME_LEN is defined in common.h to be 91 because a fully qualified 612*7711facfSdinak * token name adds up this way: 613*7711facfSdinak * =32(label) + 32(manuf) + 16(serial) + 4("", ) + 4("", ) + 3("" and nul) 6147c478bd9Sstevel@tonic-gate */ 615*7711facfSdinak void 616*7711facfSdinak full_token_name(char *token_name, char *manuf_id, char *serial_no, char *buf) 6177c478bd9Sstevel@tonic-gate { 618*7711facfSdinak char *marker = buf; 619*7711facfSdinak int n_written = 0; 620*7711facfSdinak int space_left = FULL_NAME_LEN; 6217c478bd9Sstevel@tonic-gate 622*7711facfSdinak if (!token_name) 623*7711facfSdinak return; 624*7711facfSdinak 625*7711facfSdinak n_written = sprintf(buf, "\"%.32s\"", token_name); 626*7711facfSdinak marker += n_written; 627*7711facfSdinak space_left -= n_written; 628*7711facfSdinak 629*7711facfSdinak n_written = sprintf(marker, ", \"%.32s\"", manuf_id ? manuf_id : ""); 630*7711facfSdinak marker += n_written; 631*7711facfSdinak space_left -= n_written; 6327c478bd9Sstevel@tonic-gate 633*7711facfSdinak n_written = sprintf(marker, ", \"%.16s\"", serial_no ? serial_no : ""); 634*7711facfSdinak marker += n_written; 635*7711facfSdinak space_left -= n_written; 636*7711facfSdinak 637*7711facfSdinak /* space_left should always be >= 1 */ 638*7711facfSdinak } 639*7711facfSdinak 640*7711facfSdinak /* 641*7711facfSdinak * Find how many token objects with the given label. 642*7711facfSdinak */ 643*7711facfSdinak CK_RV 644*7711facfSdinak find_obj_count(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label, 645*7711facfSdinak CK_ULONG *count) 646*7711facfSdinak { 647*7711facfSdinak CK_RV rv = CKR_OK; 648*7711facfSdinak CK_ATTRIBUTE attrs[4] = { 649*7711facfSdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 650*7711facfSdinak { 0, NULL, 0 }, 651*7711facfSdinak { 0, NULL, 0 }, 652*7711facfSdinak { 0, NULL, 0 } 653*7711facfSdinak }; 654*7711facfSdinak CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); 655*7711facfSdinak CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */ 656*7711facfSdinak CK_OBJECT_CLASS obj_class; 657*7711facfSdinak CK_OBJECT_HANDLE tmp_obj; 658*7711facfSdinak CK_ULONG obj_count = 0; 659*7711facfSdinak 660*7711facfSdinak cryptodebug("inside find_obj_count"); 661*7711facfSdinak 662*7711facfSdinak if (!session_opened || sess == NULL) { 663*7711facfSdinak cryptodebug("session handle is null"); 664*7711facfSdinak return (CKR_SESSION_HANDLE_INVALID); 665*7711facfSdinak } 666*7711facfSdinak 667*7711facfSdinak if (label) { 668*7711facfSdinak cryptodebug("object label was specified"); 669*7711facfSdinak attrs[cur_attr].type = CKA_LABEL; 670*7711facfSdinak attrs[cur_attr].pValue = label; 671*7711facfSdinak attrs[cur_attr].ulValueLen = strlen((char *)label); 672*7711facfSdinak cur_attr++; 673*7711facfSdinak } 674*7711facfSdinak 675*7711facfSdinak if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) { 676*7711facfSdinak cryptodebug("only searching for private objects"); 677*7711facfSdinak attrs[cur_attr].type = CKA_PRIVATE; 678*7711facfSdinak attrs[cur_attr].pValue = &pk_true; 679*7711facfSdinak attrs[cur_attr].ulValueLen = sizeof (pk_true); 680*7711facfSdinak cur_attr++; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate /* 684*7711facfSdinak * If "certs and all keys" is not specified, but at least either 685*7711facfSdinak * "certs" or some "keys" is specified, then go into this block. 686*7711facfSdinak * If all certs and keys were specified, there's no point in 687*7711facfSdinak * putting that fact in the attribute template -- leave that open, 688*7711facfSdinak * and all certs and keys will be matched automatically. 689*7711facfSdinak * In other words, only if at least one of 0x10,0x20,0x40,0x80 690*7711facfSdinak * bits is off, go into this code block. 691*7711facfSdinak * 692*7711facfSdinak * NOTE: For now, only one of cert or key types is allowed. 693*7711facfSdinak * This needs to change in the future. 6947c478bd9Sstevel@tonic-gate */ 695*7711facfSdinak if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) && 696*7711facfSdinak ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) { 697*7711facfSdinak if (obj_type & PK_CERT_OBJ) { 698*7711facfSdinak cryptodebug("only searching for certificates"); 699*7711facfSdinak obj_class = CKO_CERTIFICATE; 700*7711facfSdinak } else if (obj_type & PK_PRIKEY_OBJ) { 701*7711facfSdinak cryptodebug("only searching for private keys"); 702*7711facfSdinak obj_class = CKO_PRIVATE_KEY; 703*7711facfSdinak } else if (obj_type & PK_PUBKEY_OBJ) { 704*7711facfSdinak cryptodebug("only searching for public keys"); 705*7711facfSdinak obj_class = CKO_PUBLIC_KEY; 706*7711facfSdinak } else if (obj_type & PK_SECKEY_OBJ) { 707*7711facfSdinak cryptodebug("only searching for secret keys"); 708*7711facfSdinak obj_class = CKO_SECRET_KEY; 709*7711facfSdinak } 710*7711facfSdinak 711*7711facfSdinak attrs[cur_attr].type = CKA_CLASS; 712*7711facfSdinak attrs[cur_attr].pValue = &obj_class; 713*7711facfSdinak attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS); 714*7711facfSdinak cur_attr++; 715*7711facfSdinak } 716*7711facfSdinak 717*7711facfSdinak /* 718*7711facfSdinak * This can't happen now. When finding objects is enhanced in the 719*7711facfSdinak * future. this could lead to buffer overruns. 720*7711facfSdinak */ 721*7711facfSdinak if (cur_attr > num_attrs) 722*7711facfSdinak cryptodebug("internal error: attr template overrun"); 723*7711facfSdinak 724*7711facfSdinak cryptodebug("calling C_FindObjectsInit"); 725*7711facfSdinak if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) 726*7711facfSdinak return (rv); 727*7711facfSdinak 728*7711facfSdinak /* Look for the object, checking if there are more than one. */ 729*7711facfSdinak cryptodebug("calling C_FindObjects"); 730*7711facfSdinak for (*count = 0; /* empty */; (*count)++) { 731*7711facfSdinak if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) != 732*7711facfSdinak CKR_OK) 733*7711facfSdinak break; 734*7711facfSdinak 735*7711facfSdinak /* No more found. */ 736*7711facfSdinak if (obj_count == 0) 737*7711facfSdinak break; 738*7711facfSdinak } 739*7711facfSdinak 740*7711facfSdinak cryptodebug("%d matching objects found", *count); 741*7711facfSdinak 742*7711facfSdinak cryptodebug("calling C_FindObjectsFinal"); 743*7711facfSdinak (void) C_FindObjectsFinal(sess); 744*7711facfSdinak return (rv); 745*7711facfSdinak } 746*7711facfSdinak 747*7711facfSdinak /* 748*7711facfSdinak * Find the token object with the given label. 749*7711facfSdinak */ 750*7711facfSdinak CK_RV 751*7711facfSdinak find_objs(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label, 752*7711facfSdinak CK_OBJECT_HANDLE_PTR *obj, CK_ULONG *count) 753*7711facfSdinak { 754*7711facfSdinak CK_RV rv = CKR_OK; 755*7711facfSdinak CK_ATTRIBUTE attrs[4] = { 756*7711facfSdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 757*7711facfSdinak { 0, NULL, 0 }, 758*7711facfSdinak { 0, NULL, 0 }, 759*7711facfSdinak { 0, NULL, 0 } 760*7711facfSdinak }; 761*7711facfSdinak CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); 762*7711facfSdinak CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */ 763*7711facfSdinak CK_OBJECT_CLASS obj_class; 764*7711facfSdinak CK_OBJECT_HANDLE tmp_obj; 765*7711facfSdinak CK_ULONG obj_count = 0; 766*7711facfSdinak int i; 767*7711facfSdinak 768*7711facfSdinak cryptodebug("inside find_obj"); 769*7711facfSdinak 770*7711facfSdinak if ((rv = find_obj_count(sess, obj_type, label, count)) != CKR_OK) 771*7711facfSdinak return (rv); 772*7711facfSdinak 773*7711facfSdinak if (*count == 0) 774*7711facfSdinak return (CKR_OK); 775*7711facfSdinak 776*7711facfSdinak if ((*obj = (CK_OBJECT_HANDLE_PTR) malloc((*count) * 777*7711facfSdinak sizeof (CK_OBJECT_HANDLE))) == NULL) { 778*7711facfSdinak cryptodebug("no memory for found object"); 779*7711facfSdinak return (CKR_HOST_MEMORY); 780*7711facfSdinak } 781*7711facfSdinak 782*7711facfSdinak if (label) { 783*7711facfSdinak cryptodebug("object label was specified"); 784*7711facfSdinak attrs[cur_attr].type = CKA_LABEL; 785*7711facfSdinak attrs[cur_attr].pValue = label; 786*7711facfSdinak attrs[cur_attr].ulValueLen = strlen((char *)label); 787*7711facfSdinak cur_attr++; 788*7711facfSdinak } 789*7711facfSdinak 790*7711facfSdinak if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) { 791*7711facfSdinak cryptodebug("only searching for private objects"); 792*7711facfSdinak attrs[cur_attr].type = CKA_PRIVATE; 793*7711facfSdinak attrs[cur_attr].pValue = &pk_true; 794*7711facfSdinak attrs[cur_attr].ulValueLen = sizeof (pk_true); 795*7711facfSdinak cur_attr++; 796*7711facfSdinak } 797*7711facfSdinak 798*7711facfSdinak /* 799*7711facfSdinak * If "certs and all keys" is not specified, but at least either 800*7711facfSdinak * "certs" or some "keys" is specified, then go into this block. 801*7711facfSdinak * If all certs and keys were specified, there's no point in 802*7711facfSdinak * putting that fact in the attribute template -- leave that open, 803*7711facfSdinak * and all certs and keys will be matched automatically. 804*7711facfSdinak * In other words, only if at least one of 0x10,0x20,0x40,0x80 805*7711facfSdinak * bits is off, go into this code block. 806*7711facfSdinak * 807*7711facfSdinak * NOTE: For now, only one of cert or key types is allowed. 808*7711facfSdinak * This needs to change in the future. 809*7711facfSdinak */ 810*7711facfSdinak if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) && 811*7711facfSdinak ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) { 812*7711facfSdinak if (obj_type & PK_CERT_OBJ) { 813*7711facfSdinak cryptodebug("only searching for certificates"); 814*7711facfSdinak obj_class = CKO_CERTIFICATE; 815*7711facfSdinak } else if (obj_type & PK_PRIKEY_OBJ) { 816*7711facfSdinak cryptodebug("only searching for private keys"); 817*7711facfSdinak obj_class = CKO_PRIVATE_KEY; 818*7711facfSdinak } else if (obj_type & PK_PUBKEY_OBJ) { 819*7711facfSdinak cryptodebug("only searching for public keys"); 820*7711facfSdinak obj_class = CKO_PUBLIC_KEY; 821*7711facfSdinak } else if (obj_type & PK_SECKEY_OBJ) { 822*7711facfSdinak cryptodebug("only searching for secret keys"); 823*7711facfSdinak obj_class = CKO_SECRET_KEY; 824*7711facfSdinak } 825*7711facfSdinak 826*7711facfSdinak attrs[cur_attr].type = CKA_CLASS; 827*7711facfSdinak attrs[cur_attr].pValue = &obj_class; 828*7711facfSdinak attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS); 829*7711facfSdinak cur_attr++; 830*7711facfSdinak } 831*7711facfSdinak 832*7711facfSdinak /* 833*7711facfSdinak * This can't happen now. When finding objects is enhanced in the 834*7711facfSdinak * future. this could lead to buffer overruns. 835*7711facfSdinak */ 836*7711facfSdinak if (cur_attr > num_attrs) 837*7711facfSdinak cryptodebug("internal error: attr template overrun"); 838*7711facfSdinak 839*7711facfSdinak cryptodebug("calling C_FindObjectsInit"); 840*7711facfSdinak if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) { 841*7711facfSdinak free(*obj); 842*7711facfSdinak return (rv); 843*7711facfSdinak } 844*7711facfSdinak 845*7711facfSdinak /* 846*7711facfSdinak * Find all the matching objects. The loop goes 1 more beyond 847*7711facfSdinak * the number of objects found to determine if any new objects 848*7711facfSdinak * were created since the time the object count was done. 849*7711facfSdinak */ 850*7711facfSdinak cryptodebug("calling C_FindObjects"); 851*7711facfSdinak for (i = 0; i < (*count) + 1; i++) { 852*7711facfSdinak if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) != 853*7711facfSdinak CKR_OK) 854*7711facfSdinak break; 855*7711facfSdinak 856*7711facfSdinak /* No more found. */ 857*7711facfSdinak if (obj_count == 0) 858*7711facfSdinak break; 859*7711facfSdinak 860*7711facfSdinak /* 861*7711facfSdinak * Save the object in the list being created, as long as 862*7711facfSdinak * we don't overrun the size of the list. 863*7711facfSdinak */ 864*7711facfSdinak if (i < *count) 865*7711facfSdinak (*obj)[i] = tmp_obj; 866*7711facfSdinak else 867*7711facfSdinak cryptodebug("number of objects changed since last count"); 868*7711facfSdinak } 869*7711facfSdinak 870*7711facfSdinak if (rv != CKR_OK) { 871*7711facfSdinak free(*obj); 872*7711facfSdinak } else { 873*7711facfSdinak /* 874*7711facfSdinak * There are three cases to handle: (1) fewer objects were 875*7711facfSdinak * found than originally counted => change *count to the 876*7711facfSdinak * smaller number; (2) the number of objects found matches 877*7711facfSdinak * the number originally counted => do nothing; (3) more 878*7711facfSdinak * objects found than originally counted => list passed 879*7711facfSdinak * in is too small to contain the extra object(s), flag 880*7711facfSdinak * that in the debug output but don't change number of 881*7711facfSdinak * objects returned. The caller can double-check by 882*7711facfSdinak * calling find_obj_count() after this function to make 883*7711facfSdinak * sure the numbers match, if desired. 884*7711facfSdinak */ 885*7711facfSdinak /* Case 1: Fewer objects. */ 886*7711facfSdinak if (i < *count) { 887*7711facfSdinak cryptodebug("%d objects found, expected %d", i, *count); 888*7711facfSdinak *count = i; 889*7711facfSdinak /* Case 3: More objects. */ 890*7711facfSdinak } else if (i > *count) { 891*7711facfSdinak cryptodebug("at least %d objects found, expected %d", 892*7711facfSdinak i, *count); 893*7711facfSdinak } 894*7711facfSdinak /* 895*7711facfSdinak * Case 2: Same number of objects. 896*7711facfSdinak * 897*7711facfSdinak * else if (i == *count) 898*7711facfSdinak * ; 899*7711facfSdinak */ 900*7711facfSdinak } 901*7711facfSdinak 902*7711facfSdinak cryptodebug("calling C_FindObjectsFinal"); 903*7711facfSdinak (void) C_FindObjectsFinal(sess); 904*7711facfSdinak return (rv); 905*7711facfSdinak } 906*7711facfSdinak 907*7711facfSdinak char * 908*7711facfSdinak class_str(CK_OBJECT_CLASS class) 909*7711facfSdinak { 910*7711facfSdinak switch (class) { 911*7711facfSdinak case CKO_DATA: return (gettext("data")); 912*7711facfSdinak case CKO_CERTIFICATE: return (gettext("certificate")); 913*7711facfSdinak case CKO_PUBLIC_KEY: return (gettext("public key")); 914*7711facfSdinak case CKO_PRIVATE_KEY: return (gettext("private key")); 915*7711facfSdinak case CKO_SECRET_KEY: return (gettext("secret key")); 916*7711facfSdinak case CKO_DOMAIN_PARAMETERS: return (gettext("domain parameter")); 917*7711facfSdinak default: return (gettext("unknown object")); 918*7711facfSdinak } 919*7711facfSdinak } 920*7711facfSdinak 921*7711facfSdinak char * 922*7711facfSdinak keytype_str(CK_KEY_TYPE keytype) 923*7711facfSdinak { 924*7711facfSdinak switch (keytype) { 925*7711facfSdinak case CKK_RSA: return (gettext("RSA")); 926*7711facfSdinak case CKK_DSA: return (gettext("DSA")); 927*7711facfSdinak case CKK_DH: return (gettext("Diffie-Hellman")); 928*7711facfSdinak case CKK_X9_42_DH: return (gettext("X9.42 Diffie-Hellman")); 929*7711facfSdinak case CKK_GENERIC_SECRET: return (gettext("generic")); 930*7711facfSdinak case CKK_RC2: return (gettext("RC2")); 931*7711facfSdinak case CKK_RC4: return (gettext("RC4")); 932*7711facfSdinak case CKK_DES: return (gettext("DES")); 933*7711facfSdinak case CKK_DES2: return (gettext("Double-DES")); 934*7711facfSdinak case CKK_DES3: return (gettext("Triple-DES")); 935*7711facfSdinak case CKK_RC5: return (gettext("RC5")); 936*7711facfSdinak case CKK_AES: return (gettext("AES")); 937*7711facfSdinak default: return (gettext("typeless")); 9387c478bd9Sstevel@tonic-gate } 939*7711facfSdinak } 9407c478bd9Sstevel@tonic-gate 941*7711facfSdinak char * 942*7711facfSdinak attr_str(CK_ATTRIBUTE_TYPE attrtype) 943*7711facfSdinak { 944*7711facfSdinak switch (attrtype) { 945*7711facfSdinak case CKA_PRIVATE: return (gettext("private")); 946*7711facfSdinak case CKA_LOCAL: return (gettext("local")); 947*7711facfSdinak case CKA_SENSITIVE: return (gettext("sensitive")); 948*7711facfSdinak case CKA_EXTRACTABLE: return (gettext("extractable")); 949*7711facfSdinak case CKA_ENCRYPT: return (gettext("encrypt")); 950*7711facfSdinak case CKA_DECRYPT: return (gettext("decrypt")); 951*7711facfSdinak case CKA_WRAP: return (gettext("wrap")); 952*7711facfSdinak case CKA_UNWRAP: return (gettext("unwrap")); 953*7711facfSdinak case CKA_SIGN: return (gettext("sign")); 954*7711facfSdinak case CKA_SIGN_RECOVER: return (gettext("sign-recover")); 955*7711facfSdinak case CKA_VERIFY: return (gettext("verify")); 956*7711facfSdinak case CKA_VERIFY_RECOVER: return (gettext("verify-recover")); 957*7711facfSdinak case CKA_DERIVE: return (gettext("derive")); 958*7711facfSdinak case CKA_ALWAYS_SENSITIVE: return (gettext("always sensitive")); 959*7711facfSdinak case CKA_NEVER_EXTRACTABLE: return (gettext("never extractable")); 960*7711facfSdinak default: return (gettext("unknown capability")); 961*7711facfSdinak } 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 965*7711facfSdinak * Convert a byte string into a string of octets formatted like this: 966*7711facfSdinak * oo oo oo oo oo ... oo 967*7711facfSdinak * where each "oo" is an octet is space separated and in the form: 968*7711facfSdinak * [0-f][0-f] if the octet is a non-printable character 969*7711facfSdinak * <space><char> if the octet is a printable character 970*7711facfSdinak * 971*7711facfSdinak * Note: octets_sz must be 3 * str_sz + 1, or at least as long as "blank" 9727c478bd9Sstevel@tonic-gate */ 9737c478bd9Sstevel@tonic-gate void 974*7711facfSdinak octetify(CK_BYTE *str, CK_ULONG str_sz, char *octets, int octets_sz, 975*7711facfSdinak boolean_t stop_on_nul, boolean_t do_ascii, int limit, char *indent, 976*7711facfSdinak char *blank) 9777c478bd9Sstevel@tonic-gate { 978*7711facfSdinak char *marker; 979*7711facfSdinak int nc; 980*7711facfSdinak int newline; 981*7711facfSdinak int indent_len; 982*7711facfSdinak boolean_t first = B_TRUE; 983*7711facfSdinak 984*7711facfSdinak cryptodebug("inside octetify"); 985*7711facfSdinak 986*7711facfSdinak cryptodebug(stop_on_nul ? "stopping on first nul found" : 987*7711facfSdinak "continuing to full length of buffer"); 988*7711facfSdinak cryptodebug(do_ascii ? "using ascii chars where printable" : 989*7711facfSdinak "using only hex octets"); 990*7711facfSdinak cryptodebug("every %d characters indent with \"%s\"\n ", limit, indent); 991*7711facfSdinak cryptodebug("return \"%s\" if buffer is null or empty", blank); 9927c478bd9Sstevel@tonic-gate 993*7711facfSdinak /* If string is empty, write as much of the blank string and leave. */ 994*7711facfSdinak if (str_sz == 0) { 995*7711facfSdinak (void) snprintf(octets, octets_sz, "%s", blank); 996*7711facfSdinak return; 9977c478bd9Sstevel@tonic-gate } 998*7711facfSdinak 999*7711facfSdinak /* If only limit or indent is set, pick default for the other. */ 1000*7711facfSdinak if (limit > 0 && indent == NULL) 1001*7711facfSdinak indent = "\n"; 1002*7711facfSdinak if (indent != NULL && limit == 0) 1003*7711facfSdinak limit = 60; 1004*7711facfSdinak indent_len = strlen(indent); 1005*7711facfSdinak 1006*7711facfSdinak for (marker = octets, newline = 0, first = B_TRUE; 1007*7711facfSdinak (stop_on_nul && *str != '\0') || 1008*7711facfSdinak (!stop_on_nul && str_sz > 0 && octets_sz > 0); 1009*7711facfSdinak str++, str_sz--, marker += nc, octets_sz -= nc) { 1010*7711facfSdinak if (!first) { 1011*7711facfSdinak if (limit > 0 && ((marker - octets) / limit) > 1012*7711facfSdinak newline) { 1013*7711facfSdinak nc = snprintf(marker, indent_len, "%s", indent); 1014*7711facfSdinak newline++; 1015*7711facfSdinak continue; 1016*7711facfSdinak } 1017*7711facfSdinak nc = sprintf(marker, 1018*7711facfSdinak ((do_ascii && isprint(*str) && !isspace(*str)) ? 1019*7711facfSdinak "%s%c" : "%s%02x"), (do_ascii ? " " : ":"), *str); 1020*7711facfSdinak } else { 1021*7711facfSdinak nc = sprintf(marker, 1022*7711facfSdinak ((do_ascii && isprint(*str) && !isspace(*str)) ? 1023*7711facfSdinak "%c" : "%02x"), *str); 1024*7711facfSdinak first = B_FALSE; 1025*7711facfSdinak } 1026*7711facfSdinak } 1027*7711facfSdinak *marker = '\0'; 1028*7711facfSdinak } 1029*7711facfSdinak 1030*7711facfSdinak /* 1031*7711facfSdinak * Copies a biginteger_t to a template attribute. 1032*7711facfSdinak * Should be a macro instead of a function. 1033*7711facfSdinak */ 1034*7711facfSdinak void 1035*7711facfSdinak copy_bigint_to_attr(biginteger_t big, CK_ATTRIBUTE_PTR attr) 1036*7711facfSdinak { 1037*7711facfSdinak attr->pValue = big.big_value; 1038*7711facfSdinak attr->ulValueLen = big.big_value_len; 1039*7711facfSdinak } 1040*7711facfSdinak 1041*7711facfSdinak /* 1042*7711facfSdinak * Copies a string and its length to a template attribute. 1043*7711facfSdinak * Should be a macro instead of a function. 1044*7711facfSdinak */ 1045*7711facfSdinak void 1046*7711facfSdinak copy_string_to_attr(CK_BYTE *buf, CK_ULONG buflen, CK_ATTRIBUTE_PTR attr) 1047*7711facfSdinak { 1048*7711facfSdinak attr->pValue = buf; 1049*7711facfSdinak attr->ulValueLen = buflen; 1050*7711facfSdinak } 1051*7711facfSdinak 1052*7711facfSdinak /* 1053*7711facfSdinak * Copies a template attribute to a biginteger_t. 1054*7711facfSdinak * Should be a macro instead of a function. 1055*7711facfSdinak */ 1056*7711facfSdinak void 1057*7711facfSdinak copy_attr_to_bigint(CK_ATTRIBUTE_PTR attr, biginteger_t *big) 1058*7711facfSdinak { 1059*7711facfSdinak big->big_value = attr->pValue; 1060*7711facfSdinak big->big_value_len = attr->ulValueLen; 1061*7711facfSdinak } 1062*7711facfSdinak 1063*7711facfSdinak /* 1064*7711facfSdinak * Copies a template attribute to a string and its length. 1065*7711facfSdinak * Should be a macro instead of a function. 1066*7711facfSdinak */ 1067*7711facfSdinak void 1068*7711facfSdinak copy_attr_to_string(CK_ATTRIBUTE_PTR attr, CK_BYTE **buf, CK_ULONG *buflen) 1069*7711facfSdinak { 1070*7711facfSdinak *buf = attr->pValue; 1071*7711facfSdinak *buflen = attr->ulValueLen; 1072*7711facfSdinak } 1073*7711facfSdinak 1074*7711facfSdinak /* 1075*7711facfSdinak * Copies a template attribute to a date and its length. 1076*7711facfSdinak * Should be a macro instead of a function. 1077*7711facfSdinak */ 1078*7711facfSdinak void 1079*7711facfSdinak copy_attr_to_date(CK_ATTRIBUTE_PTR attr, CK_DATE **buf, CK_ULONG *buflen) 1080*7711facfSdinak { 1081*7711facfSdinak *buf = (CK_DATE *)attr->pValue; 1082*7711facfSdinak *buflen = attr->ulValueLen; 10837c478bd9Sstevel@tonic-gate } 1084