1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <errno.h>
27 #include <sys/sysmacros.h>
28 #include <security/cryptoki.h>
29 #include <security/pkcs11.h>
30 #include <stdio.h>
31 #include <strings.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #include <fcntl.h>
39 #include <inet/kssl/kssl.h>
40 #include <cryptoutil.h>
41 #include <libscf.h>
42 #include "kssladm.h"
43
44 #include <kmfapi.h>
45
46 void
usage_create(boolean_t do_print)47 usage_create(boolean_t do_print)
48 {
49 if (do_print)
50 (void) fprintf(stderr, "Usage:\n");
51 (void) fprintf(stderr, "kssladm create"
52 " -f pkcs11 [-d softtoken_directory] -T <token_label>"
53 " -C <certificate_label> -x <proxy_port>"
54 " [-h <ca_certchain_file>]"
55 " [options] [<server_address>] [<server_port>]\n");
56
57 (void) fprintf(stderr, "kssladm create"
58 " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
59 " [options] [<server_address>] [<server_port>]\n");
60
61 (void) fprintf(stderr, "kssladm create"
62 " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
63 " [options] [<server_address>] [<server_port>]\n");
64
65 (void) fprintf(stderr, "options are:\n"
66 "\t[-c <ciphersuites>]\n"
67 "\t[-p <password_file>]\n"
68 "\t[-t <ssl_session_cache_timeout>]\n"
69 "\t[-z <ssl_session_cache_size>]\n"
70 "\t[-v]\n");
71 }
72
73 /*
74 * Everything is allocated in one single contiguous buffer.
75 * The layout is the following:
76 * . the kssl_params_t structure
77 * . optional buffer containing pin (if key is non extractable)
78 * . the array of key attribute structs, (value of ck_attrs)
79 * . the key attributes values (values of ck_attrs[i].ck_value);
80 * . the array of sizes of the certificates, (referred to as sc_sizes[])
81 * . the certificates values (referred to as sc_certs[])
82 *
83 * The address of the certs and key attributes values are offsets
84 * from the beginning of the big buffer. sc_sizes_offset points
85 * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
86 */
87 static kssl_params_t *
kmf_to_kssl(int nxkey,KMF_RAW_KEY_DATA * rsa,int ncerts,KMF_X509_DER_CERT * certs,int * paramsize,char * token_label,KMF_DATA * idstr,KMF_CREDENTIAL * creds)88 kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
89 KMF_X509_DER_CERT *certs, int *paramsize,
90 char *token_label, KMF_DATA *idstr,
91 KMF_CREDENTIAL *creds)
92 {
93 int i, tcsize;
94 kssl_params_t *kssl_params;
95 kssl_key_t *key;
96 char *buf;
97 uint32_t bufsize;
98 static CK_BBOOL true = TRUE;
99 static CK_BBOOL false = FALSE;
100 static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
101 static CK_KEY_TYPE keytype = CKK_RSA;
102 kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
103 CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
104 {CKA_TOKEN, &true, sizeof (true)},
105 {CKA_EXTRACTABLE, &false, sizeof (false)},
106 {CKA_CLASS, &class, sizeof (class) },
107 {CKA_KEY_TYPE, &keytype, sizeof (keytype) },
108 {CKA_ID, NULL, 0}
109 };
110 kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
111 {SUN_CKA_MODULUS, NULL, 0},
112 {SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
113 {SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
114 {SUN_CKA_PRIME_1, NULL, 0},
115 {SUN_CKA_PRIME_2, NULL, 0},
116 {SUN_CKA_EXPONENT_1, NULL, 0},
117 {SUN_CKA_EXPONENT_2, NULL, 0},
118 {SUN_CKA_COEFFICIENT, NULL, 0}
119 };
120 KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
121 int attr_cnt;
122
123 if (nxkey && idstr != NULL) {
124 exkey_attrs[4].pValue = idstr->Data;
125 exkey_attrs[4].ulValueLen = idstr->Length;
126 }
127 tcsize = 0;
128 for (i = 0; i < ncerts; i++)
129 tcsize += certs[i].certificate.Length;
130
131 bufsize = sizeof (kssl_params_t);
132 bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
133
134 if (!nxkey) {
135 bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
136 MAX_ATTR_CNT);
137 /* and the key attributes */
138 priv_key_bignums[0] = rsa->rawdata.rsa.mod;
139 priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
140 priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
141 priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
142 priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
143 priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
144 priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
145 priv_key_bignums[7] = rsa->rawdata.rsa.coef;
146
147 if (rsa->rawdata.rsa.mod.val == NULL ||
148 rsa->rawdata.rsa.priexp.val == NULL) {
149 (void) fprintf(stderr,
150 "missing required attributes in private key.\n");
151 return (NULL);
152 }
153
154 attr_cnt = 0;
155 for (i = 0; i < MAX_ATTR_CNT; i++) {
156 if (priv_key_bignums[i].val == NULL)
157 continue;
158 kssl_attrs[attr_cnt].ka_type =
159 kssl_tmpl_attrs[i].ka_type;
160 kssl_attrs[attr_cnt].ka_value_len =
161 priv_key_bignums[i].len;
162 bufsize += sizeof (crypto_object_attribute_t) +
163 kssl_attrs[attr_cnt].ka_value_len;
164 attr_cnt++;
165 }
166 } else {
167 /*
168 * Compute space for the attributes and values that the
169 * kssl kernel module will need in order to search for
170 * the private key.
171 */
172 for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
173 bufsize += sizeof (crypto_object_attribute_t) +
174 exkey_attrs[attr_cnt].ulValueLen;
175 }
176 if (creds)
177 bufsize += creds->credlen;
178 }
179
180 /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
181 bufsize += sizeof (uint32_t);
182
183 /* Now the big memory allocation */
184 if ((buf = calloc(bufsize, 1)) == NULL) {
185 (void) fprintf(stderr,
186 "Cannot allocate memory for the kssl_params "
187 "and values\n");
188 return (NULL);
189 }
190
191 /* LINTED */
192 kssl_params = (kssl_params_t *)buf;
193
194 buf = (char *)(kssl_params + 1);
195
196 if (!nxkey) {
197 /* the keys attributes structs array */
198 key = &kssl_params->kssl_privkey;
199 key->ks_format = CRYPTO_KEY_ATTR_LIST;
200 key->ks_count = attr_cnt;
201 key->ks_attrs_offset = buf - (char *)kssl_params;
202 buf += attr_cnt * sizeof (kssl_object_attribute_t);
203
204 attr_cnt = 0;
205 /* then the key attributes values */
206 for (i = 0; i < MAX_ATTR_CNT; i++) {
207 if (priv_key_bignums[i].val == NULL)
208 continue;
209 (void) memcpy(buf, priv_key_bignums[i].val,
210 priv_key_bignums[i].len);
211 kssl_attrs[attr_cnt].ka_value_offset =
212 buf - (char *)kssl_params;
213 buf += kssl_attrs[attr_cnt].ka_value_len;
214 attr_cnt++;
215 }
216 } else {
217 char tlabel[CRYPTO_EXT_SIZE_LABEL];
218 bzero(tlabel, sizeof (tlabel));
219 (void) strlcpy(tlabel, token_label, sizeof (tlabel));
220
221 /*
222 * For a non-extractable key, we must provide the PIN
223 * so the kssl module can access the token to find
224 * the key handle.
225 */
226 kssl_params->kssl_is_nxkey = 1;
227 bcopy(tlabel, kssl_params->kssl_token.toklabel,
228 CRYPTO_EXT_SIZE_LABEL);
229 kssl_params->kssl_token.pinlen = creds->credlen;
230 kssl_params->kssl_token.tokpin_offset =
231 buf - (char *)kssl_params;
232 kssl_params->kssl_token.ck_rv = 0;
233 bcopy(creds->cred, buf, creds->credlen);
234 buf += creds->credlen;
235
236 /*
237 * Next in the buffer, we must provide the attributes
238 * that the kssl module will use to search in the
239 * token to find the protected key handle.
240 */
241 key = &kssl_params->kssl_privkey;
242 key->ks_format = CRYPTO_KEY_ATTR_LIST;
243 key->ks_count = attr_cnt;
244 key->ks_attrs_offset = buf - (char *)kssl_params;
245
246 buf += attr_cnt * sizeof (kssl_object_attribute_t);
247 for (i = 0; i < attr_cnt; i++) {
248 bcopy(exkey_attrs[i].pValue, buf,
249 exkey_attrs[i].ulValueLen);
250
251 kssl_attrs[i].ka_type = exkey_attrs[i].type;
252 kssl_attrs[i].ka_value_offset =
253 buf - (char *)kssl_params;
254 kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
255
256 buf += exkey_attrs[i].ulValueLen;
257 }
258 }
259 /* Copy the key attributes array here */
260 bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
261 attr_cnt * sizeof (kssl_object_attribute_t));
262
263 buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
264
265 /*
266 * Finally, add the certificate chain to the buffer.
267 */
268 kssl_params->kssl_certs.sc_count = ncerts;
269
270 /* First, an array of certificate sizes */
271 for (i = 0; i < ncerts; i++) {
272 uint32_t certsz = (uint32_t)certs[i].certificate.Length;
273 char *p = buf + (i * sizeof (uint32_t));
274 bcopy(&certsz, p, sizeof (uint32_t));
275 }
276
277 kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
278 buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
279
280 kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
281
282 /* Now add the certificate data (ASN.1 DER encoded) */
283 for (i = 0; i < ncerts; i++) {
284 bcopy(certs[i].certificate.Data, buf,
285 certs[i].certificate.Length);
286 buf += certs[i].certificate.Length;
287 }
288
289 *paramsize = bufsize;
290 return (kssl_params);
291 }
292
293 /*
294 * Extract a sensitive key via wrap/unwrap operations.
295 *
296 * This function requires that we call PKCS#11 API directly since
297 * KMF does not yet support wrapping/unwrapping of keys. By extracting
298 * a sensitive key in wrapped form, we then unwrap it into a session key
299 * object. KMF is then used to find the session key and return it in
300 * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
301 */
302 static KMF_RETURN
get_sensitive_key_data(KMF_HANDLE_T kmfh,KMF_CREDENTIAL * creds,char * keylabel,char * idstr,KMF_KEY_HANDLE * key,KMF_KEY_HANDLE * rawkey)303 get_sensitive_key_data(KMF_HANDLE_T kmfh,
304 KMF_CREDENTIAL *creds, char *keylabel,
305 char *idstr, KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
306 {
307 KMF_RETURN rv = KMF_OK;
308 static CK_BYTE aes_param[16];
309 static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
310 static CK_KEY_TYPE privkey_type = CKK_RSA;
311 static CK_BBOOL false = FALSE;
312 boolean_t kmftrue = B_TRUE;
313 boolean_t kmffalse = B_FALSE;
314 char *err = NULL;
315 char wrapkey_label[BUFSIZ];
316 int fd;
317 uint32_t nkeys = 0;
318 CK_RV ckrv;
319 CK_SESSION_HANDLE pk11session;
320 CK_BYTE aes_key_val[16];
321 int numattr = 0;
322 int idx;
323 KMF_ATTRIBUTE attrlist[16];
324 KMF_KEYSTORE_TYPE kstype;
325 KMF_KEY_CLASS kclass;
326 KMF_ENCODE_FORMAT format;
327
328 CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
329 sizeof (aes_param)};
330 CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
331 CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
332 CK_BYTE *wrapped_privkey = NULL;
333 CK_ULONG wrapped_privkey_len = 0;
334
335 CK_ATTRIBUTE unwrap_tmpl[] = {
336 /* code below depends on the following attribute order */
337 {CKA_TOKEN, &false, sizeof (false)},
338 {CKA_CLASS, &privkey_class, sizeof (privkey_class)},
339 {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
340 {CKA_SENSITIVE, &false, sizeof (false)},
341 {CKA_PRIVATE, &false, sizeof (false)},
342 {CKA_LABEL, NULL, 0}
343 };
344
345 /*
346 * Create a wrap key with random data.
347 */
348 fd = open("/dev/urandom", O_RDONLY);
349 if (fd == -1) {
350 perror("Error reading /dev/urandom");
351 return (KMF_ERR_INTERNAL);
352 }
353 if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
354 sizeof (aes_key_val)) {
355 perror("Error reading from /dev/urandom");
356 (void) close(fd);
357 return (KMF_ERR_INTERNAL);
358 }
359 (void) close(fd);
360
361 pk11session = kmf_get_pk11_handle(kmfh);
362
363 /*
364 * Login to create the wrap key stuff.
365 */
366 ckrv = C_Login(pk11session, CKU_USER,
367 (CK_UTF8CHAR_PTR)creds->cred, creds->credlen);
368 if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
369 (void) fprintf(stderr,
370 "Cannot login to the token. error = %s\n",
371 pkcs11_strerror(ckrv));
372 return (KMF_ERR_INTERNAL);
373 }
374
375 /*
376 * Turn the random key into a PKCS#11 session object.
377 */
378 ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
379 sizeof (aes_key_val), &aes_key_obj);
380 if (ckrv != CKR_OK) {
381 (void) fprintf(stderr,
382 "Cannot create wrapping key. error = %s\n",
383 pkcs11_strerror(ckrv));
384 return (KMF_ERR_INTERNAL);
385 }
386
387 /*
388 * Find the original private key that we are going to wrap.
389 */
390 kstype = KMF_KEYSTORE_PK11TOKEN;
391 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
392 &kstype, sizeof (kstype));
393 numattr++;
394
395 kclass = KMF_ASYM_PRI;
396 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
397 &kclass, sizeof (kclass));
398 numattr++;
399
400 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
401 creds, sizeof (KMF_CREDENTIAL));
402 numattr++;
403
404 if (keylabel) {
405 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
406 keylabel, strlen(keylabel));
407 numattr++;
408 }
409 if (idstr) {
410 kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
411 idstr, strlen(idstr));
412 numattr++;
413 }
414 format = KMF_FORMAT_NATIVE;
415 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
416 &format, sizeof (format));
417 numattr++;
418
419 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
420 &kmftrue, sizeof (kmftrue));
421 numattr++;
422
423 kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
424 &kmftrue, sizeof (kmftrue));
425 numattr++;
426
427 nkeys = 1;
428 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
429 &nkeys, sizeof (nkeys));
430 numattr++;
431
432 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
433 key, sizeof (KMF_KEY_HANDLE));
434 numattr++;
435
436 rv = kmf_find_key(kmfh, numattr, attrlist);
437 if (rv != KMF_OK) {
438 REPORT_KMF_ERROR(rv, "Error finding private key", err);
439 goto out;
440 }
441
442 /*
443 * Get the size of the wrapped private key.
444 */
445 bzero(aes_param, sizeof (aes_param));
446 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
447 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
448 NULL, &wrapped_privkey_len);
449 if (ckrv != CKR_OK) {
450 /*
451 * Most common error here is that the token doesn't
452 * support the wrapping mechanism or the key is
453 * marked non-extractable. Return an error and let
454 * the caller deal with it gracefully.
455 */
456 (void) fprintf(stderr,
457 "Cannot get wrap key size. error = %s\n",
458 pkcs11_strerror(ckrv));
459 rv = KMF_ERR_INTERNAL;
460 goto out;
461 }
462 wrapped_privkey = malloc(wrapped_privkey_len);
463 if (wrapped_privkey == NULL) {
464 rv = KMF_ERR_MEMORY;
465 goto out;
466 }
467 /*
468 * Now get the actual wrapped key data.
469 */
470 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
471 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
472 wrapped_privkey, &wrapped_privkey_len);
473 if (ckrv != CKR_OK) {
474 (void) fprintf(stderr,
475 "Cannot wrap private key. error = %s\n",
476 pkcs11_strerror(ckrv));
477 rv = KMF_ERR_INTERNAL;
478 goto out;
479 }
480 /*
481 * Create a label for the wrapped session key so we can find
482 * it easier later.
483 */
484 (void) snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
485 getpid());
486
487 unwrap_tmpl[5].pValue = wrapkey_label;
488 unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
489
490 /*
491 * Unwrap the key into the template and create a temporary
492 * session private key.
493 */
494 ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
495 wrapped_privkey, wrapped_privkey_len,
496 unwrap_tmpl, 6, &sess_privkey_obj);
497 if (ckrv != CKR_OK) {
498 (void) fprintf(stderr,
499 "Cannot unwrap private key. error = %s\n",
500 pkcs11_strerror(ckrv));
501 rv = KMF_ERR_INTERNAL;
502 goto out;
503 }
504
505 /*
506 * Use KMF to find the session key and return it as RAW data
507 * so we can pass it along to KSSL.
508 */
509 kclass = KMF_ASYM_PRI;
510 if ((idx = kmf_find_attr(KMF_KEYCLASS_ATTR, attrlist, numattr)) != -1) {
511 attrlist[idx].pValue = &kclass;
512 }
513
514 format = KMF_FORMAT_RAWKEY;
515 if ((idx = kmf_find_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
516 numattr)) != -1) {
517 attrlist[idx].pValue = &format;
518 }
519 if (wrapkey_label != NULL &&
520 (idx = kmf_find_attr(KMF_KEYLABEL_ATTR, attrlist, numattr)) != -1) {
521 attrlist[idx].pValue = wrapkey_label;
522 attrlist[idx].valueLen = strlen(wrapkey_label);
523 }
524
525 if ((idx = kmf_find_attr(KMF_PRIVATE_BOOL_ATTR, attrlist,
526 numattr)) != -1) {
527 attrlist[idx].pValue = &kmffalse;
528 }
529 if ((idx = kmf_find_attr(KMF_TOKEN_BOOL_ATTR, attrlist,
530 numattr)) != -1) {
531 attrlist[idx].pValue = &kmffalse;
532 }
533
534 if ((idx = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist,
535 numattr)) != -1) {
536 attrlist[idx].pValue = rawkey;
537 }
538 /*
539 * Clear the IDSTR attribute since it is not part of the
540 * wrapped session key.
541 */
542 if ((idx = kmf_find_attr(KMF_IDSTR_ATTR, attrlist,
543 numattr)) != -1) {
544 attrlist[idx].pValue = NULL;
545 attrlist[idx].valueLen = 0;
546 }
547
548 /* The wrapped key should not be sensitive. */
549 kmf_set_attr_at_index(attrlist, numattr, KMF_SENSITIVE_BOOL_ATTR,
550 &false, sizeof (false));
551 numattr++;
552
553 rv = kmf_find_key(kmfh, numattr, attrlist);
554 if (rv != KMF_OK) {
555 REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
556 goto out;
557 }
558 out:
559 if (wrapped_privkey)
560 free(wrapped_privkey);
561
562 if (aes_key_obj != CK_INVALID_HANDLE)
563 (void) C_DestroyObject(pk11session, aes_key_obj);
564
565 if (sess_privkey_obj != CK_INVALID_HANDLE)
566 (void) C_DestroyObject(pk11session, sess_privkey_obj);
567
568 return (rv);
569 }
570
571 static kssl_params_t *
load_from_pkcs11(KMF_HANDLE_T kmfh,const char * token_label,const char * password_file,const char * certname,int * bufsize)572 load_from_pkcs11(KMF_HANDLE_T kmfh,
573 const char *token_label, const char *password_file,
574 const char *certname, int *bufsize)
575 {
576 KMF_RETURN rv;
577 KMF_X509_DER_CERT cert;
578 KMF_KEY_HANDLE key, rawkey;
579 KMF_CREDENTIAL creds;
580 KMF_DATA iddata = { 0, NULL };
581 kssl_params_t *kssl_params = NULL;
582 uint32_t ncerts, nkeys;
583 char *err, *idstr = NULL;
584 char password_buf[1024];
585 int nxkey = 0;
586 int numattr = 0;
587 KMF_ATTRIBUTE attrlist[16];
588 KMF_KEYSTORE_TYPE kstype;
589 KMF_KEY_CLASS kclass;
590 KMF_ENCODE_FORMAT format;
591 boolean_t false = B_FALSE;
592 boolean_t true = B_TRUE;
593
594 if (get_passphrase(password_file, password_buf,
595 sizeof (password_buf)) <= 0) {
596 perror("Unable to read passphrase");
597 goto done;
598 }
599 creds.cred = password_buf;
600 creds.credlen = strlen(password_buf);
601
602 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
603 (void) memset(&rawkey, 0, sizeof (KMF_KEY_HANDLE));
604
605 kstype = KMF_KEYSTORE_PK11TOKEN;
606 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
607 &kstype, sizeof (kstype));
608 numattr++;
609
610 if (token_label && strlen(token_label)) {
611 kmf_set_attr_at_index(attrlist, numattr,
612 KMF_TOKEN_LABEL_ATTR,
613 (void *)token_label, strlen(token_label));
614 numattr++;
615 }
616
617 kmf_set_attr_at_index(attrlist, numattr, KMF_READONLY_ATTR,
618 &false, sizeof (false));
619 numattr++;
620
621 rv = kmf_configure_keystore(kmfh, numattr, attrlist);
622 if (rv != KMF_OK) {
623 REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
624 goto done;
625 }
626
627 /*
628 * Find the certificate matching the given label.
629 */
630 numattr = 0;
631 kstype = KMF_KEYSTORE_PK11TOKEN;
632 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
633 &kstype, sizeof (kstype));
634 numattr++;
635
636 if (certname) {
637 kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
638 (void *)certname, strlen(certname));
639 numattr++;
640 }
641 ncerts = 1;
642
643 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
644 &ncerts, sizeof (ncerts));
645 numattr++;
646
647 kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
648 &cert, sizeof (cert));
649 numattr++;
650
651 rv = kmf_find_cert(kmfh, numattr, attrlist);
652 if (rv != KMF_OK || ncerts == 0)
653 goto done;
654
655 /*
656 * Find the associated private key for this cert by
657 * keying off of the label and the ASCII ID string.
658 */
659 rv = kmf_get_cert_id_str(&cert.certificate, &idstr);
660 if (rv != KMF_OK)
661 goto done;
662
663 numattr = 1; /* attrlist[0] is already set to kstype */
664
665 kclass = KMF_ASYM_PRI;
666 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
667 &kclass, sizeof (kclass));
668 numattr++;
669
670 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
671 &creds, sizeof (KMF_CREDENTIAL));
672 numattr++;
673
674 format = KMF_FORMAT_RAWKEY;
675 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
676 &format, sizeof (format));
677 numattr++;
678
679 if (certname) {
680 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
681 (void *)certname, strlen(certname));
682 numattr++;
683 }
684 if (idstr) {
685 kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
686 (void *)idstr, strlen(idstr));
687 numattr++;
688 }
689 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
690 &true, sizeof (true));
691 numattr++;
692
693 kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
694 &true, sizeof (true));
695 numattr++;
696
697 /* We only expect to find 1 key at most */
698 nkeys = 1;
699 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
700 &nkeys, sizeof (nkeys));
701 numattr++;
702
703 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
704 &key, sizeof (KMF_KEY_HANDLE));
705 numattr++;
706
707 rv = kmf_find_key(kmfh, numattr, attrlist);
708 if (rv == KMF_ERR_SENSITIVE_KEY) {
709 kmf_free_kmf_key(kmfh, &key);
710 /*
711 * Get a normal key handle and then do a wrap/unwrap
712 * in order to get the necessary raw data fields needed
713 * to send to KSSL.
714 */
715 format = KMF_FORMAT_NATIVE;
716 rv = get_sensitive_key_data(kmfh, &creds,
717 (char *)certname, idstr, &key, &rawkey);
718 if (rv == KMF_OK) {
719 /* Swap "key" for "rawkey" */
720 kmf_free_kmf_key(kmfh, &key);
721
722 key = rawkey;
723 } else {
724 kmf_free_kmf_key(kmfh, &key);
725
726 /* Let kssl try to find the key. */
727 nxkey = 1;
728 rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
729 }
730 } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
731 kmf_free_kmf_key(kmfh, &key);
732
733 /* Let kssl try to find the key. */
734 nxkey = 1;
735 rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
736 } else if (rv != KMF_OK || nkeys == 0)
737 goto done;
738
739 if (rv == KMF_OK)
740 kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
741 1, &cert, bufsize, (char *)token_label, &iddata, &creds);
742 done:
743 if (ncerts != 0)
744 kmf_free_kmf_cert(kmfh, &cert);
745 if (nkeys != 0)
746 kmf_free_kmf_key(kmfh, &key);
747 if (idstr)
748 free(idstr);
749
750 return (kssl_params);
751 }
752
753 /*
754 * add_cacerts
755 *
756 * Load a chain of certificates from a PEM file.
757 */
758 static kssl_params_t *
add_cacerts(KMF_HANDLE_T kmfh,kssl_params_t * old_params,const char * cacert_chain_file)759 add_cacerts(KMF_HANDLE_T kmfh,
760 kssl_params_t *old_params, const char *cacert_chain_file)
761 {
762 int i, newlen;
763 uint32_t certlen = 0, ncerts;
764 char *buf;
765 KMF_RETURN rv;
766 KMF_X509_DER_CERT *certs = NULL;
767 kssl_params_t *kssl_params;
768 char *err = NULL;
769 int numattr = 0;
770 KMF_ATTRIBUTE attrlist[16];
771 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
772
773 kstype = KMF_KEYSTORE_OPENSSL;
774
775 ncerts = 0;
776 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
777 &kstype, sizeof (KMF_KEYSTORE_TYPE));
778 numattr++;
779
780 kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
781 (void *)cacert_chain_file, strlen(cacert_chain_file));
782 numattr++;
783
784 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
785 &ncerts, sizeof (ncerts));
786 numattr++;
787
788 rv = kmf_find_cert(kmfh, numattr, attrlist);
789 if (rv != KMF_OK) {
790 REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
791 return (0);
792 }
793 certs = (KMF_X509_DER_CERT *)malloc(ncerts *
794 sizeof (KMF_X509_DER_CERT));
795 if (certs == NULL) {
796 (void) fprintf(stderr, "memory allocation error.\n");
797 return (NULL);
798 }
799 bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
800
801 /* add new attribute for the cert list to be returned */
802 kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
803 certs, (ncerts * sizeof (KMF_X509_DER_CERT)));
804 numattr++;
805 rv = kmf_find_cert(kmfh, numattr, attrlist);
806
807 if (rv != KMF_OK || ncerts == 0) {
808 bzero(old_params, old_params->kssl_params_size);
809 free(old_params);
810 return (NULL);
811 }
812
813 if (verbose) {
814 (void) printf("%d certificates read successfully\n", ncerts);
815 }
816
817 newlen = old_params->kssl_params_size;
818 for (i = 0; i < ncerts; i++)
819 newlen += certs[i].certificate.Length;
820
821 /*
822 * Get a bigger structure and update the
823 * fields to account for the additional certs.
824 */
825 kssl_params = realloc(old_params, newlen);
826
827 kssl_params->kssl_params_size = newlen;
828 kssl_params->kssl_certs.sc_count += ncerts;
829
830 /* Put the cert size info starting from sc_sizes[1] */
831 buf = (char *)kssl_params;
832 buf += kssl_params->kssl_certs.sc_sizes_offset;
833 bcopy(buf, &certlen, sizeof (uint32_t));
834 buf += sizeof (uint32_t);
835 for (i = 0; i < ncerts; i++) {
836 uint32_t size = (uint32_t)certs[i].certificate.Length;
837 bcopy(&size, buf, sizeof (uint32_t));
838 buf += sizeof (uint32_t);
839 }
840
841 /* Put the cert_bufs starting from sc_certs[1] */
842 buf = (char *)kssl_params;
843 buf += kssl_params->kssl_certs.sc_certs_offset;
844 buf += certlen;
845
846 /* now the certs values */
847 for (i = 0; i < ncerts; i++) {
848 bcopy(certs[i].certificate.Data, buf,
849 certs[i].certificate.Length);
850 buf += certs[i].certificate.Length;
851 }
852
853 for (i = 0; i < ncerts; i++)
854 kmf_free_kmf_cert(kmfh, &certs[i]);
855 free(certs);
856
857 return (kssl_params);
858 }
859
860 /*
861 * Find a key and certificate(s) from a single PEM file.
862 */
863 static kssl_params_t *
load_from_pem(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)864 load_from_pem(KMF_HANDLE_T kmfh, const char *filename,
865 const char *password_file, int *paramsize)
866 {
867 int ncerts = 0, i;
868 kssl_params_t *kssl_params;
869 KMF_RAW_KEY_DATA *rsa = NULL;
870 KMF_X509_DER_CERT *certs = NULL;
871
872 ncerts = PEM_get_rsa_key_certs(kmfh,
873 filename, (char *)password_file, &rsa, &certs);
874 if (rsa == NULL || certs == NULL || ncerts == 0) {
875 return (NULL);
876 }
877
878 if (verbose)
879 (void) printf("%d certificates read successfully\n", ncerts);
880
881 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
882 NULL, NULL);
883
884 for (i = 0; i < ncerts; i++)
885 kmf_free_kmf_cert(kmfh, &certs[i]);
886 free(certs);
887 kmf_free_raw_key(rsa);
888
889 return (kssl_params);
890 }
891
892 /*
893 * Load a raw key and certificate(s) from a PKCS#12 file.
894 */
895 static kssl_params_t *
load_from_pkcs12(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)896 load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename,
897 const char *password_file, int *paramsize)
898 {
899 KMF_RAW_KEY_DATA *rsa = NULL;
900 kssl_params_t *kssl_params;
901 KMF_X509_DER_CERT *certs = NULL;
902 int ncerts = 0, i;
903
904 ncerts = PKCS12_get_rsa_key_certs(kmfh, filename,
905 password_file, &rsa, &certs);
906
907 if (certs == NULL || ncerts == 0) {
908 (void) fprintf(stderr,
909 "Unable to read cert and/or key from %s\n", filename);
910 return (NULL);
911 }
912
913 if (verbose)
914 (void) printf("%d certificates read successfully\n", ncerts);
915
916 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
917 NULL, NULL);
918
919 for (i = 0; i < ncerts; i++)
920 kmf_free_kmf_cert(kmfh, &certs[i]);
921 free(certs);
922
923 kmf_free_raw_key(rsa);
924 return (kssl_params);
925 }
926
927 int
parse_and_set_addr(char * server_address,char * server_port,struct sockaddr_in6 * addr)928 parse_and_set_addr(char *server_address, char *server_port,
929 struct sockaddr_in6 *addr)
930 {
931 long long tmp_port;
932 char *ep;
933
934 if (server_port == NULL) {
935 return (-1);
936 }
937
938 if (server_address == NULL) {
939 addr->sin6_addr = in6addr_any;
940 } else {
941 struct hostent *hp;
942 int error_num;
943
944 if ((hp = (getipnodebyname(server_address, AF_INET6,
945 AI_DEFAULT, &error_num))) == NULL) {
946 (void) fprintf(stderr, "Error: Unknown host: %s\n",
947 server_address);
948 return (-1);
949 }
950
951 (void) memcpy((caddr_t)&addr->sin6_addr, hp->h_addr,
952 hp->h_length);
953 freehostent(hp);
954 }
955
956 errno = 0;
957 tmp_port = strtoll(server_port, &ep, 10);
958 if (server_port == ep || *ep != '\0' || errno != 0) {
959 (void) fprintf(stderr, "Error: Invalid Port value: %s\n",
960 server_port);
961 return (-1);
962 }
963 if (tmp_port < 1 || tmp_port > 65535) {
964 (void) fprintf(stderr, "Error: Port out of range: %s\n",
965 server_port);
966 return (-1);
967 }
968 /* It is safe to convert since the value is inside the boundaries. */
969 addr->sin6_port = tmp_port;
970
971 return (0);
972 }
973
974 /*
975 * The order of the ciphers is important. It is used as the
976 * default order (when -c is not specified).
977 */
978 struct csuite {
979 const char *suite;
980 uint16_t val;
981 boolean_t seen;
982 } cipher_suites[CIPHER_SUITE_COUNT - 1] = {
983 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
984 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
985 {"rsa_aes_256_cbc_sha", TLS_RSA_WITH_AES_256_CBC_SHA, B_FALSE},
986 {"rsa_aes_128_cbc_sha", TLS_RSA_WITH_AES_128_CBC_SHA, B_FALSE},
987 {"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
988 {"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
989 };
990
991 static int
check_suites(char * suites,uint16_t * sarray)992 check_suites(char *suites, uint16_t *sarray)
993 {
994 int i;
995 int err = 0;
996 char *suite;
997 int sindx = 0;
998
999 if (suites != NULL) {
1000 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1001 sarray[i] = CIPHER_NOTSET;
1002 } else {
1003 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1004 sarray[i] = cipher_suites[i].val;
1005 return (err);
1006 }
1007
1008 suite = strtok(suites, ",");
1009 do {
1010 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
1011 if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
1012 if (!cipher_suites[i].seen) {
1013 sarray[sindx++] = cipher_suites[i].val;
1014 cipher_suites[i].seen = B_TRUE;
1015 }
1016 break;
1017 }
1018 }
1019
1020 if (i == (CIPHER_SUITE_COUNT - 1)) {
1021 (void) fprintf(stderr,
1022 "Unknown Cipher suite name: %s\n", suite);
1023 err++;
1024 }
1025 } while ((suite = strtok(NULL, ",")) != NULL);
1026
1027 return (err);
1028 }
1029
1030 int
do_create(int argc,char * argv[])1031 do_create(int argc, char *argv[])
1032 {
1033 const char *softtoken_dir = NULL;
1034 const char *token_label = NULL;
1035 const char *password_file = NULL;
1036 const char *cert_key_file = NULL;
1037 const char *cacert_chain_file = NULL;
1038 const char *certname = NULL;
1039 char *suites = NULL;
1040 uint32_t timeout = DEFAULT_SID_TIMEOUT;
1041 uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
1042 uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
1043 int proxy_port = -1;
1044 struct sockaddr_in6 server_addr;
1045 char *format = NULL;
1046 char *port, *addr;
1047 char c;
1048 int pcnt;
1049 kssl_params_t *kssl_params;
1050 int bufsize;
1051 KMF_HANDLE_T kmfh = NULL;
1052 KMF_RETURN rv = KMF_OK;
1053 char *err = NULL;
1054
1055 argc -= 1;
1056 argv += 1;
1057
1058 while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
1059 switch (c) {
1060 case 'd':
1061 softtoken_dir = optarg;
1062 break;
1063 case 'c':
1064 suites = optarg;
1065 break;
1066 case 'C':
1067 certname = optarg;
1068 break;
1069 case 'f':
1070 format = optarg;
1071 break;
1072 case 'h':
1073 cacert_chain_file = optarg;
1074 break;
1075 case 'i':
1076 cert_key_file = optarg;
1077 break;
1078 case 'T':
1079 token_label = optarg;
1080 break;
1081 case 'p':
1082 password_file = optarg;
1083 break;
1084 case 't':
1085 timeout = atoi(optarg);
1086 break;
1087 case 'x':
1088 proxy_port = atoi(optarg);
1089 break;
1090 case 'v':
1091 verbose = B_TRUE;
1092 break;
1093 case 'z':
1094 scache_size = atoi(optarg);
1095 break;
1096 default:
1097 goto err;
1098 }
1099 }
1100
1101 pcnt = argc - optind;
1102 if (pcnt == 0) {
1103 port = "443"; /* default SSL port */
1104 addr = NULL;
1105 } else if (pcnt == 1) {
1106 port = argv[optind];
1107 addr = NULL;
1108 } else if (pcnt == 2) {
1109 addr = argv[optind];
1110 port = argv[optind + 1];
1111 } else {
1112 goto err;
1113 }
1114
1115 if (parse_and_set_addr(addr, port, &server_addr) < 0) {
1116 goto err;
1117 }
1118
1119 if (verbose) {
1120 char buffer[128];
1121
1122 (void) inet_ntop(AF_INET6, &server_addr.sin6_addr, buffer,
1123 sizeof (buffer));
1124 (void) printf("addr = %s, port = %d\n", buffer,
1125 server_addr.sin6_port);
1126 }
1127
1128 if (format == NULL || proxy_port == -1) {
1129 goto err;
1130 }
1131
1132 if (check_suites(suites, kssl_suites) != 0) {
1133 goto err;
1134 }
1135
1136 rv = kmf_initialize(&kmfh, NULL, NULL);
1137 if (rv != KMF_OK) {
1138 REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
1139 return (0);
1140 }
1141
1142 if (strcmp(format, "pkcs11") == 0) {
1143 if (token_label == NULL || certname == NULL) {
1144 goto err;
1145 }
1146 if (softtoken_dir != NULL) {
1147 (void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
1148 if (verbose) {
1149 (void) printf(
1150 "SOFTTOKEN_DIR=%s\n",
1151 getenv("SOFTTOKEN_DIR"));
1152 }
1153 }
1154 kssl_params = load_from_pkcs11(kmfh,
1155 token_label, password_file, certname, &bufsize);
1156 } else if (strcmp(format, "pkcs12") == 0) {
1157 if (cert_key_file == NULL) {
1158 goto err;
1159 }
1160 kssl_params = load_from_pkcs12(kmfh,
1161 cert_key_file, password_file, &bufsize);
1162 } else if (strcmp(format, "pem") == 0) {
1163 if (cert_key_file == NULL) {
1164 goto err;
1165 }
1166 kssl_params = load_from_pem(kmfh,
1167 cert_key_file, password_file, &bufsize);
1168 } else {
1169 (void) fprintf(stderr, "Unsupported cert format: %s\n", format);
1170 goto err;
1171 }
1172
1173 if (kssl_params == NULL) {
1174 (void) kmf_finalize(kmfh);
1175 return (FAILURE);
1176 }
1177
1178 /*
1179 * Add the list of supported ciphers to the buffer.
1180 */
1181 bcopy(kssl_suites, kssl_params->kssl_suites,
1182 sizeof (kssl_params->kssl_suites));
1183 kssl_params->kssl_params_size = bufsize;
1184 kssl_params->kssl_addr = server_addr;
1185 kssl_params->kssl_session_cache_timeout = timeout;
1186 kssl_params->kssl_proxy_port = proxy_port;
1187 kssl_params->kssl_session_cache_size = scache_size;
1188
1189 if (cacert_chain_file != NULL) {
1190 kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file);
1191 if (kssl_params == NULL) {
1192 bzero(kssl_params, bufsize);
1193 free(kssl_params);
1194 (void) kmf_finalize(kmfh);
1195 return (FAILURE);
1196 }
1197 }
1198
1199 if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
1200 int err = CRYPTO_FAILED;
1201
1202 if (kssl_params->kssl_is_nxkey)
1203 err = kssl_params->kssl_token.ck_rv;
1204 (void) fprintf(stderr,
1205 "Error loading cert and key: 0x%x\n", err);
1206 bzero(kssl_params, bufsize);
1207 free(kssl_params);
1208 (void) kmf_finalize(kmfh);
1209 return (FAILURE);
1210 }
1211
1212 if (verbose)
1213 (void) printf("Successfully loaded cert and key\n");
1214
1215 bzero(kssl_params, bufsize);
1216 free(kssl_params);
1217 (void) kmf_finalize(kmfh);
1218 return (SUCCESS);
1219
1220 err:
1221 usage_create(B_TRUE);
1222 (void) kmf_finalize(kmfh);
1223 return (SMF_EXIT_ERR_CONFIG);
1224 }
1225