diff options
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 371 |
1 files changed, 361 insertions, 10 deletions
diff --git a/authfile.c b/authfile.c index d0c1089eb..e38a3dd14 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.98 2013/11/21 00:45:43 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.99 2013/12/06 13:34:54 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -13,7 +13,7 @@ | |||
13 | * called by a name other than "ssh" or "Secure Shell". | 13 | * called by a name other than "ssh" or "Secure Shell". |
14 | * | 14 | * |
15 | * | 15 | * |
16 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 16 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
17 | * | 17 | * |
18 | * Redistribution and use in source and binary forms, with or without | 18 | * Redistribution and use in source and binary forms, with or without |
19 | * modification, are permitted provided that the following conditions | 19 | * modification, are permitted provided that the following conditions |
@@ -58,6 +58,8 @@ | |||
58 | #include <string.h> | 58 | #include <string.h> |
59 | #include <unistd.h> | 59 | #include <unistd.h> |
60 | 60 | ||
61 | #include <util.h> | ||
62 | |||
61 | #include "xmalloc.h" | 63 | #include "xmalloc.h" |
62 | #include "cipher.h" | 64 | #include "cipher.h" |
63 | #include "buffer.h" | 65 | #include "buffer.h" |
@@ -68,6 +70,16 @@ | |||
68 | #include "rsa.h" | 70 | #include "rsa.h" |
69 | #include "misc.h" | 71 | #include "misc.h" |
70 | #include "atomicio.h" | 72 | #include "atomicio.h" |
73 | #include "uuencode.h" | ||
74 | |||
75 | /* openssh private key file format */ | ||
76 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" | ||
77 | #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" | ||
78 | #define KDFNAME "bcrypt" | ||
79 | #define AUTH_MAGIC "openssh-key-v1" | ||
80 | #define SALT_LEN 16 | ||
81 | #define DEFAULT_CIPHERNAME "aes256-cbc" | ||
82 | #define DEFAULT_ROUNDS 16 | ||
71 | 83 | ||
72 | #define MAX_KEY_FILE_SIZE (1024 * 1024) | 84 | #define MAX_KEY_FILE_SIZE (1024 * 1024) |
73 | 85 | ||
@@ -75,6 +87,333 @@ | |||
75 | static const char authfile_id_string[] = | 87 | static const char authfile_id_string[] = |
76 | "SSH PRIVATE KEY FILE FORMAT 1.1\n"; | 88 | "SSH PRIVATE KEY FILE FORMAT 1.1\n"; |
77 | 89 | ||
90 | static int | ||
91 | key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase, | ||
92 | const char *comment, const char *ciphername, int rounds) | ||
93 | { | ||
94 | u_char *key, *cp, salt[SALT_LEN]; | ||
95 | size_t keylen, ivlen, blocksize, authlen; | ||
96 | u_int len, check; | ||
97 | int i, n; | ||
98 | const Cipher *c; | ||
99 | Buffer encoded, b, kdf; | ||
100 | CipherContext ctx; | ||
101 | const char *kdfname = KDFNAME; | ||
102 | |||
103 | if (rounds <= 0) | ||
104 | rounds = DEFAULT_ROUNDS; | ||
105 | if (passphrase == NULL || !strlen(passphrase)) { | ||
106 | ciphername = "none"; | ||
107 | kdfname = "none"; | ||
108 | } else if (ciphername == NULL) | ||
109 | ciphername = DEFAULT_CIPHERNAME; | ||
110 | else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) | ||
111 | fatal("invalid cipher"); | ||
112 | |||
113 | if ((c = cipher_by_name(ciphername)) == NULL) | ||
114 | fatal("unknown cipher name"); | ||
115 | buffer_init(&kdf); | ||
116 | blocksize = cipher_blocksize(c); | ||
117 | keylen = cipher_keylen(c); | ||
118 | ivlen = cipher_ivlen(c); | ||
119 | authlen = cipher_authlen(c); | ||
120 | key = xcalloc(1, keylen + ivlen); | ||
121 | if (strcmp(kdfname, "none") != 0) { | ||
122 | arc4random_buf(salt, SALT_LEN); | ||
123 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), | ||
124 | salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) | ||
125 | fatal("bcrypt_pbkdf failed"); | ||
126 | buffer_put_string(&kdf, salt, SALT_LEN); | ||
127 | buffer_put_int(&kdf, rounds); | ||
128 | } | ||
129 | cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1); | ||
130 | memset(key, 0, keylen + ivlen); | ||
131 | free(key); | ||
132 | |||
133 | buffer_init(&encoded); | ||
134 | buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC)); | ||
135 | buffer_put_cstring(&encoded, ciphername); | ||
136 | buffer_put_cstring(&encoded, kdfname); | ||
137 | buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf)); | ||
138 | buffer_put_int(&encoded, 1); /* number of keys */ | ||
139 | key_to_blob(prv, &cp, &len); /* public key */ | ||
140 | buffer_put_string(&encoded, cp, len); | ||
141 | |||
142 | memset(cp, 0, len); | ||
143 | free(cp); | ||
144 | |||
145 | buffer_free(&kdf); | ||
146 | |||
147 | /* set up the buffer that will be encrypted */ | ||
148 | buffer_init(&b); | ||
149 | |||
150 | /* Random check bytes */ | ||
151 | check = arc4random(); | ||
152 | buffer_put_int(&b, check); | ||
153 | buffer_put_int(&b, check); | ||
154 | |||
155 | /* append private key and comment*/ | ||
156 | key_private_serialize(prv, &b); | ||
157 | buffer_put_cstring(&b, comment); | ||
158 | |||
159 | /* padding */ | ||
160 | i = 0; | ||
161 | while (buffer_len(&b) % blocksize) | ||
162 | buffer_put_char(&b, ++i & 0xff); | ||
163 | |||
164 | /* length */ | ||
165 | buffer_put_int(&encoded, buffer_len(&b)); | ||
166 | |||
167 | /* encrypt */ | ||
168 | cp = buffer_append_space(&encoded, buffer_len(&b) + authlen); | ||
169 | if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0, | ||
170 | authlen) != 0) | ||
171 | fatal("%s: cipher_crypt failed", __func__); | ||
172 | buffer_free(&b); | ||
173 | cipher_cleanup(&ctx); | ||
174 | |||
175 | /* uuencode */ | ||
176 | len = 2 * buffer_len(&encoded); | ||
177 | cp = xmalloc(len); | ||
178 | n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded), | ||
179 | (char *)cp, len); | ||
180 | if (n < 0) | ||
181 | fatal("%s: uuencode", __func__); | ||
182 | |||
183 | buffer_clear(blob); | ||
184 | buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1); | ||
185 | for (i = 0; i < n; i++) { | ||
186 | buffer_put_char(blob, cp[i]); | ||
187 | if (i % 70 == 69) | ||
188 | buffer_put_char(blob, '\n'); | ||
189 | } | ||
190 | if (i % 70 != 69) | ||
191 | buffer_put_char(blob, '\n'); | ||
192 | buffer_append(blob, MARK_END, sizeof(MARK_END) - 1); | ||
193 | free(cp); | ||
194 | |||
195 | return buffer_len(blob); | ||
196 | } | ||
197 | |||
198 | static Key * | ||
199 | key_parse_private2(Buffer *blob, int type, const char *passphrase, | ||
200 | char **commentp) | ||
201 | { | ||
202 | u_char *key = NULL, *cp, *salt = NULL, pad, last; | ||
203 | char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp; | ||
204 | u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys; | ||
205 | u_int check1, check2, m1len, m2len; | ||
206 | size_t authlen; | ||
207 | const Cipher *c; | ||
208 | Buffer b, encoded, copy, kdf; | ||
209 | CipherContext ctx; | ||
210 | Key *k = NULL; | ||
211 | int dlen, ret, i; | ||
212 | |||
213 | buffer_init(&b); | ||
214 | buffer_init(&kdf); | ||
215 | buffer_init(&encoded); | ||
216 | buffer_init(©); | ||
217 | |||
218 | /* uudecode */ | ||
219 | m1len = sizeof(MARK_BEGIN) - 1; | ||
220 | m2len = sizeof(MARK_END) - 1; | ||
221 | cp = buffer_ptr(blob); | ||
222 | len = buffer_len(blob); | ||
223 | if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) { | ||
224 | debug("%s: missing begin marker", __func__); | ||
225 | goto out; | ||
226 | } | ||
227 | cp += m1len; | ||
228 | len -= m1len; | ||
229 | while (len) { | ||
230 | if (*cp != '\n' && *cp != '\r') | ||
231 | buffer_put_char(&encoded, *cp); | ||
232 | last = *cp; | ||
233 | len--; | ||
234 | cp++; | ||
235 | if (last == '\n') { | ||
236 | if (len >= m2len && !memcmp(cp, MARK_END, m2len)) { | ||
237 | buffer_put_char(&encoded, '\0'); | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | if (!len) { | ||
243 | debug("%s: no end marker", __func__); | ||
244 | goto out; | ||
245 | } | ||
246 | len = buffer_len(&encoded); | ||
247 | if ((cp = buffer_append_space(©, len)) == NULL) { | ||
248 | error("%s: buffer_append_space", __func__); | ||
249 | goto out; | ||
250 | } | ||
251 | if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) { | ||
252 | error("%s: uudecode failed", __func__); | ||
253 | goto out; | ||
254 | } | ||
255 | if ((u_int)dlen > len) { | ||
256 | error("%s: crazy uudecode length %d > %u", __func__, dlen, len); | ||
257 | goto out; | ||
258 | } | ||
259 | buffer_consume_end(©, len - dlen); | ||
260 | if (buffer_len(©) < sizeof(AUTH_MAGIC) || | ||
261 | memcmp(buffer_ptr(©), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { | ||
262 | error("%s: bad magic", __func__); | ||
263 | goto out; | ||
264 | } | ||
265 | buffer_consume(©, sizeof(AUTH_MAGIC)); | ||
266 | |||
267 | ciphername = buffer_get_cstring_ret(©, NULL); | ||
268 | if (ciphername == NULL || | ||
269 | (c = cipher_by_name(ciphername)) == NULL) { | ||
270 | error("%s: unknown cipher name", __func__); | ||
271 | goto out; | ||
272 | } | ||
273 | if ((passphrase == NULL || !strlen(passphrase)) && | ||
274 | strcmp(ciphername, "none") != 0) { | ||
275 | /* passphrase required */ | ||
276 | goto out; | ||
277 | } | ||
278 | kdfname = buffer_get_cstring_ret(©, NULL); | ||
279 | if (kdfname == NULL || | ||
280 | (!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) { | ||
281 | error("%s: unknown kdf name", __func__); | ||
282 | goto out; | ||
283 | } | ||
284 | if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { | ||
285 | error("%s: cipher %s requires kdf", __func__, ciphername); | ||
286 | goto out; | ||
287 | } | ||
288 | /* kdf options */ | ||
289 | kdfp = buffer_get_string_ptr_ret(©, &klen); | ||
290 | if (kdfp == NULL) { | ||
291 | error("%s: kdf options not set", __func__); | ||
292 | goto out; | ||
293 | } | ||
294 | if (klen > 0) { | ||
295 | if ((cp = buffer_append_space(&kdf, klen)) == NULL) { | ||
296 | error("%s: kdf alloc failed", __func__); | ||
297 | goto out; | ||
298 | } | ||
299 | memcpy(cp, kdfp, klen); | ||
300 | } | ||
301 | /* number of keys */ | ||
302 | if (buffer_get_int_ret(&nkeys, ©) < 0) { | ||
303 | error("%s: key counter missing", __func__); | ||
304 | goto out; | ||
305 | } | ||
306 | if (nkeys != 1) { | ||
307 | error("%s: only one key supported", __func__); | ||
308 | goto out; | ||
309 | } | ||
310 | /* pubkey */ | ||
311 | if ((cp = buffer_get_string_ret(©, &len)) == NULL) { | ||
312 | error("%s: pubkey not found", __func__); | ||
313 | goto out; | ||
314 | } | ||
315 | free(cp); /* XXX check pubkey against decrypted private key */ | ||
316 | |||
317 | /* size of encrypted key blob */ | ||
318 | len = buffer_get_int(©); | ||
319 | blocksize = cipher_blocksize(c); | ||
320 | authlen = cipher_authlen(c); | ||
321 | if (len < blocksize) { | ||
322 | error("%s: encrypted data too small", __func__); | ||
323 | goto out; | ||
324 | } | ||
325 | if (len % blocksize) { | ||
326 | error("%s: length not multiple of blocksize", __func__); | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | /* setup key */ | ||
331 | keylen = cipher_keylen(c); | ||
332 | ivlen = cipher_ivlen(c); | ||
333 | key = xcalloc(1, keylen + ivlen); | ||
334 | if (!strcmp(kdfname, "bcrypt")) { | ||
335 | if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) { | ||
336 | error("%s: salt not set", __func__); | ||
337 | goto out; | ||
338 | } | ||
339 | if (buffer_get_int_ret(&rounds, &kdf) < 0) { | ||
340 | error("%s: rounds not set", __func__); | ||
341 | goto out; | ||
342 | } | ||
343 | if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, | ||
344 | key, keylen + ivlen, rounds) < 0) { | ||
345 | error("%s: bcrypt_pbkdf failed", __func__); | ||
346 | goto out; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | cp = buffer_append_space(&b, len); | ||
351 | cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0); | ||
352 | ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(©), len, 0, authlen); | ||
353 | cipher_cleanup(&ctx); | ||
354 | buffer_consume(©, len); | ||
355 | |||
356 | /* fail silently on decryption errors */ | ||
357 | if (ret != 0) { | ||
358 | debug("%s: decrypt failed", __func__); | ||
359 | goto out; | ||
360 | } | ||
361 | |||
362 | if (buffer_len(©) != 0) { | ||
363 | error("%s: key blob has trailing data (len = %u)", __func__, | ||
364 | buffer_len(©)); | ||
365 | goto out; | ||
366 | } | ||
367 | |||
368 | /* check bytes */ | ||
369 | if (buffer_get_int_ret(&check1, &b) < 0 || | ||
370 | buffer_get_int_ret(&check2, &b) < 0) { | ||
371 | error("check bytes missing"); | ||
372 | goto out; | ||
373 | } | ||
374 | if (check1 != check2) { | ||
375 | debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__, | ||
376 | check1, check2); | ||
377 | goto out; | ||
378 | } | ||
379 | |||
380 | k = key_private_deserialize(&b); | ||
381 | |||
382 | /* comment */ | ||
383 | comment = buffer_get_cstring_ret(&b, NULL); | ||
384 | |||
385 | i = 0; | ||
386 | while (buffer_len(&b)) { | ||
387 | if (buffer_get_char_ret(&pad, &b) == -1 || | ||
388 | pad != (++i & 0xff)) { | ||
389 | error("%s: bad padding", __func__); | ||
390 | key_free(k); | ||
391 | k = NULL; | ||
392 | goto out; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | if (k && commentp) { | ||
397 | *commentp = comment; | ||
398 | comment = NULL; | ||
399 | } | ||
400 | |||
401 | /* XXX decode pubkey and check against private */ | ||
402 | out: | ||
403 | free(ciphername); | ||
404 | free(kdfname); | ||
405 | free(salt); | ||
406 | free(comment); | ||
407 | if (key) | ||
408 | memset(key, 0, keylen + ivlen); | ||
409 | free(key); | ||
410 | buffer_free(&encoded); | ||
411 | buffer_free(©); | ||
412 | buffer_free(&kdf); | ||
413 | buffer_free(&b); | ||
414 | return k; | ||
415 | } | ||
416 | |||
78 | /* | 417 | /* |
79 | * Serialises the authentication (private) key to a blob, encrypting it with | 418 | * Serialises the authentication (private) key to a blob, encrypting it with |
80 | * passphrase. The identification of the blob (lowest 64 bits of n) will | 419 | * passphrase. The identification of the blob (lowest 64 bits of n) will |
@@ -149,8 +488,9 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, | |||
149 | 488 | ||
150 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | 489 | cipher_set_key_string(&ciphercontext, cipher, passphrase, |
151 | CIPHER_ENCRYPT); | 490 | CIPHER_ENCRYPT); |
152 | cipher_crypt(&ciphercontext, 0, cp, | 491 | if (cipher_crypt(&ciphercontext, 0, cp, |
153 | buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); | 492 | buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0) |
493 | fatal("%s: cipher_crypt failed", __func__); | ||
154 | cipher_cleanup(&ciphercontext); | 494 | cipher_cleanup(&ciphercontext); |
155 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | 495 | memset(&ciphercontext, 0, sizeof(ciphercontext)); |
156 | 496 | ||
@@ -239,7 +579,8 @@ key_save_private_blob(Buffer *keybuf, const char *filename) | |||
239 | /* Serialise "key" to buffer "blob" */ | 579 | /* Serialise "key" to buffer "blob" */ |
240 | static int | 580 | static int |
241 | key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, | 581 | key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, |
242 | const char *comment) | 582 | const char *comment, int force_new_format, const char *new_format_cipher, |
583 | int new_format_rounds) | ||
243 | { | 584 | { |
244 | switch (key->type) { | 585 | switch (key->type) { |
245 | case KEY_RSA1: | 586 | case KEY_RSA1: |
@@ -247,6 +588,10 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, | |||
247 | case KEY_DSA: | 588 | case KEY_DSA: |
248 | case KEY_ECDSA: | 589 | case KEY_ECDSA: |
249 | case KEY_RSA: | 590 | case KEY_RSA: |
591 | if (force_new_format) { | ||
592 | return key_private_to_blob2(key, blob, passphrase, | ||
593 | comment, new_format_cipher, new_format_rounds); | ||
594 | } | ||
250 | return key_private_pem_to_blob(key, blob, passphrase, comment); | 595 | return key_private_pem_to_blob(key, blob, passphrase, comment); |
251 | default: | 596 | default: |
252 | error("%s: cannot save key type %d", __func__, key->type); | 597 | error("%s: cannot save key type %d", __func__, key->type); |
@@ -256,13 +601,15 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, | |||
256 | 601 | ||
257 | int | 602 | int |
258 | key_save_private(Key *key, const char *filename, const char *passphrase, | 603 | key_save_private(Key *key, const char *filename, const char *passphrase, |
259 | const char *comment) | 604 | const char *comment, int force_new_format, const char *new_format_cipher, |
605 | int new_format_rounds) | ||
260 | { | 606 | { |
261 | Buffer keyblob; | 607 | Buffer keyblob; |
262 | int success = 0; | 608 | int success = 0; |
263 | 609 | ||
264 | buffer_init(&keyblob); | 610 | buffer_init(&keyblob); |
265 | if (!key_private_to_blob(key, &keyblob, passphrase, comment)) | 611 | if (!key_private_to_blob(key, &keyblob, passphrase, comment, |
612 | force_new_format, new_format_cipher, new_format_rounds)) | ||
266 | goto out; | 613 | goto out; |
267 | if (!key_save_private_blob(&keyblob, filename)) | 614 | if (!key_save_private_blob(&keyblob, filename)) |
268 | goto out; | 615 | goto out; |
@@ -473,8 +820,9 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) | |||
473 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | 820 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ |
474 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | 821 | cipher_set_key_string(&ciphercontext, cipher, passphrase, |
475 | CIPHER_DECRYPT); | 822 | CIPHER_DECRYPT); |
476 | cipher_crypt(&ciphercontext, 0, cp, | 823 | if (cipher_crypt(&ciphercontext, 0, cp, |
477 | buffer_ptr(©), buffer_len(©), 0, 0); | 824 | buffer_ptr(©), buffer_len(©), 0, 0) != 0) |
825 | fatal("%s: cipher_crypt failed", __func__); | ||
478 | cipher_cleanup(&ciphercontext); | 826 | cipher_cleanup(&ciphercontext); |
479 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | 827 | memset(&ciphercontext, 0, sizeof(ciphercontext)); |
480 | buffer_free(©); | 828 | buffer_free(©); |
@@ -641,6 +989,8 @@ static Key * | |||
641 | key_parse_private_type(Buffer *blob, int type, const char *passphrase, | 989 | key_parse_private_type(Buffer *blob, int type, const char *passphrase, |
642 | char **commentp) | 990 | char **commentp) |
643 | { | 991 | { |
992 | Key *k; | ||
993 | |||
644 | switch (type) { | 994 | switch (type) { |
645 | case KEY_RSA1: | 995 | case KEY_RSA1: |
646 | return key_parse_private_rsa1(blob, passphrase, commentp); | 996 | return key_parse_private_rsa1(blob, passphrase, commentp); |
@@ -648,6 +998,8 @@ key_parse_private_type(Buffer *blob, int type, const char *passphrase, | |||
648 | case KEY_ECDSA: | 998 | case KEY_ECDSA: |
649 | case KEY_RSA: | 999 | case KEY_RSA: |
650 | case KEY_UNSPEC: | 1000 | case KEY_UNSPEC: |
1001 | if ((k = key_parse_private2(blob, type, passphrase, commentp))) | ||
1002 | return k; | ||
651 | return key_parse_private_pem(blob, type, passphrase, commentp); | 1003 | return key_parse_private_pem(blob, type, passphrase, commentp); |
652 | default: | 1004 | default: |
653 | error("%s: cannot parse key type %d", __func__, type); | 1005 | error("%s: cannot parse key type %d", __func__, type); |
@@ -943,4 +1295,3 @@ key_in_file(Key *key, const char *filename, int strict_type) | |||
943 | fclose(f); | 1295 | fclose(f); |
944 | return ret; | 1296 | return ret; |
945 | } | 1297 | } |
946 | |||