View | Details | Raw Unified | Return to bug 2075
Collapse All | Expand All

(-)a/authfile.c (-6 / +50 lines)
Lines 75-80 Link Here
75
static const char authfile_id_string[] =
75
static const char authfile_id_string[] =
76
    "SSH PRIVATE KEY FILE FORMAT 1.1\n";
76
    "SSH PRIVATE KEY FILE FORMAT 1.1\n";
77
77
78
/* Version identification string for external key identity files. */
79
static const char externalkey_id_string[] =
80
    "SSH PRIVATE KEY EXTERNAL 1.0\n";
81
78
/*
82
/*
79
 * Serialises the authentication (private) key to a blob, encrypting it with
83
 * Serialises the authentication (private) key to a blob, encrypting it with
80
 * passphrase.  The identification of the blob (lowest 64 bits of n) will
84
 * passphrase.  The identification of the blob (lowest 64 bits of n) will
Lines 214-219 key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase, Link Here
214
	return success;
218
	return success;
215
}
219
}
216
220
221
static int
222
key_private_external_to_blob(Key *key, Buffer *blob, const char *passphrase,
223
    const char *comment) {
224
	Buffer buffer;
225
	int i;
226
227
	buffer_init(&buffer);
228
229
	/* Store an identifier to identify key as being external. */
230
	for (i = 0; externalkey_id_string[i]; i++)
231
		buffer_put_char(&buffer, externalkey_id_string[i]);
232
	buffer_put_char(&buffer, 0);
233
234
	buffer_append(blob, buffer_ptr(&buffer), buffer_len(&buffer));
235
	buffer_free(&buffer);
236
237
	return 1;
238
}
239
217
/* Save a key blob to a file */
240
/* Save a key blob to a file */
218
static int
241
static int
219
key_save_private_blob(Buffer *keybuf, const char *filename)
242
key_save_private_blob(Buffer *keybuf, const char *filename)
Lines 241-246 static int Link Here
241
key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
264
key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
242
    const char *comment)
265
    const char *comment)
