4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
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.
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.
20 * Portions copyright (c) 2008 Nominet UK. All rights reserved.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
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.
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.
43 /* Id: pkcs11-keygen.c,v 1.9 2009/10/26 23:36:53 each Exp */
45 /* pkcs11-keygen - pkcs11 rsa key generator
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.
53 * pkcs11-keygen [-P] [-m module] [-s slot] [-e] -b keysize
54 * -l label [-i id] [-p pin]
67 #include <sys/types.h>
73 #ifndef FORCE_STATIC_PROVIDER
78 #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
79 #define getpassphrase(x) getpass(x)
82 /* Define static key template values */
83 static CK_BBOOL truevalue
= TRUE
;
84 static CK_BBOOL falsevalue
= FALSE
;
87 main(int argc
, char *argv
[])
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];
103 unsigned long id
= 0;
105 CK_ULONG ulObjectCount
;
106 /* Set search template */
107 CK_ATTRIBUTE search_template
[] = {
108 {CKA_LABEL
, NULL_PTR
, 0}
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
}
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
}
128 CK_ULONG privatekey_attrcnt
= 7;
133 pk11_provider
= getenv("PKCS11_PROVIDER");
134 if (pk11_provider
!= NULL
)
135 pk11_libname
= pk11_provider
;
137 while ((c
= getopt(argc
, argv
, ":Pm:s:b:ei:l:p:")) != -1) {
143 pk11_libname
= optarg
;
152 modulusbits
= atoi(optarg
);
155 label
= (CK_CHAR
*)optarg
;
158 id
= strtoul(optarg
, NULL
, 0);
162 pin
= (CK_UTF8CHAR
*)optarg
;
166 "Option -%c requires an operand\n",
172 fprintf(stderr
, "Unrecognised option: -%c\n", optopt
);
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");
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
);
192 /* Set public exponent to F4 or F5 */
193 public_exponent
[0] = 0x01;
194 public_exponent
[1] = 0x00;
196 public_exponent
[2] = 0x01;
198 publickey_template
[4].ulValueLen
= expsize
;
199 public_exponent
[2] = 0x00;
200 public_exponent
[3] = 0x00;
201 public_exponent
[4] = 0x01;
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;
211 privatekey_attrcnt
--;
212 } else if (id
<= 0xffff) {
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
;
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
;
225 /* Initialize the CRYPTOKI library */
226 rv
= C_Initialize(NULL_PTR
);
231 "Can't load or link module \"%s\"\n",
234 fprintf(stderr
, "C_Initialize: Error = 0x%.8lX\n", rv
);
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
);
243 fprintf(stderr
, "C_OpenSession: Error = 0x%.8lX\n", rv
);
248 /* Login to the Token (Keystore) */
250 pin
= (CK_UTF8CHAR
*)getpassphrase("Enter Pin: ");
252 rv
= C_Login(hSession
, CKU_USER
, pin
, strlen((char *)pin
));
253 memset(pin
, 0, strlen((char *)pin
));
255 fprintf(stderr
, "C_Login: Error = 0x%.8lX\n", rv
);
260 /* check if a key with the same id already exists */
261 rv
= C_FindObjectsInit(hSession
, search_template
, 1);
263 fprintf(stderr
, "C_FindObjectsInit: Error = 0x%.8lX\n", rv
);
267 rv
= C_FindObjects(hSession
, &privatekey
, 1, &ulObjectCount
);
269 fprintf(stderr
, "C_FindObjects: Error = 0x%.8lX\n", rv
);
273 if (ulObjectCount
!= 0) {
274 fprintf(stderr
, "Key already exists.\n");
279 /* Set attributes if the key is not to be hidden */
281 privatekey_template
[4].pValue
= &falsevalue
;
282 privatekey_template
[5].pValue
= &truevalue
;
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
);
292 fprintf(stderr
, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv
);
297 rv
= C_FindObjectsFinal(hSession
);
299 fprintf(stderr
, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv
);
304 (void)C_CloseSession(hSession
);
307 (void)C_Finalize(NULL_PTR
);