View | Details | Raw Unified | Return to bug 1371 | Differences between
and this patch

Collapse All | Expand All

(-)ssh/pkcs11.c (+845 lines)
Line 0 Link Here
1
/*
2
 * Copyright(c) 2005-2008 Alon Bar-Lev.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#ifdef ENABLE_PKCS11
26
27
#include <string.h>
28
#include <unistd.h>
29
#include <sys/wait.h>
30
#include <errno.h>
31
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
32
#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
33
#include "openssl/pem.h"
34
#include "misc.h"
35
#include "buffer.h"
36
#include "xmalloc.h"
37
#include "log.h"
38
#include "uuencode.h"
39
#include "pkcs11.h"
40
41
static char *
42
ssh_from_x509(X509 *);
43
44
static time_t
45
mytime(void)
46
{
47
	return time(NULL);
48
}
49
50
static void
51
mysleep(const unsigned long usec)
52
{
53
	usleep((unsigned)usec);
54
}
55
56
static int
57
mygettimeofday(struct timeval *tv)
58
{
59
	return gettimeofday(tv, NULL);
60
}
61
62
static pkcs11h_engine_system_t s_pkcs11h_sys_engine = {
63
	xmalloc,
64
	xfree,
65
	mytime,
66
	mysleep,
67
	mygettimeofday
68
};
69
70
static LogLevel
71
pkcs11_msg_pkcs112openssh(const unsigned flags)
72
{
73
	LogLevel openssh_flags;
74
75
	switch (flags) {
76
	case PKCS11H_LOG_DEBUG2:
77
		openssh_flags = SYSLOG_LEVEL_DEBUG3;
78
		break;
79
	case PKCS11H_LOG_DEBUG1:
80
		openssh_flags = SYSLOG_LEVEL_DEBUG2;
81
		break;
82
	case PKCS11H_LOG_INFO:
83
		openssh_flags = SYSLOG_LEVEL_INFO;
84
		break;
85
	case PKCS11H_LOG_WARN:
86
		openssh_flags = SYSLOG_LEVEL_ERROR;
87
		break;
88
	case PKCS11H_LOG_ERROR:
89
		openssh_flags = SYSLOG_LEVEL_FATAL;
90
		break;
91
	default:
92
		openssh_flags = SYSLOG_LEVEL_FATAL;
93
		break;
94
	}
95
96
	return openssh_flags;
97
}
98
99
static unsigned
100
pkcs11_msg_openssh2pkcs11(const LogLevel flags)
101
{
102
	unsigned pkcs11_flags;
103
104
	switch (flags) {
105
	case SYSLOG_LEVEL_DEBUG3:
106
		pkcs11_flags = PKCS11H_LOG_DEBUG2;
107
		break;
108
	case SYSLOG_LEVEL_DEBUG2:
109
		pkcs11_flags = PKCS11H_LOG_DEBUG1;
110
		break;
111
	case SYSLOG_LEVEL_INFO:
112
		pkcs11_flags = PKCS11H_LOG_INFO;
113
		break;
114
	case SYSLOG_LEVEL_ERROR:
115
		pkcs11_flags = PKCS11H_LOG_WARN;
116
		break;
117
	case SYSLOG_LEVEL_FATAL:
118
		pkcs11_flags = PKCS11H_LOG_ERROR;
119
		break;
120
	default:
121
		pkcs11_flags = PKCS11H_LOG_ERROR;
122
		break;
123
	}
124
125
	return pkcs11_flags;
126
}
127
128
/* ARGSUSED */
129
static void
130
pkcs11_openssh_log(void *const global_data, unsigned flags,
131
	const char *const format, va_list args)
132
{
133
	do_log(pkcs11_msg_pkcs112openssh(flags), format, args);
134
}
135
136
/* ARGSUSED */
137
static PKCS11H_BOOL
138
pkcs11_ssh_token_prompt(void *const global_data,
139
	void *const user_data,
140
	const pkcs11h_token_id_t token, IN const unsigned retry)
141
{
142
	return ask_permission("Please insert token '%s'", token->display);
143
}
144
145
/* ARGSUSED */
146
static PKCS11H_BOOL
147
_pkcs11_ssh_pin_prompt(void *const global_data,
148
	void *const user_data, const pkcs11h_token_id_t token,
149
	const unsigned retry, char *const pin, const size_t pin_max)