243
{
266
{
267
	if (key->flags & KEY_FLAG_EXT) {
268
		return key_private_external_to_blob(key, blob, passphrase, comment);
269
	}
270
244
	switch (key->type) {
271
	switch (key->type) {
245
	case KEY_RSA1:
272
	case KEY_RSA1:
246
		return key_private_rsa1_to_blob(key, blob, passphrase, comment);
273
		return key_private_rsa1_to_blob(key, blob, passphrase, comment);
Lines 609-614 key_load_private_pem(int fd, int type, const char *passphrase, Link Here
609
	return prv;
636
	return prv;
610
}
637
}
611
638
639
static int
640
key_parse_is_private_external(Buffer *blob)
641
{
642
	return (buffer_len(blob) >= sizeof(externalkey_id_string)
643
			&& memcmp(buffer_ptr(blob), externalkey_id_string,
644
			          sizeof(externalkey_id_string)) == 0);
645
}
646
612
int
647
int
613
key_perm_ok(int fd, const char *filename)
648
key_perm_ok(int fd, const char *filename)
614
{
649
{
Lines 639-646 key_perm_ok(int fd, const char *filename) Link Here
639
674
640
static Key *
675
static Key *
641
key_parse_private_type(Buffer *blob, int type, const char *passphrase,
676
key_parse_private_type(Buffer *blob, int type, const char *passphrase,
642
    char **commentp)
677
    char **commentp, int *is_external)
643
{
678
{
679
	if (key_parse_is_private_external(blob)) {
680
		// key must be loaded through other means (e.g., pkcs11 module).
681
		if (is_external != NULL) {
682
			*is_external = 1;
683
		}
684
		return NULL;
685
	}
686
644
	switch (type) {
687
	switch (type) {
645
	case KEY_RSA1:
688
	case KEY_RSA1:
646
		return key_parse_private_rsa1(blob, passphrase, commentp);
689
		return key_parse_private_rsa1(blob, passphrase, commentp);
Lines 658-664 key_parse_private_type(Buffer *blob, int type, const char *passphrase, Link Here
658
701
659
Key *
702
Key *
660
key_load_private_type(int type, const char *filename, const char *passphrase,
703
key_load_private_type(int type, const char *filename, const char *passphrase,
661
    char **commentp, int *perm_ok)
704
    char **commentp, int *perm_ok, int *is_external)
662
{
705
{
663
	int fd;
706
	int fd;
664
	Key *ret;
707
	Key *ret;
Lines 689-695 key_load_private_type(int type, const char *filename, const char *passphrase, Link Here
689
		return NULL;
732
		return NULL;
690
	}
733
	}
691
	close(fd);
734
	close(fd);
692
	ret = key_parse_private_type(&buffer, type, passphrase, commentp);
735
	ret = key_parse_private_type(&buffer, type, passphrase, commentp,
736
	    is_external);
693
	buffer_free(&buffer);
737
	buffer_free(&buffer);
694
	return ret;
738
	return ret;
695
}
739
}
Lines 704-710 key_parse_private(Buffer *buffer, const char *filename, Link Here
704
	pub = key_parse_public_rsa1(buffer, commentp);
748
	pub = key_parse_public_rsa1(buffer, commentp);
705
	if (pub == NULL) {
749
	if (pub == NULL) {
706
		prv = key_parse_private_type(buffer, KEY_UNSPEC,
750
		prv = key_parse_private_type(buffer, KEY_UNSPEC,
707
		    passphrase, NULL);
751
		    passphrase, NULL, NULL);
708
		/* use the filename as a comment for PEM */
752
		/* use the filename as a comment for PEM */
709
		if (commentp && prv)
753
		if (commentp && prv)
710
			*commentp = xstrdup(filename);
754
			*commentp = xstrdup(filename);
Lines 712-718 key_parse_private(Buffer *buffer, const char *filename, Link Here
712
		key_free(pub);
756
		key_free(pub);
713
		/* key_parse_public_rsa1() has already loaded the comment */
757
		/* key_parse_public_rsa1() has already loaded the comment */
714
		prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
758
		prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
715
		    NULL);
759
		    NULL, NULL);
716
	}
760
	}
717
	return prv;
761
	return prv;
718
}
762
}
Lines 858-864 key_load_private_cert(int type, const char *filename, const char *passphrase, Link Here
858
	}
902
	}
859
903
860
	if ((key = key_load_private_type(type, filename, 
904
	if ((key = key_load_private_type(type, filename, 
861
	    passphrase, NULL, perm_ok)) == NULL)
905
	    passphrase, NULL, perm_ok, NULL)) == NULL)
862
		return NULL;
906
		return NULL;
863
907
864
	if ((pub = key_load_cert(filename)) == NULL) {
908
	if ((pub = key_load_cert(filename)) == NULL) {
(-)a/authfile.h (-1 / +1 lines)
Lines 23-29 Key *key_load_public_type(int, const char *, char **); Link Here
23
Key	*key_parse_private(Buffer *, const char *, const char *, char **);
23
Key	*key_parse_private(Buffer *, const char *, const char *, char **);
24
Key	*key_load_private(const char *, const char *, char **);
24
Key	*key_load_private(const char *, const char *, char **);
25
Key	*key_load_private_cert(int, const char *, const char *, int *);
25
Key	*key_load_private_cert(int, const char *, const char *, int *);
26
Key	*key_load_private_type(int, const char *, const char *, char **, int *);
26
Key	*key_load_private_type(int, const char *, const char *, char **, int *, int *);
27
Key	*key_load_private_pem(int, int, const char *, char **);
27
Key	*key_load_private_pem(int, int, const char *, char **);
28
int	 key_perm_ok(int, const char *);
28
int	 key_perm_ok(int, const char *);
29
int	 key_in_file(Key *, const char *, int);
29
int	 key_in_file(Key *, const char *, int);
(-)a/ssh-keygen.1 (-1 / +12 lines)
Lines 35-41 Link Here
35
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
.\"
37
.\"
38
.Dd $Mdocdate: January 19 2013 $
38
.Dd $Mdocdate: March 6 2013 $
39
.Dt SSH-KEYGEN 1
39
.Dt SSH-KEYGEN 1
40
.Os
40
.Os
41
.Sh NAME
41
.Sh NAME
Lines 80-85 Link Here
80
.Nm ssh-keygen
80
.Nm ssh-keygen
81
.Fl D Ar pkcs11
81
.Fl D Ar pkcs11
82
.Nm ssh-keygen
82
.Nm ssh-keygen
83
.Fl d Ar pkcs11
84
.Op Fl E Ar slot_index
85
.Nm ssh-keygen
83
.Fl F Ar hostname
86
.Fl F Ar hostname
84
.Op Fl f Ar known_hosts_file
87
.Op Fl f Ar known_hosts_file
85
.Op Fl l
88
.Op Fl l
Lines 255-260 When used in combination with Link Here
255
this option indicates that a CA key resides in a PKCS#11 token (see the
258
this option indicates that a CA key resides in a PKCS#11 token (see the
256
.Sx CERTIFICATES
259
.Sx CERTIFICATES
257
section for details).
260
section for details).
261
.It Fl d Ar pkcs11
262
Generate the public / private key pair using the PKCS#11 shared library
263
.Ar pkcs11 .
264
.It Fl E Ar slot_idx
265
Specify the PKCS#11 slot index on which to generate the public / private key
266
pair when used in combination with
267
.Fl d .
268
If not specified, default is 0.
258
.It Fl e
269
.It Fl e
259
This option will read a private or public OpenSSH key file and
270
This option will read a private or public OpenSSH key file and
260
print to stdout the key in one of the formats specified by the
271
print to stdout the key in one of the formats specified by the
(-)a/ssh-keygen.c (-15 / +58 lines)
Lines 147-153 int print_generic = 0; Link Here
147
147
148
char *key_type_name = NULL;
148
char *key_type_name = NULL;
149
149
150
/* Load key from this PKCS#11 provider */
150
/* Load or insert keys from this PKCS#11 provider */
151
char *pkcs11provider = NULL;
151
char *pkcs11provider = NULL;
152
152
153
/* argv0 */
153
/* argv0 */
Lines 762-767 do_download(struct passwd *pw) Link Here
762
#endif /* ENABLE_PKCS11 */
762
#endif /* ENABLE_PKCS11 */
763
}
763
}
764
764
765
static Key *
766
do_generate_key_pkcs11(unsigned long slot_idx, int type, u_int bits,
767
    char* key_comment)
768
{
769
#ifdef ENABLE_PKCS11
770
	Key *key;
771
	char *label;
772
	xasprintf(&label, "ssh-keygen:%s", key_comment);
773
774
	pkcs11_init(1);
775
	key = pkcs11_key_generate(pkcs11provider, NULL, slot_idx, label, type, bits);
776
	pkcs11_terminate();
777
778
	xfree(label);
779
	return key;
780
#else
781
	fatal("no pkcs11 support");
782
#endif /* ENABLE_PKCS11 */
783
}
784
765
static void
785
static void
766
do_fingerprint(struct passwd *pw)
786
do_fingerprint(struct passwd *pw)
767
{
787
{
Lines 2132-2137 usage(void) Link Here
2132
	fprintf(stderr, "  -c          Change comment in private and public key files.\n");
2152
	fprintf(stderr, "  -c          Change comment in private and public key files.\n");
2133
#ifdef ENABLE_PKCS11
2153
#ifdef ENABLE_PKCS11
2134
	fprintf(stderr, "  -D pkcs11   Download public key from pkcs11 token.\n");
2154
	fprintf(stderr, "  -D pkcs11   Download public key from pkcs11 token.\n");
2155
	fprintf(stderr, "  -d pkcs11   Generate key using pkcs11 token.\n");
2156
	fprintf(stderr, "  -E slot_idx Pkcs11 slot index on which to generate key for -d (default '0').\n");
2135
#endif
2157
#endif
2136
	fprintf(stderr, "  -e          Export OpenSSH to foreign format key file.\n");
2158
	fprintf(stderr, "  -e          Export OpenSSH to foreign format key file.\n");
2137
	fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
2159
	fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
Lines 2188-2195 main(int argc, char **argv) Link Here
2188
	int opt, type, fd;
2210
	int opt, type, fd;
2189
	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
2211
	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
2190
	int do_gen_candidates = 0, do_screen_candidates = 0;
2212
	int do_gen_candidates = 0, do_screen_candidates = 0;
2213
	int do_download_pkcs11 = 0, do_gen_key_pkcs11 = 0;
2191
	int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
2214
	int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
2192
	unsigned long start_lineno = 0, lines_to_process = 0;
2215
	unsigned long start_lineno = 0, lines_to_process = 0, pkcs11_slot_idx = 0;
2193
	BIGNUM *start = NULL;
2216
	BIGNUM *start = NULL;
2194
	FILE *f;
2217
	FILE *f;
2195
	const char *errstr;
2218
	const char *errstr;
Lines 2219-2225 main(int argc, char **argv) Link Here
2219
	}
2242
	}
2220
2243
2221
	while ((opt = getopt(argc, argv, "ABHLQXceghiklpquvxy"
2244
	while ((opt = getopt(argc, argv, "ABHLQXceghiklpquvxy"
2222
	    "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
2245
	    "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:a:b:d:f:g:j:m:n:r:s:t:z:")) != -1) {
2223
		switch (opt) {
2246
		switch (opt) {
2224
		case 'A':
2247
		case 'A':
2225
			gen_all_hostkeys = 1;
2248
			gen_all_hostkeys = 1;
Lines 2337-2344 main(int argc, char **argv) Link Here
2337
			key_type_name = optarg;
2360
			key_type_name = optarg;
2338
			break;
2361
			break;
2339
		case 'D':
2362
		case 'D':
2363
			do_download_pkcs11 = 1;
2364
			pkcs11provider = optarg;
2365
			break;
2366
		case 'd':
2367
			do_gen_key_pkcs11 = 1;
2340
			pkcs11provider = optarg;
2368
			pkcs11provider = optarg;
2341
			break;
2369
			break;
2370
		case 'E':
2371
			pkcs11_slot_idx = strtoul(optarg, &ep, 10);
2372
			break;
2342
		case 'u':
2373
		case 'u':
2343
			update_krl = 1;
2374
			update_krl = 1;
2344
			break;
2375
			break;
Lines 2450-2456 main(int argc, char **argv) Link Here
2450
		do_show_cert(pw);
2481
		do_show_cert(pw);
2451
	if (delete_host || hash_hosts || find_host)
2482
	if (delete_host || hash_hosts || find_host)
2452
		do_known_hosts(pw, rr_hostname);
2483
		do_known_hosts(pw, rr_hostname);
2453
	if (pkcs11provider != NULL)
2484
	if (do_download_pkcs11)
2454
		do_download(pw);
2485
		do_download(pw);
2455
	if (print_fingerprint || print_bubblebabble)
2486
	if (print_fingerprint || print_bubblebabble)
2456
		do_fingerprint(pw);
2487
		do_fingerprint(pw);
Lines 2542-2550 main(int argc, char **argv) Link Here
2542
	type = key_type_from_name(key_type_name);
2573
	type = key_type_from_name(key_type_name);
2543
	type_bits_valid(type, &bits);
2574
	type_bits_valid(type, &bits);
2544
2575
2545
	if (!quiet)
2576
	if (identity_comment) {
2546
		printf("Generating public/private %s key pair.\n", key_type_name);
2577
		strlcpy(comment, identity_comment, sizeof(comment));
2547
	private = key_generate(type, bits);
2578
	} else {
2579
		/* Create default comment field for the passphrase. */
2580
		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
2581
	}
2582
2583
	if (do_gen_key_pkcs11) {
2584
		if (!quiet)
2585
			printf("Generating public/private %s key pair using pkcs11 token %s.\n",
2586
			    key_type_name, pkcs11provider);
2587
		private = do_generate_key_pkcs11(pkcs11_slot_idx, type, bits, comment);
2588
	} else {
2589
		if (!quiet)
2590
			printf("Generating public/private %s key pair.\n", key_type_name);
2591
		private = key_generate(type, bits);
2592
	}
2548
	if (private == NULL) {
2593
	if (private == NULL) {
2549
		fprintf(stderr, "key_generate failed\n");
2594
		fprintf(stderr, "key_generate failed\n");
2550
		exit(1);
2595
		exit(1);
Lines 2609-2621 passphrase_again: Link Here
2609
		xfree(passphrase2);
2654
		xfree(passphrase2);
2610
	}
2655
	}
2611
2656
2612
	if (identity_comment) {
2613
		strlcpy(comment, identity_comment, sizeof(comment));
2614
	} else {
2615
		/* Create default comment field for the passphrase. */
2616
		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
2617
	}
2618
2619
	/* Save the key with the given passphrase and comment. */
2657
	/* Save the key with the given passphrase and comment. */
2620
	if (!key_save_private(private, identity_file, passphrase1, comment)) {
2658
	if (!key_save_private(private, identity_file, passphrase1, comment)) {
2621
		printf("Saving the key failed: %s.\n", identity_file);
2659
		printf("Saving the key failed: %s.\n", identity_file);
Lines 2631-2638 passphrase_again: Link Here
2631
	key_free(private);
2669
	key_free(private);
2632
	arc4random_stir();
2670
	arc4random_stir();
2633
2671
2634
	if (!quiet)
2672
	if (!quiet) {
2635
		printf("Your identification has been saved in %s.\n", identity_file);
2673
		printf("Your identification has been saved in %s.\n", identity_file);
2674
		if (do_gen_key_pkcs11) {
2675
			printf("To use this identity you must configure ssh to use the the given "
2676
			    "pkcs11 provider.\n");
2677
		}
2678
	}
2636
2679
2637
	strlcat(identity_file, ".pub", sizeof(identity_file));
2680
	strlcat(identity_file, ".pub", sizeof(identity_file));
2638
	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
2681
	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
(-)a/ssh-pkcs11.c (-98 / +269 lines)
Lines 168-173 pkcs11_del_provider(char *provider_id) Link Here
168
	return (-1);
168
	return (-1);
169
}
169
}
170
170
171
static int
172
pkcs11_login(struct pkcs11_provider	*p, struct pkcs11_slotinfo	*si) {
173
	CK_FUNCTION_LIST	*f;
174
	CK_RV			rv;
175
	char			*pin, prompt[1024];
176
177
	f = p->function_list;
178
179
	if (!pkcs11_interactive) {
180
		error("need pin");
181
		return (-1);
182
	}
183
	snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
184
	    si->token.label);
185
	pin = read_passphrase(prompt, RP_ALLOW_EOF);
186
	if (pin == NULL)
187
		return (-1);	/* bail out */
188
	if ((rv = f->C_Login(si->session, CKU_USER, pin, strlen(pin)))
189
	    != CKR_OK) {
190
		xfree(pin);
191
		error("C_Login failed: %lu", rv);
192
		return (-1);
193
	}
194
	xfree(pin);
195
	si->logged_in = 1;
196
197
	return 0;
198
}
199
171
/* openssl callback for freeing an RSA key */
200
/* openssl callback for freeing an RSA key */
172
static int
201
static int
173
pkcs11_rsa_finish(RSA *rsa)
202
pkcs11_rsa_finish(RSA *rsa)
Lines 236-242 pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, Link Here
236
		{CKA_ID, NULL, 0},
265
		{CKA_ID, NULL, 0},
237
		{CKA_SIGN, NULL, sizeof(true_val) }
266
		{CKA_SIGN, NULL, sizeof(true_val) }
238
	};
267
	};
239
	char			*pin, prompt[1024];
240
	int			rval = -1;
268
	int			rval = -1;
241
269
242
	/* some compilers complain about non-constant initializer so we
270
	/* some compilers complain about non-constant initializer so we
Lines 254-277 pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, Link Here
254
	}
282
	}
255
	f = k11->provider->function_list;
283
	f = k11->provider->function_list;
256
	si = &k11->provider->slotinfo[k11->slotidx];
284
	si = &k11->provider->slotinfo[k11->slotidx];
257
	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
285
	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in &&
258
		if (!pkcs11_interactive) {
286
	    pkcs11_login(k11->provider, si)) {
259
			error("need pin");
287
		return (-1);
260
			return (-1);
261
		}
262
		snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
263
		    si->token.label);
264
		pin = read_passphrase(prompt, RP_ALLOW_EOF);
265
		if (pin == NULL)
266
			return (-1);	/* bail out */
267
		if ((rv = f->C_Login(si->session, CKU_USER, pin, strlen(pin)))
268
		    != CKR_OK) {
269
			xfree(pin);
270
			error("C_Login failed: %lu", rv);
271
			return (-1);
272
		}
273
		xfree(pin);
274
		si->logged_in = 1;
275
	}
288
	}
276
	key_filter[1].pValue = k11->keyid;
289
	key_filter[1].pValue = k11->keyid;
277
	key_filter[1].ulValueLen = k11->keyid_len;
290
	key_filter[1].ulValueLen = k11->keyid_len;
Lines 327-332 pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, Link Here
327
	return (0);
340
	return (0);
328
}
341
}
329
342
343
static Key*
344
extract_key(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE	obj) {
345
	Key			*key;
346
	RSA			*rsa;
347
	CK_RV			rv;
348
	CK_SESSION_HANDLE	session;
349
	CK_FUNCTION_LIST	*f;
350
	CK_ATTRIBUTE		attribs[] = {
351
		{ CKA_ID, NULL, 0 },
352
		{ CKA_MODULUS, NULL, 0 },
353
		{ CKA_PUBLIC_EXPONENT, NULL, 0 }
354
	};
355
	int			i;
356
357
	key = NULL;
358
359
	f = p->function_list;
360
	session = p->slotinfo[slotidx].session;
361
362
	/* figure out size of the attributes */
363
	if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
364
	    != CKR_OK) {
365
		error("C_GetAttributeValue failed: %lu", rv);
366
		return NULL;
367
	}
368
	/* check that none of the attributes are zero length */
369
	if (attribs[0].ulValueLen == 0 ||
370
	    attribs[1].ulValueLen == 0 ||
371
	    attribs[2].ulValueLen == 0) {
372
		return NULL;
373
	}
374
	/* allocate buffers for attributes */
375
	for (i = 0; i < 3; i++)
376
		attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
377
	/* retrieve ID, modulus and public exponent of RSA key */
378
	if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
379
	    != CKR_OK) {
380
		error("C_GetAttributeValue failed: %lu", rv);
381
	} else if ((rsa = RSA_new()) == NULL) {
382
		error("RSA_new failed");
383
	} else {
384
		rsa->n = BN_bin2bn(attribs[1].pValue,
385
		    attribs[1].ulValueLen, NULL);
386
		rsa->e = BN_bin2bn(attribs[2].pValue,
387
		    attribs[2].ulValueLen, NULL);
388
		if (rsa->n && rsa->e &&
389
		    pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
390
			key = key_new(KEY_UNSPEC);
391
			key->rsa = rsa;
392
			key->type = KEY_RSA;
393
			key->flags |= KEY_FLAG_EXT;
394
		} else {
395
			RSA_free(rsa);
396
		}
397
	}
398
	for (i = 0; i < 3; i++)
399
		xfree(attribs[i].pValue);
400
401
	return key;
402
}
403
330
/* remove trailing spaces */
404
/* remove trailing spaces */
331
static void
405
static void
332
rmspace(char *buf, size_t len)
406
rmspace(char *buf, size_t len)
Lines 380-385 pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) Link Here
380
	return (0);
