1/* 2 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 10 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 11 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 14 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* 18 * Portions copyright (c) 2008 Nominet UK. All rights reserved. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 32 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 34 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41/* $Id: pkcs11-keygen.c,v 1.9 2009/10/26 23:36:53 each Exp $ */ 42 43/* pkcs11-keygen - pkcs11 rsa key generator 44* 45* create RSASHA1 key in the keystore of an SCA6000 46* The calculation of key tag is left to the script 47* that converts the key into a DNSKEY RR and inserts 48* it into a zone file. 49* 50* usage: 51* pkcs11-keygen [-P] [-m module] [-s slot] [-e] -b keysize 52* -l label [-i id] [-p pin] 53* 54*/ 55 56/*! \file */ 57 58#include <config.h> 59 60#include <stdio.h> 61#include <stdlib.h> 62#include <fcntl.h> 63#include <errno.h> 64#include <string.h> 65#include <sys/types.h> 66#include "cryptoki.h" 67 68#ifdef WIN32 69#include "win32.c" 70#else 71#ifndef FORCE_STATIC_PROVIDER 72#include "unix.c" 73#endif 74#endif 75 76#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) 77#define getpassphrase(x) getpass(x) 78#endif 79 80/* Define static key template values */ 81static CK_BBOOL truevalue = TRUE; 82static CK_BBOOL falsevalue = FALSE; 83 84int 85main(int argc, char *argv[]) 86{ 87 CK_RV rv; 88 CK_SLOT_ID slot = 0; 89 CK_MECHANISM genmech; 90 CK_SESSION_HANDLE hSession; 91 CK_UTF8CHAR *pin = NULL; 92 CK_ULONG modulusbits = 0; 93 CK_CHAR *label = NULL; 94 CK_OBJECT_HANDLE privatekey, publickey; 95 CK_BYTE public_exponent[5]; 96 CK_ULONG expsize = 3; 97 int error = 0; 98 int c, errflg = 0; 99 int hide = 1; 100 int idlen = 0; 101 unsigned long id = 0; 102 CK_BYTE idbuf[4]; 103 CK_ULONG ulObjectCount; 104 /* Set search template */ 105 CK_ATTRIBUTE search_template[] = { 106 {CKA_LABEL, NULL_PTR, 0} 107 }; 108 CK_ATTRIBUTE publickey_template[] = { 109 {CKA_LABEL, NULL_PTR, 0}, 110 {CKA_VERIFY, &truevalue, sizeof(truevalue)}, 111 {CKA_TOKEN, &truevalue, sizeof(truevalue)}, 112 {CKA_MODULUS_BITS, &modulusbits, sizeof(modulusbits)}, 113 {CKA_PUBLIC_EXPONENT, &public_exponent, expsize}, 114 {CKA_ID, &idbuf, idlen} 115 }; 116 CK_ULONG publickey_attrcnt = 6; 117 CK_ATTRIBUTE privatekey_template[] = { 118 {CKA_LABEL, NULL_PTR, 0}, 119 {CKA_SIGN, &truevalue, sizeof(truevalue)}, 120 {CKA_TOKEN, &truevalue, sizeof(truevalue)}, 121 {CKA_PRIVATE, &truevalue, sizeof(truevalue)}, 122 {CKA_SENSITIVE, &truevalue, sizeof(truevalue)}, 123 {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)}, 124 {CKA_ID, &idbuf, idlen} 125 }; 126 CK_ULONG privatekey_attrcnt = 7; 127 char *pk11_provider; 128 extern char *optarg; 129 extern int optopt; 130 131 pk11_provider = getenv("PKCS11_PROVIDER"); 132 if (pk11_provider != NULL) 133 pk11_libname = pk11_provider; 134 135 while ((c = getopt(argc, argv, ":Pm:s:b:ei:l:p:")) != -1) { 136 switch (c) { 137 case 'P': 138 hide = 0; 139 break; 140 case 'm': 141 pk11_libname = optarg; 142 break; 143 case 's': 144 slot = atoi(optarg); 145 break; 146 case 'e': 147 expsize = 5; 148 break; 149 case 'b': 150 modulusbits = atoi(optarg); 151 break; 152 case 'l': 153 label = (CK_CHAR *)optarg; 154 break; 155 case 'i': 156 id = strtoul(optarg, NULL, 0); 157 idlen = 4; 158 break; 159 case 'p': 160 pin = (CK_UTF8CHAR *)optarg; 161 break; 162 case ':': 163 fprintf(stderr, 164 "Option -%c requires an operand\n", 165 optopt); 166 errflg++; 167 break; 168 case '?': 169 default: 170 fprintf(stderr, "Unrecognised option: -%c\n", optopt); 171 errflg++; 172 } 173 } 174 175 if (errflg || !modulusbits || (label == NULL)) { 176 fprintf(stderr, "Usage:\n"); 177 fprintf(stderr, "\tpkcs11-keygen -b keysize -l label\n"); 178 fprintf(stderr, "\t [-P] [-m module] " 179 "[-s slot] [-e] [-i id] [-p PIN]\n"); 180 exit(2); 181 } 182 183 search_template[0].pValue = label; 184 search_template[0].ulValueLen = strlen((char *)label); 185 publickey_template[0].pValue = label; 186 publickey_template[0].ulValueLen = strlen((char *)label); 187 privatekey_template[0].pValue = label; 188 privatekey_template[0].ulValueLen = strlen((char *)label); 189 190 /* Set public exponent to F4 or F5 */ 191 public_exponent[0] = 0x01; 192 public_exponent[1] = 0x00; 193 if (expsize == 3) 194 public_exponent[2] = 0x01; 195 else { 196 publickey_template[4].ulValueLen = expsize; 197 public_exponent[2] = 0x00; 198 public_exponent[3] = 0x00; 199 public_exponent[4] = 0x01; 200 } 201 202 /* Set up mechanism for generating key pair */ 203 genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; 204 genmech.pParameter = NULL_PTR; 205 genmech.ulParameterLen = 0; 206 207 if (idlen == 0) { 208 publickey_attrcnt--; 209 privatekey_attrcnt--; 210 } else if (id <= 0xffff) { 211 idlen = 2; 212 publickey_template[5].ulValueLen = idlen; 213 privatekey_template[6].ulValueLen = idlen; 214 idbuf[0] = (CK_BYTE)(id >> 8); 215 idbuf[1] = (CK_BYTE)id; 216 } else { 217 idbuf[0] = (CK_BYTE)(id >> 24); 218 idbuf[1] = (CK_BYTE)(id >> 16); 219 idbuf[2] = (CK_BYTE)(id >> 8); 220 idbuf[3] = (CK_BYTE)id; 221 } 222 223 /* Initialize the CRYPTOKI library */ 224 rv = C_Initialize(NULL_PTR); 225 226 if (rv != CKR_OK) { 227 if (rv == 0xfe) 228 fprintf(stderr, 229 "Can't load or link module \"%s\"\n", 230 pk11_libname); 231 else 232 fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); 233 exit(1); 234 } 235 236 /* Open a session on the slot found */ 237 rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION, 238 NULL_PTR, NULL_PTR, &hSession); 239 240 if (rv != CKR_OK) { 241 fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv); 242 error = 1; 243 goto exit_program; 244 } 245 246 /* Login to the Token (Keystore) */ 247 if (pin == NULL) 248 pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); 249 250 rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin)); 251 memset(pin, 0, strlen((char *)pin)); 252 if (rv != CKR_OK) { 253 fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv); 254 error = 1; 255 goto exit_session; 256 } 257 258 /* check if a key with the same id already exists */ 259 rv = C_FindObjectsInit(hSession, search_template, 1); 260 if (rv != CKR_OK) { 261 fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); 262 error = 1; 263 goto exit_session; 264 } 265 rv = C_FindObjects(hSession, &privatekey, 1, &ulObjectCount); 266 if (rv != CKR_OK) { 267 fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); 268 error = 1; 269 goto exit_search; 270 } 271 if (ulObjectCount != 0) { 272 fprintf(stderr, "Key already exists.\n"); 273 error = 1; 274 goto exit_search; 275 } 276 277 /* Set attributes if the key is not to be hidden */ 278 if (!hide) { 279 privatekey_template[4].pValue = &falsevalue; 280 privatekey_template[5].pValue = &truevalue; 281 } 282 283 /* Generate Key pair for signing/verifying */ 284 rv = C_GenerateKeyPair(hSession, &genmech, 285 publickey_template, publickey_attrcnt, 286 privatekey_template, privatekey_attrcnt, 287 &publickey, &privatekey); 288 289 if (rv != CKR_OK) { 290 fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv); 291 error = 1; 292 } 293 294 exit_search: 295 rv = C_FindObjectsFinal(hSession); 296 if (rv != CKR_OK) { 297 fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); 298 error = 1; 299 } 300 301 exit_session: 302 (void)C_CloseSession(hSession); 303 304 exit_program: 305 (void)C_Finalize(NULL_PTR); 306 307 exit(error); 308} 309