150
{
151
	char prompt[1024];
152
	char *passphrase = NULL;
153
	PKCS11H_BOOL ret = FALSE;
154
155
	if (snprintf(prompt, sizeof(prompt), "Please enter PIN for token '%s': ",
156
		token->display) < 0)
157
		goto cleanup;
158
159
	passphrase = read_passphrase(prompt, RP_ALLOW_EOF);
160
161
	if (passphrase == NULL || strlen(passphrase) == 0 ||
162
		strlen(passphrase) > pin_max-1)
163
		goto cleanup;
164
	
165
	strlcpy(pin, passphrase, pin_max);
166
	bzero(passphrase, strlen(passphrase));
167
168
	ret = TRUE;
169
170
cleanup:
171
172
	if (passphrase != NULL)
173
		xfree(passphrase);
174
175
	return ret;
176
}
177
178
static int
179
pkcs11_convert_to_ssh_key(const pkcs11h_certificate_id_t certificate_id, Key **const key,
180
	char **const comment, const int pin_cache_period)
181
{
182
	pkcs11h_certificate_t certificate = NULL;
183
	pkcs11h_certificate_id_t certificate_id_new = NULL;
184
	pkcs11h_openssl_session_t openssl_session = NULL;
185
	Key *internal_key = NULL;
186
	char *internal_comment = NULL;
187
	RSA *rsa = NULL;
188
	size_t temp;
189
	CK_RV rv = CKR_OK;
190
191
	*key = NULL;
192
	*comment = NULL;
193
194
	debug3("PKCS#11: pkcs11_convert_to_ssh_key - entered - certificate=%p, "
195
		"key=%p, comment=%p, pin_cache_period=%d", (void *) certificate,
196
		(void *) key, (void *) comment, pin_cache_period);
197
198
	if ((rv = pkcs11h_certificate_create(certificate_id, NULL,
199
		PKCS11H_PROMPT_MASK_ALLOW_ALL, pin_cache_period,
200
		&certificate)) != CKR_OK) {
201
		error("PKCS#11: Cannot get certificate %ld-'%s'", rv,
202
			pkcs11h_getMessage(rv));
203
		goto cleanup;
204
	}
205
206
	/*
207
	 * New certificate_id is constructed from certificate
208
	 * blob so that it will contian the proper description.
209
	 */
210
211
	if ((rv = pkcs11h_certificate_getCertificateBlob(certificate,
212
				NULL, &temp)) != CKR_OK) {
213
		error("PKCS#11: Cannot get certificate blob %ld-'%s'", rv,
214
			pkcs11h_getMessage(rv));
215
		goto cleanup;
216
	}
217
218
	if ((rv = pkcs11h_certificate_getCertificateId(certificate,
219
		&certificate_id_new)) != CKR_OK) {
220
		error("PKCS#11: Cannot get certificate_id %ld-'%s'", rv,
221
			pkcs11h_getMessage(rv));
222
		goto cleanup;
223
	}
224
225
	if ((internal_comment = xstrdup(certificate_id_new->displayName)) == NULL) {
226
		error("PKCS#11: Memory allocation error");
227
		goto cleanup;
228
	}
229
230
	if ((openssl_session =
231
			pkcs11h_openssl_createSession(certificate)) == NULL) {
232
		error("PKCS#11: Cannot initialize openssl session");
233
		goto cleanup;
234
	}
235
236
	/*
237
	 * will be release by openssl_session
238
	 */
239
	certificate = NULL;
240
241
	if ((rsa = pkcs11h_openssl_session_getRSA(openssl_session)) == NULL) {
242
		error("PKCS#11: Unable get rsa object");
243
		goto cleanup;
244
	}
245
246
	internal_key = key_new_private(KEY_UNSPEC);
247
	internal_key->flags |= KEY_FLAG_EXT;
248
	internal_key->rsa = rsa;
249
	rsa = NULL;
250
	internal_key->type = KEY_RSA;
251
252
	*key = internal_key;
253
	internal_key = NULL;
254
	*comment = internal_comment;
255
	internal_comment = NULL;
256
257
cleanup:
258
	if (internal_key != NULL) {
259
		key_free(internal_key);
260
		internal_key = NULL;
261
	}
262
263
	if (internal_comment != NULL) {
264
		xfree(internal_comment);
265
		internal_comment = NULL;
266
	}
267
268
	if (rsa != NULL) {
269
		RSA_free (rsa);
270
		rsa = NULL;
271
	}
272
273
	if (openssl_session != NULL) {
274
		pkcs11h_openssl_freeSession(openssl_session);
275
		openssl_session = NULL;
276
	}
277
278
	if (certificate_id_new != NULL) {
279
		pkcs11h_certificate_freeCertificateId(certificate_id_new);
280
		certificate_id_new = NULL;
281
	}
282
283
	if (certificate != NULL) {
284
		pkcs11h_certificate_freeCertificate(certificate);
285
		certificate = NULL;
286
	}
287
288
	debug3("PKCS#11: pkcs11_convert_to_ssh_key - return *key=%p", (void *) *key);
289
290
	return *key != NULL;
291
}
292
293
int
294
pkcs11_initialize(const int protected_authentication, const int pin_cache_period)
295
{
296
	CK_RV rv = CKR_FUNCTION_FAILED;
297
298
	debug3("PKCS#11: pkcs11_initialize - entered protected_authentication=%d, "
299
		"pin_cache_period=%d", protected_authentication, pin_cache_period);
300
301
	if ((rv = pkcs11h_engine_setSystem(&s_pkcs11h_sys_engine)) != CKR_OK) {
302
		error("PKCS#11: Cannot set system engine %ld-'%s'", rv,
303
			pkcs11h_getMessage(rv));
304
		goto cleanup;
305
	}
306
307
	if ((rv = pkcs11h_initialize()) != CKR_OK) {
308
		error("PKCS#11: Cannot initialize %ld-'%s'", rv,
309
			pkcs11h_getMessage(rv));
310
		goto cleanup;
311
	}
312
313
	if ((rv = pkcs11h_setLogHook(pkcs11_openssh_log, NULL)) != CKR_OK) {
314
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
315
			pkcs11h_getMessage(rv));
316
		goto cleanup;
317
	}