454
	return (0);
381
}
455
}
382
456
457
static Key*
458
pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
459
    char *label, CK_ULONG bits)
460
{
461
	struct pkcs11_slotinfo	*si;
462
	CK_FUNCTION_LIST *f;
463
	CK_SESSION_HANDLE	session;
464
	CK_BBOOL		    true_val = CK_TRUE;
465
	CK_MECHANISM		mech = {
466
		CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
467
	};
468
	CK_BYTE pubExponent[] = {
469
			0x01, 0x00, 0x01 /* RSA_F4 in bytes */
470
	};
471
	CK_ATTRIBUTE    pubKeyTemplate[] = {
472
		{CKA_TOKEN, &true_val, sizeof(true_val)},
473
		{CKA_LABEL, label, strlen(label)},
474
		{CKA_ENCRYPT, &true_val, sizeof(true_val)},
475
		{CKA_VERIFY, &true_val, sizeof(true_val)},
476
		{CKA_WRAP, &true_val, sizeof(true_val)},
477
		{CKA_MODULUS_BITS, &bits, sizeof(bits)},
478
		{CKA_PUBLIC_EXPONENT, pubExponent, sizeof(pubExponent)}
479
	};
480
	CK_ATTRIBUTE    privKeyTemplate[] = {
481
		{CKA_TOKEN, &true_val, sizeof(true_val)},
482
		{CKA_LABEL, label, strlen(label)},
483
		{CKA_PRIVATE, &true_val, sizeof(true_val)},
484
		{CKA_SENSITIVE, &true_val, sizeof(true_val)},
485
		{CKA_DECRYPT, &true_val, sizeof(true_val)},
486
		{CKA_SIGN, &true_val, sizeof(true_val)},
487
		{CKA_UNWRAP, &true_val, sizeof(true_val)}
488
	};
489
	CK_ATTRIBUTE		modulus[] = {
490
		{ CKA_MODULUS, NULL, 0 }
491
	};
492
	CK_ATTRIBUTE		id[] = {
493
		{ CKA_ID, NULL, 0 }
494
	};
495
	CK_OBJECT_HANDLE pubKey, privKey;
496
	CK_RV rv;
497
498
	f = p->function_list;
499
	si = &p->slotinfo[slotidx];
500
	session = si->session;
501
502
	/* login if we haven't done so yet */
503
	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in &&
504
	    pkcs11_login(p, si))
