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