318
319
	pkcs11h_setLogLevel(pkcs11_msg_openssh2pkcs11(get_log_level ()));
320
321
	if ((rv = pkcs11h_setTokenPromptHook(pkcs11_ssh_token_prompt,
322
		NULL)) != CKR_OK) {
323
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
324
			pkcs11h_getMessage(rv));
325
		goto cleanup;
326
	}
327
328
	if ((rv = pkcs11h_setPINPromptHook(_pkcs11_ssh_pin_prompt,
329
		NULL)) != CKR_OK) {
330
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
331
			pkcs11h_getMessage(rv));
332
		goto cleanup;
333
	}
334
335
	if ((rv = pkcs11h_setProtectedAuthentication(protected_authentication)) !=
336
		CKR_OK) {
337
		error("PKCS#11: Cannot set protected authentication mode %ld-'%s'",
338
			rv, pkcs11h_getMessage(rv));
339
		goto cleanup;
340
	}
341
342
	if ((rv = pkcs11h_setPINCachePeriod(pin_cache_period)) != CKR_OK) {
343
		error("PKCS#11: Cannot set PIN cache period %ld-'%s'", rv,
344
			pkcs11h_getMessage(rv));
345
		goto cleanup;
346
	}
347
348
	rv = CKR_OK;
349
350
cleanup:
351
	debug3("PKCS#11: pkcs11_initialize - return rv=%ld-'%s'",
352
		rv, pkcs11h_getMessage(rv));
353
354
	return rv == CKR_OK;