505
		fatal("Unable to login to slotidx %lu", slotidx);
506
507
	/* generate public / private key pair */
508
	if ((rv = f->C_GenerateKeyPair(session, &mech, pubKeyTemplate, 7,
509
	    privKeyTemplate, 6, &pubKey, &privKey)) != CKR_OK) {
510
		fatal("pkcs11 rsa key pair generation failed with error 0x%lx", rv);
511
	}
512
513
	/* get the generated public modulus */
514
	if ((rv = f->C_GetAttributeValue(session, pubKey, modulus, 1)) != CKR_OK) {
515
		fatal("C_GetAttributeValue failed: %lu", rv);
516
	}
517
	modulus[0].pValue = xmalloc(modulus[0].ulValueLen);
518
	if ((rv = f->C_GetAttributeValue(session, pubKey, modulus, 1)) != CKR_OK) {
519
		fatal("C_GetAttributeValue failed: %lu", rv);
520
	}
521
522
	/* set the id of the generated public and private keys to the modulus */
523
	id[0].pValue = modulus[0].pValue;
524
	id[0].ulValueLen = modulus[0].ulValueLen;
525
	if ((rv = f->C_SetAttributeValue(session, pubKey, id, 1)) != CKR_OK) {
526
		fatal("C_SetAttributeValue failed: %lu", rv);
527
	}
