1 /* $NetBSD: create.c,v 1.1.1.4 2014/12/10 03:34:28 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Portions copyright (c) 2008 Nominet UK. All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 /* Id */ 44 45 /* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */ 46 47 /*! \file */ 48 49 #include <config.h> 50 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <time.h> 55 #include <unistd.h> 56 57 #include <isc/commandline.h> 58 #include <isc/print.h> 59 #include <isc/result.h> 60 #include <isc/types.h> 61 62 #include <pk11/pk11.h> 63 #include <pk11/result.h> 64 65 #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) 66 #define getpassphrase(x) getpass(x) 67 #endif 68 69 #ifndef HAVE_CLOCK_GETTIME 70 #ifndef CLOCK_REALTIME 71 #define CLOCK_REALTIME 0 72 #endif 73 74 int 75 clock_gettime(int32_t id, struct timespec *tp) 76 { 77 struct timeval tv; 78 int result; 79 80 result = gettimeofday(&tv, NULL); 81 if (result) 82 return (result); 83 tp->tv_sec = tv.tv_sec; 84 tp->tv_nsec = (long) tv.tv_usec * 1000; 85 return (result); 86 } 87 #endif 88 89 CK_BYTE buf[1024]; 90 char label[16]; 91 92 static CK_BBOOL truevalue = TRUE; 93 static CK_BBOOL falsevalue = FALSE; 94 95 int 96 main(int argc, char *argv[]) { 97 isc_result_t result; 98 CK_RV rv; 99 CK_SLOT_ID slot = 0; 100 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; 101 CK_OBJECT_HANDLE *hKey; 102 CK_OBJECT_CLASS kClass = CKO_DATA; 103 CK_ULONG len = sizeof(buf); 104 CK_ATTRIBUTE kTemplate[] = 105 { 106 { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, 107 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 108 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, 109 { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) }, 110 { CKA_VALUE, buf, (CK_ULONG) sizeof(buf) } 111 }; 112 pk11_context_t pctx; 113 char *lib_name = NULL; 114 char *pin = NULL; 115 int error = 0; 116 int c, errflg = 0; 117 int ontoken = 0; 118 unsigned int count = 1000; 119 unsigned int i; 120 struct timespec starttime; 121 struct timespec endtime; 122 123 while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { 124 switch (c) { 125 case 'm': 126 lib_name = isc_commandline_argument; 127 break; 128 case 's': 129 slot = atoi(isc_commandline_argument); 130 break; 131 case 't': 132 ontoken = 1; 133 break; 134 case 'p': 135 pin = isc_commandline_argument; 136 break; 137 case 'n': 138 count = atoi(isc_commandline_argument); 139 break; 140 case ':': 141 fprintf(stderr, 142 "Option -%c requires an operand\n", 143 isc_commandline_option); 144 errflg++; 145 break; 146 case '?': 147 default: 148 fprintf(stderr, "Unrecognised option: -%c\n", 149 isc_commandline_option); 150 errflg++; 151 } 152 } 153 154 if (errflg) { 155 fprintf(stderr, "Usage:\n"); 156 fprintf(stderr, 157 "\tcreate [-m module] [-s slot] [-t] [-n count]\n"); 158 exit(1); 159 } 160 161 pk11_result_register(); 162 163 /* Allocate hanles */ 164 hKey = (CK_SESSION_HANDLE *) 165 malloc(count * sizeof(CK_SESSION_HANDLE)); 166 if (hKey == NULL) { 167 perror("malloc"); 168 exit(1); 169 } 170 for (i = 0; i < count; i++) 171 hKey[i] = CK_INVALID_HANDLE; 172 173 /* Initialize the CRYPTOKI library */ 174 if (lib_name != NULL) 175 pk11_set_lib_name(lib_name); 176 177 if (pin == NULL) 178 pin = getpassphrase("Enter Pin: "); 179 180 result = pk11_get_session(&pctx, OP_ANY, ISC_TRUE, ISC_TRUE, 181 ISC_TRUE, (const char *) pin, slot); 182 if ((result != ISC_R_SUCCESS) && 183 (result != PK11_R_NORANDOMSERVICE) && 184 (result != PK11_R_NODIGESTSERVICE) && 185 (result != PK11_R_NOAESSERVICE)) { 186 fprintf(stderr, "Error initializing PKCS#11: %s\n", 187 isc_result_totext(result)); 188 exit(1); 189 } 190 191 if (pin != NULL) 192 memset(pin, 0, strlen((char *)pin)); 193 194 hSession = pctx.session; 195 196 /* Randomize the buffer */ 197 rv = pkcs_C_GenerateRandom(hSession, buf, len); 198 if (rv != CKR_OK) { 199 fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv); 200 goto exit_objects; 201 } 202 203 if (ontoken) 204 kTemplate[1].pValue = &truevalue; 205 206 if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { 207 perror("clock_gettime(start)"); 208 goto exit_objects; 209 } 210 211 for (i = 0; i < count; i++) { 212 (void) snprintf(label, sizeof(label), "obj%u", i); 213 kTemplate[3].ulValueLen = strlen(label); 214 rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]); 215 if (rv != CKR_OK) { 216 fprintf(stderr, 217 "C_CreateObject[%u]: Error = 0x%.8lX\n", 218 i, rv); 219 error = 1; 220 if (i == 0) 221 goto exit_objects; 222 break; 223 } 224 } 225 226 if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { 227 perror("clock_gettime(end)"); 228 goto exit_objects; 229 } 230 231 endtime.tv_sec -= starttime.tv_sec; 232 endtime.tv_nsec -= starttime.tv_nsec; 233 while (endtime.tv_nsec < 0) { 234 endtime.tv_sec -= 1; 235 endtime.tv_nsec += 1000000000; 236 } 237 printf("%u created objects in %ld.%09lds\n", i, 238 endtime.tv_sec, endtime.tv_nsec); 239 if (i > 0) 240 printf("%g created objects/s\n", 241 1024 * i / ((double) endtime.tv_sec + 242 (double) endtime.tv_nsec / 1000000000.)); 243 244 exit_objects: 245 for (i = 0; i < count; i++) { 246 /* Destroy objects */ 247 if (hKey[i] == CK_INVALID_HANDLE) 248 continue; 249 rv = pkcs_C_DestroyObject(hSession, hKey[i]); 250 if ((rv != CKR_OK) && !errflg) { 251 fprintf(stderr, 252 "C_DestroyObject[%u]: Error = 0x%.8lX\n", 253 i, rv); 254 errflg = 1; 255 } 256 } 257 258 free(hKey); 259 pk11_return_session(&pctx); 260 (void) pk11_finalize(); 261 262 exit(error); 263 } 264