355
}
356
357
void
358
pkcs11_terminate(void)
359
{
360
	debug3("PKCS#11: pkcs11_terminate - entered");
361
362
	pkcs11h_terminate();
363
364
	debug3("PKCS#11: pkcs11_terminate - return");
365
}
366
367
void
368
pkcs11_free_provider(pkcs11_provider *const provider) {
369
	if (provider != NULL) {
370
		if (provider->provider != NULL)
371
			xfree(provider->provider);
372
		xfree(provider);
373
	}
374
}
375
376
pkcs11_provider *
377
pkcs11_parse_provider(const char *const info)
378
{
379
	pkcs11_provider *provider = NULL;
380
	pkcs11_provider *ret = NULL;
381
	char *split[4];
382
	char *s = NULL;
383
	char *p;
384
	int i;
385
386
	if (info == NULL)
387
		goto cleanup;
388
389
	if ((provider = (pkcs11_provider *) xmalloc(sizeof(*provider))) == NULL)
390
		goto cleanup;
391
392
	memset(provider, 0, sizeof(*provider));
393
	memset(split, 0, sizeof(split));
394
395
	if ((s=xstrdup(info)) == NULL)
396
		goto cleanup;
397
398
	p = s;
399
	i=0;
400
	while(i<4 && p != NULL) {
401
		char *t;
402
		if ((t = strchr(p, ':')) != NULL)
403
			*t = '\x0';
404
		split[i++] = p;
405
		if (t != NULL)
406
			p = t+1;
407
		else
408
			p = NULL;
409
	}
410
411
	/*
412
	 * provider[:protected_authentication[:private_mode[:cert_is_private]]]
413
	 * string:1|0:hex:1|0
414
	 */
415
	if (split[0] != NULL)
416
		provider->provider = xstrdup(split[0]);
417
	if (split[1] != NULL)
418
		provider->protected_authentication = atoi(split[1]) != 0;
419
	if (split[2] != NULL)
420
		sscanf(split[2], "%x", &provider->private_mode);
421
	if (split[3] != NULL)
422
		provider->cert_is_private = atoi(split[3]) != 0;
423
	
424
	if (provider->provider == NULL || strlen(provider->provider) == 0)
425
		goto cleanup;
426
427
	ret = provider;
428
	provider = NULL;
429
430
cleanup:
431
	if (s != NULL)
432
		xfree(s);
433
434
	if (provider != NULL)
435
		pkcs11_free_provider(provider);
436
437
	return ret;
438
}
439
440
int
441
pkcs11_add_provider(const pkcs11_provider *const provider)
442
{
443
	CK_RV rv = CKR_OK;
444
445
	debug3("PKCS#11: pkcs11_add_provider - entered - provider='%s', "
446
		"protected_authentication=%d, private_mode='%08x', cert_is_private=%d",
447
		provider->provider, provider->protected_authentication ? 1 : 0,
448
		provider->private_mode,	provider->cert_is_private ? 1 : 0);
449
450
	debug("PKCS#11: Adding PKCS#11 provider '%s'", provider->provider);
451
452
	if (rv == CKR_OK &&
453
		(rv = pkcs11h_addProvider(provider->provider, provider->provider,
454
			provider->protected_authentication, provider->private_mode,
455
				PKCS11H_SLOTEVENT_METHOD_AUTO,
456
				0, provider->cert_is_private)) != CKR_OK) {
457
		error("PKCS#11: Cannot initialize provider '%s' %ld-'%s'",
458
			provider->provider, rv, pkcs11h_getMessage(rv));
459
	}
460
461
	debug3("PKCS#11: pkcs11_add_provider - return rv=%ld-'%s'",
462
		rv, pkcs11h_getMessage(rv));
463
464
	return rv == CKR_OK;
465
}
466
467
pkcs11_id *
468
pkcs11_id_new(void)
469
{
470
	pkcs11_id *id = (pkcs11_id *) xmalloc(sizeof(*id));
471
	if (id != NULL) {
472
		memset(id, 0, sizeof(*id));
473
		id->pin_cache_period = PKCS11H_PIN_CACHE_INFINITE;
474
	}
475
	return id;
476
}
477
478
void
479
pkcs11_id_free(pkcs11_id *const id)
480
{
481
	if (id != NULL)
482
		xfree(id);
483
}
484
485
int
486
pkcs11_get_key(const pkcs11_id *const id, Key **const key,
487
	char **const comment)