528
	if ((rv = f->C_SetAttributeValue(session, privKey, id, 1)) != CKR_OK) {
529
		fatal("C_SetAttributeValue failed: %lu", rv);
530
	}
531
532
	xfree(modulus[0].pValue);
533
534
	return extract_key(p, slotidx, privKey);
535
}
536
383
/*
537
/*
384
 * lookup public keys for token in slot identified by slotidx,
538
 * lookup public keys for token in slot identified by slotidx,
385
 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
539
 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
Lines 390-397 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, Link Here
390
    int *nkeys)
544
    int *nkeys)
391
{
545
{
392
	Key			*key;
546
	Key			*key;
393
	RSA			*rsa;
394
	int			i;
395
	CK_RV			rv;
547
	CK_RV			rv;
396
	CK_OBJECT_HANDLE	obj;
548
	CK_OBJECT_HANDLE	obj;
397
	CK_ULONG		nfound;
549
	CK_ULONG		nfound;
Lines 401-411 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, Link Here
401
	CK_ATTRIBUTE		pubkey_filter[] = {
553
	CK_ATTRIBUTE		pubkey_filter[] = {
402
		{ CKA_CLASS, NULL, sizeof(pubkey_class) }
554
		{ CKA_CLASS, NULL, sizeof(pubkey_class) }
403
	};
555
	};
404
	CK_ATTRIBUTE		attribs[] = {
405
		{ CKA_ID, NULL, 0 },
406
		{ CKA_MODULUS, NULL, 0 },
407
		{ CKA_PUBLIC_EXPONENT, NULL, 0 }
408
	};
409
556
410
	/* some compilers complain about non-constant initializer so we
557
	/* some compilers complain about non-constant initializer so we
411
	   use NULL in CK_ATTRIBUTE above and set the value here */