488
{
489
	pkcs11h_certificate_id_t certificate_id = NULL;
490
	CK_RV rv = CKR_OK;
491
492
	debug3("PKCS#11: pkcs11_get_key - entered - id=%p, key=%p, "
493
		"comment=%p", (const void *) id, (void *) key, (void *) comment);
494
495
	debug3("PKCS#11: pkcs11_get_key - id - id=%s, "
496
		"pin_cache_period=%d, cert_file=%s",
497
		id->id, id->pin_cache_period, id->cert_file);
498
499
	if (pkcs11h_certificate_deserializeCertificateId(&certificate_id, id->id)) {
500
		error("PKCS#11: Cannot deserialize id %ld-'%s'", rv,
501
			pkcs11h_getMessage(rv));
502
		goto cleanup;
503
	}
504
505
	if (id->cert_file != NULL && id->cert_file[0] != '\x0') {
506
		X509 *x509 = NULL;
507
		unsigned char *p = NULL;
508
		unsigned char *certificate_blob = NULL;
509
		size_t certificate_blob_size = 0;
510
		int size;
511
		FILE *fp = NULL;
512
513
		if ((fp = fopen(id->cert_file, "r")) == NULL) {
514
			error("PKCS#11: Cannot open file '%s'", id->cert_file);
515
			goto cleanup1;
516
		}
517
518
		if (!PEM_read_X509(fp, &x509, NULL, 0)) {
519
			x509 = NULL;
520
			error("PKCS#11: Cannot read PEM from file '%s'", id->cert_file);
521
			goto cleanup1;
522
		}
523
524
		if ((size = i2d_X509(x509, NULL)) < 0) {
525
			error("PKCS#11: Cannot read decode certificate");
526
			goto cleanup1;
527
		}
528
		certificate_blob_size = (size_t)size;
529
530
		if ((certificate_blob =
531
				(unsigned char *) xmalloc(certificate_blob_size)) == NULL) {
532
			error("PKCS#11: Cannot allocate memory");
533
			goto cleanup1;
534
		}
535
536
		/*
537
		 * i2d_X509 increments p!!!
538
		 */
539
		p = certificate_blob;
540
541
		if ((size = i2d_X509(x509, &p)) < 0) {
542
			error("PKCS#11: Cannot read decode certificate");
543
			goto cleanup1;
544
		}
545
		certificate_blob_size = (size_t)size;
546
547
		if (pkcs11h_certificate_setCertificateIdCertificateBlob
548
			(certificate_id, certificate_blob, certificate_blob_size)
549
			!= CKR_OK) {
550
			error("PKCS#11: Cannot set certificate blob %ld-'%s'", rv,
551
				pkcs11h_getMessage(rv));
552
			goto cleanup1;
553
		}
554
555
	cleanup1:
556
		if (x509 != NULL) {
557
			X509_free(x509);
558
			x509 = NULL;
559
		}
560
561
		if (certificate_blob != NULL) {
562
			xfree(certificate_blob);
563
			certificate_blob = NULL;
564
		}
565
566
		if (fp != NULL) {
567
			fclose(fp);
568
			fp = NULL;
569
		}
570
	}
571
572
	pkcs11_convert_to_ssh_key(certificate_id, key, comment, id->pin_cache_period);
573
574
cleanup:
575
576
	if (certificate_id != NULL) {
577
		pkcs11h_certificate_freeCertificateId(certificate_id);
578
		certificate_id = NULL;
579
	}
580
581
	debug3("PKCS#11: pkcs11_get_key - return rv=%ld, *key=%p", rv, ( void *) *key);
582
583
	return *key != NULL;
584
}
585
586
int
587
pkcs11_get_keys(Key ***const keys, char ***const comments)
588
{
589
#define PKCS11_MAX_KEYS 10
590
	Key **internal_keys = NULL;
591
	char **internal_comments = NULL;
592
	pkcs11h_certificate_id_list_t user_certificates = NULL;
593
	pkcs11h_certificate_id_list_t current = NULL;
594
	CK_RV rv = CKR_FUNCTION_FAILED;
595
	int i;
596
597
	debug3("PKCS#11: pkcs11_get_keys - entered - sshkey=%p, "
598
		"comment=%p",
599
		(void *) keys, (void *) comments);
600
	
601
	*keys = NULL;
602
	*comments = NULL;
603
	
604
	if((internal_keys = (Key **) xcalloc(sizeof(*internal_keys), PKCS11_MAX_KEYS+1)) == NULL) {
605
		rv = CKR_HOST_MEMORY;
606
		goto cleanup;
607
	}
608
609
	if((internal_comments = (char **) xcalloc(sizeof(*internal_comments), PKCS11_MAX_KEYS+1)) == NULL) {
610
		rv = CKR_HOST_MEMORY;
611
		goto cleanup;
612
	}
613
614
	memset(internal_keys, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_keys));
615
	memset(internal_comments, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_comments));
616
617
	if ((rv = pkcs11h_certificate_enumCertificateIds(
618
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
619
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
620
		&user_certificates)) != CKR_OK) {
621
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
622
			pkcs11h_getMessage(rv));
623
		goto cleanup;
624
	}
625
626
	i = 0;