558
	   use NULL in CK_ATTRIBUTE above and set the value here */
Lines 419-496 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, Link Here
419
		return (-1);
566
		return (-1);
420
	}
567
	}
421
	while (1) {
568
	while (1) {
422
		/* XXX 3 attributes in attribs[] */
423
		for (i = 0; i < 3; i++) {
424
			attribs[i].pValue = NULL;
425
			attribs[i].ulValueLen = 0;
426
		}
427
		if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK
569
		if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK
428
		    || nfound == 0)
570
		    || nfound == 0)
429
			break;
571
			break;
430
		/* found a key, so figure out size of the attributes */
572
431
		if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
573
		/* found a key, extract details */
432
		    != CKR_OK) {
574
		if ((key = extract_key(p, slotidx, obj)) != NULL) {
433
			error("C_GetAttributeValue failed: %lu", rv);
575
			/* expand key array and add key */
434
			continue;
576
			*keysp = xrealloc(*keysp, *nkeys + 1,
435
		}
577
			    sizeof(Key *));
436
		/* check that none of the attributes are zero length */
578
			(*keysp)[*nkeys] = key;
437
		if (attribs[0].ulValueLen == 0 ||
579
			*nkeys = *nkeys + 1;
438
		    attribs[1].ulValueLen == 0 ||
580
			debug("have %d keys", *nkeys);
439
		    attribs[2].ulValueLen == 0) {
440
			continue;
441
		}
442
		/* allocate buffers for attributes */
443
		for (i = 0; i < 3; i++)
444
			attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
445
		/* retrieve ID, modulus and public exponent of RSA key */
446
		if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
447
		    != CKR_OK) {
448
			error("C_GetAttributeValue failed: %lu", rv);
449
		} else if ((rsa = RSA_new()) == NULL) {
450
			error("RSA_new failed");
451
		} else {
452
			rsa->n = BN_bin2bn(attribs[1].pValue,
453
			    attribs[1].ulValueLen, NULL);
454
			rsa->e = BN_bin2bn(attribs[2].pValue,
455
			    attribs[2].ulValueLen, NULL);
456
			if (rsa->n && rsa->e &&
457
			    pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
458
				key = key_new(KEY_UNSPEC);
459
				key->rsa = rsa;
460
				key->type = KEY_RSA;
461
				key->flags |= KEY_FLAG_EXT;
462
				/* expand key array and add key */
463
				*keysp = xrealloc(*keysp, *nkeys + 1,
464
				    sizeof(Key *));
465
				(*keysp)[*nkeys] = key;
466
				*nkeys = *nkeys + 1;
467
				debug("have %d keys", *nkeys);
468
			} else {
469
				RSA_free(rsa);
470
			}
471
		}
581
		}
472
		for (i = 0; i < 3; i++)
473
			xfree(attribs[i].pValue);
474
	}
582
	}
475
	if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
583
	if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
476
		error("C_FindObjectsFinal failed: %lu", rv);
584
		error("C_FindObjectsFinal failed: %lu", rv);
477
	return (0);
585
	return (0);
478
}
586
}
479
587
480
/* register a new provider, fails if provider already exists */
588
/* initialize a new provider, fails if provider is already registered */
481
int
589
static struct pkcs11_provider *
482
pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp)
590
pkcs11_init_provider(char *provider_id, char *pin)
483
{
591
{
484
	int nkeys, need_finalize = 0;
592
	int need_finalize = 0;
485
	struct pkcs11_provider *p = NULL;
593
	struct pkcs11_provider *p = NULL;
486
	void *handle = NULL;
594
	void *handle = NULL;
487
	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
595
	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
488
	CK_RV rv;
489
	CK_FUNCTION_LIST *f = NULL;
596
	CK_FUNCTION_LIST *f = NULL;
490
	CK_TOKEN_INFO *token;
597
	CK_TOKEN_INFO *token;
491
	CK_ULONG i;
598
	CK_ULONG i;
599
	CK_RV rv;
492
600
493
	*keyp = NULL;
494
	if (pkcs11_provider_lookup(provider_id) != NULL) {
601
	if (pkcs11_provider_lookup(provider_id) != NULL) {
495
		error("provider already registered: %s", provider_id);
602
		error("provider already registered: %s", provider_id);
496
		goto fail;
603
		goto fail;
Lines 542-558 pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) Link Here
542
	}
649
	}
543
	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
650
	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
544
	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
651
	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
545
	    != CKR_OK) {
652
			!= CKR_OK) {
546
		error("C_GetSlotList failed: %lu", rv);
653
		error("C_GetSlotList failed: %lu", rv);
547
		goto fail;
654
		goto fail;
548
	}