627
	for (current = user_certificates; current != NULL && i<PKCS11_MAX_KEYS;
628
		current = current->next) {
629
630
		if (pkcs11_convert_to_ssh_key(current->certificate_id, &internal_keys[i],
631
			&internal_comments[i], PKCS11H_PIN_CACHE_INFINITE)) {
632
			i++;
633
		}
634
	}
635
636
	*keys = internal_keys;
637
	internal_keys = NULL;
638
	*comments = internal_comments;
639
	internal_comments = NULL;
640
	rv = CKR_OK;
641
642
cleanup:
643
	if (user_certificates != NULL) {
644
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
645
		user_certificates = NULL;
646
	}
647
648
	if (internal_keys != NULL) {
649
		Key **t = internal_keys;
650
		while (*t != NULL) {
651
			key_free(*t);
652
			t++;
653
		}
654
		xfree(internal_keys);
655
	}
656
657
	if (internal_comments != NULL) {
658
		char **t = internal_comments;
659
		while (*t != NULL) {
660
			xfree(*t);
661
			t++;
662
		}
663
		xfree(internal_comments);
664
	}
665
666
	debug3("PKCS#11: pkcs11_get_keys - return rv=%ld, *keys=%p", rv, (void *) *keys);
667
668
	return *keys != NULL;
669
#undef PKCS11_MAX_KEYS
670
}
671
672
void
673
pkcs11_show_ids(void)
674
{
675
	pkcs11h_certificate_id_list_t user_certificates = NULL;
676
	pkcs11h_certificate_id_list_t current = NULL;
677
	CK_RV rv = CKR_FUNCTION_FAILED;
678
679
	if ((rv = pkcs11h_certificate_enumCertificateIds(
680
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
681
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
682
		&user_certificates)) != CKR_OK) {
683
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
684
			pkcs11h_getMessage(rv));
685
		goto cleanup;
686
	}
687
688
	for (current = user_certificates; current != NULL;
689
		current = current->next) {
690
691
		pkcs11h_certificate_t certificate = NULL;
692
		X509 *x509 = NULL;
693
694
		BIO *bio = NULL;
695
		char dn[1024] = { 0 };
696
		char serial[1024] = { 0 };
697
		char *ser = NULL;
698
		char *ssh_key = NULL;
699
		size_t ser_len = 0;
700
		int n;
701
702
		if ((rv = pkcs11h_certificate_serializeCertificateId(NULL,
703
			&ser_len, current->certificate_id)) != CKR_OK) {
704
			error("PKCS#11: Cannot serialize certificate id "
705
				"certificates %ld-'%s'", rv,
706
				pkcs11h_getMessage(rv));
707
			goto cleanup1;
708
		}
709
710
		if ((ser = (char *) xmalloc(ser_len)) == NULL) {
711
			error("PKCS#11: Cannot allocate memory");
712
			goto cleanup1;
713
		}
714
715
		if ((rv = pkcs11h_certificate_serializeCertificateId(ser,
716
			&ser_len, current->certificate_id)) != CKR_OK) {
717
			error("PKCS#11: Cannot serialize certificate "
718
				"id certificates %ld-'%s'",
719
				rv, pkcs11h_getMessage(rv));
720
			goto cleanup1;
721
		}
722
723
		if ((rv = pkcs11h_certificate_create(current->certificate_id,
724
			NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
725
			PKCS11H_PIN_CACHE_INFINITE, &certificate)) != CKR_OK) {
726
			error("PKCS#11: Cannot create certificate %ld-'%s'", rv,
727
				pkcs11h_getMessage(rv));
728
			goto cleanup1;
729
		}
730
731
		if ((x509 = pkcs11h_openssl_getX509(certificate)) == NULL) {
732
			error("PKCS#11: Cannot get X509");
733
			goto cleanup1;
734
		}
735
736
		X509_NAME_oneline(X509_get_subject_name(x509), dn, sizeof(dn));
737
738
		if ((bio = BIO_new(BIO_s_mem())) == NULL) {
739
			error("PKCS#11: Cannot create BIO");
740
			goto cleanup1;
741
		}
742
743
		i2a_ASN1_INTEGER(bio, X509_get_serialNumber(x509));
744
		n = BIO_read(bio, serial, sizeof(serial) - 1);
745
		if (n < 0)
746
			serial[0] = '\x0';
747
		else
748
			serial[n] = 0;
749
750
		printf(("\n"
751
				"********************************************\n"
752
				"IDENTITY:\n"
753
				"       DN:             %s\n"
754
				"       Serial:         %s\n"
755
				"       Serialized id:  %s\n"
756
				"\n" "       Certificate:\n"), dn, serial, ser);
757
		PEM_write_X509(stdout, x509);
758
759
		if ((ssh_key = ssh_from_x509(x509)) != NULL) {
760
			printf(("\n" "        SSH:\n" "%s\n"), ssh_key);
761
762
			xfree(ssh_key);
763
		}
764
765
	cleanup1:
766
		if (x509 != NULL) {
767
			X509_free(x509);
768
			x509 = NULL;
769
		}
770
771
		if (bio != NULL) {
772
			BIO_free_all(bio);
773
			bio = NULL;
774
		}
775
776
		if (certificate != NULL) {
777
			pkcs11h_certificate_freeCertificate(certificate);
778
			certificate = NULL;
779
		}
780
781
		if (ser != NULL) {
782
			xfree(ser);
783
			ser = NULL;
784
		}
785
	}
786
787
cleanup:
788
	if (user_certificates != NULL) {
789
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
790
		user_certificates = NULL;
791
	}
792
}
793
794
static char *
795
ssh_from_x509(X509 * x509)
796
{
797
	Buffer b;
798
	EVP_PKEY *pubkey = NULL;
799
	char *ret = NULL;
800
	size_t retsize = 0;
801
	const char *keyname = "ssh-rsa";
802
	int ok = 0;
803
804
	buffer_init(&b);
805
806
	if ((pubkey = X509_get_pubkey(x509)) == NULL)
807
		goto cleanup;
808
809
	if (pubkey->type != EVP_PKEY_RSA)
810
		goto cleanup;
811
812
	buffer_put_cstring(&b, keyname);
813
	buffer_put_bignum2(&b, pubkey->pkey.rsa->e);
814
	buffer_put_bignum2(&b, pubkey->pkey.rsa->n);
815
816
	/* be on the safe side, each byte=4 + 4 suffix + null terminate + keyname */
817
	retsize = buffer_len(&b)*4+4+1+strlen(keyname)+1;
818
	if ((ret = (char *) xmalloc(retsize)) == NULL)
819
		goto cleanup;
820
	snprintf(ret, retsize, "%s ", keyname);
821
	if (uuencode(buffer_ptr(&b), buffer_len(&b), ret+strlen(ret), retsize-strlen(ret)) == -1)
822
		goto cleanup;
823
824
	ok = 1;
825
826
cleanup:
827
828
	if (pubkey != NULL) {
829
		EVP_PKEY_free(pubkey);
830
		pubkey = NULL;
831
	}
832
833
	buffer_free(&b);
834
835
	if (!ok) {
836
		if (ret != NULL) {
837
			xfree(ret);
838
			ret = NULL;
839
		}
840
	}
841
842
	return ret;
843
}
844
845
#endif /* ENABLE_PKCS11 */
(-)ssh/pkcs11.h (+77 lines)
Line 0 Link Here
1
/*
2
 * Copyright (c) 2005-2008 Alon Bar-Lev.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#ifndef SSH_PKCS11_H
26
#define SSH_PKCS11_H
27
28
#ifdef ENABLE_PKCS11
29
30
#include "key.h"
31
32
typedef struct {
33
	char *provider;
34
	int protected_authentication;
35
	unsigned private_mode;
36
	int cert_is_private;
37
} pkcs11_provider;
38
39
typedef struct {
40
	char *id;
41
	int pin_cache_period;
42
	char *cert_file;
43
} pkcs11_id;
44
45
int
46
pkcs11_initialize(const int, const int);
47
48
void
49
pkcs11_terminate(void);
50
51
void
52
pkcs11_free_provider(pkcs11_provider *const);
53
54
pkcs11_provider *
55
pkcs11_parse_provider(const char *const);
56
57
int
58
pkcs11_add_provider(const pkcs11_provider *const);
59
60
pkcs11_id *
61
pkcs11_id_new(void);
62
63
void
64
pkcs11_id_free(pkcs11_id *const);
65
66
int
67
pkcs11_get_key(const pkcs11_id *const, Key **const, char **const);
68
69
int
70
pkcs11_get_keys(Key ***const, char ***const);
71
72
void
73
pkcs11_show_ids(void);
74
75
#endif /* ENABLE_PKCS11 */
76
77
#endif /* OPENSSH_PKCS11_H */

Return to bug 1371