655
	}
549
	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
656
	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
550
	p->valid = 1;
657
	p->valid = 1;
551
	nkeys = 0;
658
552
	for (i = 0; i < p->nslots; i++) {
659
	for (i = 0; i < p->nslots; i++) {
553
		token = &p->slotinfo[i].token;
660
		token = &p->slotinfo[i].token;
554
		if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
661
		if ((rv = p->function_list->C_GetTokenInfo(p->slotlist[i], token))
555
		    != CKR_OK) {
662
				!= CKR_OK) {
556
			error("C_GetTokenInfo failed: %lu", rv);
663
			error("C_GetTokenInfo failed: %lu", rv);
557
			continue;
664
			continue;
558
		}
665
		}
Lines 561-580 pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) Link Here
561
		rmspace(token->model, sizeof(token->model));
668
		rmspace(token->model, sizeof(token->model));
562
		rmspace(token->serialNumber, sizeof(token->serialNumber));
669
		rmspace(token->serialNumber, sizeof(token->serialNumber));
563
		debug("label <%s> manufacturerID <%s> model <%s> serial <%s>"
670
		debug("label <%s> manufacturerID <%s> model <%s> serial <%s>"
564
		    " flags 0x%lx",
671
				" flags 0x%lx",
565
		    token->label, token->manufacturerID, token->model,
672
				token->label, token->manufacturerID, token->model,
566
		    token->serialNumber, token->flags);
673
				token->serialNumber, token->flags);
567
		/* open session, login with pin and retrieve public keys */
674
		/* open session, login with pin */
568
		if (pkcs11_open_session(p, i, pin) == 0)
675
		pkcs11_open_session(p, i, pin);
569
			pkcs11_fetch_keys(p, i, keyp, &nkeys);
570
	}
676
	}
571
	if (nkeys > 0) {
677
572
		TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
678
	return p;
573
		p->refcount++;	/* add to provider list */
679
574
		return (nkeys);
575
	}
576
	error("no keys");
577
	/* don't add the provider, since it does not have any keys */
578
fail:
680
fail:
579
	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
681
	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
580
		error("C_Finalize failed: %lu", rv);
682
		error("C_Finalize failed: %lu", rv);
Lines 587-593 fail: Link Here
587
	}
689
	}
588
	if (handle)
690
	if (handle)
589
		dlclose(handle);
691
		dlclose(handle);
590
	return (-1);
692
	return NULL;
693
}
694
695
/* register a new provider and get keys, fails if provider already exists or
696
 * contains no keys */
697
int
698
pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp)
699
{
700
	struct pkcs11_provider *p;
701
	int nkeys;
702
	CK_ULONG i;
703
704
	if (pkcs11_provider_lookup(provider_id) != NULL) {
705
		error("provider already registered: %s", provider_id);
706
		return (-1);
707
	}
708
709
	if ((p = pkcs11_init_provider(provider_id, pin)) == NULL) {
710
		return (-1);
711
	}
712
713
	*keyp = NULL;
714
	nkeys = 0;
715
	for (i = 0; i < p->nslots; i++) {
716
		/* Fetch keys for any slots with open sessions */
717
		if (p->slotinfo[i].session)
718
			pkcs11_fetch_keys(p, i, keyp, &nkeys);
719
	}
720
	if (nkeys > 0) {
721
		TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
722
		p->refcount++;	/* add to provider list */
723
		return (nkeys);
724
	} else {
725
		error("no keys");
726
		/* don't add the provider, since it does not have any keys */
727
		pkcs11_provider_finalize(p);
728
		pkcs11_provider_unref(p);
729
		return (-1);
730
	}
731
}
732
733
Key *
734
pkcs11_key_generate(char *provider_id, char *pin, u_int slotidx, char *label,
735
    int type, u_int bits)
736
{
737
	Key *k = NULL;
738
	struct pkcs11_provider *p;
739
740
	if (((p = pkcs11_provider_lookup(provider_id)) == NULL)
741
			&& ((p = pkcs11_init_provider(provider_id, pin)) == NULL)) {
742
		fatal("pkcs11 provider initialization failed");
743
	}
744
745
	switch (type) {
746
	case KEY_RSA:
747
	case KEY_RSA1:
748
		if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label, bits)) == NULL)
749
			fatal("Error generating pkcs11 RSA key");
750
		break;
751
	default:
752
		fatal("key_generate: unknown type %d", type);
753
	}
754
755
	if (k != NULL) {
756
		// Add to pkcs11 provider list
757
		TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
758
		p->refcount++;
759
	}
760
761
	return k;
591
}
762
}
592
763
593
#else
764
#else
(-)a/ssh-pkcs11.h (+1 lines)
Lines 18-20 int pkcs11_init(int); Link Here
18
void	pkcs11_terminate(void);
18
void	pkcs11_terminate(void);
19
int	pkcs11_add_provider(char *, char *, Key ***);
19
int	pkcs11_add_provider(char *, char *, Key ***);
20
int	pkcs11_del_provider(char *);
20
int	pkcs11_del_provider(char *);
21
Key *	pkcs11_key_generate(char *, char *, u_int, char *, int, u_int);
(-)a/ssh.c (-4 / +4 lines)
Lines 826-832 main(int ac, char **av) Link Here
826
826
827
		PRIV_START;
827
		PRIV_START;
828
		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
828
		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
829
		    _PATH_HOST_KEY_FILE, "", NULL, NULL);
829
		    _PATH_HOST_KEY_FILE, "", NULL, NULL, NULL);
830
		sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
830
		sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
831
		    _PATH_HOST_DSA_KEY_FILE, "", NULL);
831
		    _PATH_HOST_DSA_KEY_FILE, "", NULL);
832
#ifdef OPENSSL_HAS_ECC
832
#ifdef OPENSSL_HAS_ECC
Lines 836-848 main(int ac, char **av) Link Here
836
		sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
836
		sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
837
		    _PATH_HOST_RSA_KEY_FILE, "", NULL);
837
		    _PATH_HOST_RSA_KEY_FILE, "", NULL);
838
		sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
838
		sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
839
		    _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
839
		    _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL, NULL);
840
#ifdef OPENSSL_HAS_ECC
840
#ifdef OPENSSL_HAS_ECC
841
		sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
841
		sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
842
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
842
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL, NULL);
843
#endif
843
#endif
844
		sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
844
		sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
845
		    _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
845
		    _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL, NULL);
846
		PRIV_END;
846
		PRIV_END;
847
847
848
		if (options.hostbased_authentication == 1 &&
848
		if (options.hostbased_authentication == 1 &&
(-)a/sshconnect1.c (-4 / +4 lines)
Lines 208-214 try_rsa_authentication(int idx) Link Here
208
	BIGNUM *challenge;
208
	BIGNUM *challenge;
209
	Key *public, *private;
209
	Key *public, *private;
210
	char buf[300], *passphrase, *comment, *authfile;
210
	char buf[300], *passphrase, *comment, *authfile;
211
	int i, perm_ok = 1, type, quit;
211
	int i, perm_ok = 1, is_external = 0, type, quit;
212
212
213
	public = options.identity_keys[idx];
213
	public = options.identity_keys[idx];
214
	authfile = options.identity_files[idx];
214
	authfile = options.identity_files[idx];
Lines 255-269 try_rsa_authentication(int idx) Link Here
255
		private = public;
255
		private = public;
256
	else
256
	else
257
		private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
257
		private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
258
		    &perm_ok);
258
		    &perm_ok, &is_external);
259
	if (private == NULL && !options.batch_mode && perm_ok) {
259
	if (private == NULL && !options.batch_mode && perm_ok && !is_external) {
260
		snprintf(buf, sizeof(buf),
260
		snprintf(buf, sizeof(buf),
261
		    "Enter passphrase for RSA key '%.100s': ", comment);
261
		    "Enter passphrase for RSA key '%.100s': ", comment);
262
		for (i = 0; i < options.number_of_password_prompts; i++) {
262
		for (i = 0; i < options.number_of_password_prompts; i++) {
263
			passphrase = read_passphrase(buf, 0);
263
			passphrase = read_passphrase(buf, 0);
264
			if (strcmp(passphrase, "") != 0) {
264
			if (strcmp(passphrase, "") != 0) {
265
				private = key_load_private_type(KEY_RSA1,
265
				private = key_load_private_type(KEY_RSA1,
266
				    authfile, passphrase, NULL, NULL);
266
				    authfile, passphrase, NULL, NULL, NULL);
267
				quit = 0;
267
				quit = 0;
268
			} else {
268
			} else {
269
				debug2("no passphrase given, try next key");
269
				debug2("no passphrase given, try next key");
(-)a/sshconnect2.c (-4 / +8 lines)
Lines 1316-1322 load_identity_file(char *filename, int userprovided) Link Here
1316
{
1316
{
1317
	Key *private;
1317
	Key *private;
1318
	char prompt[300], *passphrase;
1318
	char prompt[300], *passphrase;
1319
	int perm_ok = 0, quit, i;
1319
	int perm_ok = 0, is_external = 0, quit, i;
1320
	struct stat st;
1320
	struct stat st;
1321
1321
1322
	if (stat(filename, &st) < 0) {
1322
	if (stat(filename, &st) < 0) {
Lines 1324-1330 load_identity_file(char *filename, int userprovided) Link Here
1324
		    filename, strerror(errno));
1324
		    filename, strerror(errno));
1325
		return NULL;
1325
		return NULL;
1326
	}
1326
	}
1327
	private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
1327
	private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok,
1328
	    &is_external);
1329
	if (is_external) {
1330
		error("Key %s is external. Load it through it's pkcs11 module.", filename);
1331
		return NULL;
1332
	}
1328
	if (!perm_ok)
1333
	if (!perm_ok)
1329
		return NULL;
1334
		return NULL;
1330
	if (private == NULL) {
1335
	if (private == NULL) {
Lines 1336-1342 load_identity_file(char *filename, int userprovided) Link Here
1336
			passphrase = read_passphrase(prompt, 0);
1341
			passphrase = read_passphrase(prompt, 0);
1337
			if (strcmp(passphrase, "") != 0) {
1342
			if (strcmp(passphrase, "") != 0) {
1338
				private = key_load_private_type(KEY_UNSPEC,
1343
				private = key_load_private_type(KEY_UNSPEC,
1339
				    filename, passphrase, NULL, NULL);
1344
				    filename, passphrase, NULL, NULL, NULL);
1340
				quit = 0;
1345
				quit = 0;
1341
			} else {
1346
			} else {
1342
				debug2("no passphrase given, try next key");
1347
				debug2("no passphrase given, try next key");
1343
- 

Return to bug 2075