summaryrefslogtreecommitdiff
path: root/authfile.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-12-01 12:01:21 +1100
committerDamien Miller <djm@mindrot.org>2010-12-01 12:01:21 +1100
commita232792783655659395f445c0f265d4f9444bb7c (patch)
tree93051bddb29ca4a185be61bf92ba889efb515a66 /authfile.c
parent2cd629349d9fc4067985fec04b23bfb5ff7aa8d8 (diff)
- djm@cvs.openbsd.org 2010/11/21 10:57:07
[authfile.c] Refactor internals of private key loading and saving to work on memory buffers rather than directly on files. This will make a few things easier to do in the future; ok markus@
Diffstat (limited to 'authfile.c')
-rw-r--r--authfile.c447
1 files changed, 254 insertions, 193 deletions
diff --git a/authfile.c b/authfile.c
index 7f98ab547..f75c273fc 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfile.c,v 1.85 2010/10/28 11:22:09 djm Exp $ */ 1/* $OpenBSD: authfile.c,v 1.86 2010/11/21 10:57:07 djm 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
@@ -74,19 +74,18 @@ static const char authfile_id_string[] =
74 "SSH PRIVATE KEY FILE FORMAT 1.1\n"; 74 "SSH PRIVATE KEY FILE FORMAT 1.1\n";
75 75
76/* 76/*
77 * Saves the authentication (private) key in a file, encrypting it with 77 * Serialises the authentication (private) key to a blob, encrypting it with
78 * passphrase. The identification of the file (lowest 64 bits of n) will 78 * passphrase. The identification of the blob (lowest 64 bits of n) will
79 * precede the key to provide identification of the key without needing a 79 * precede the key to provide identification of the key without needing a
80 * passphrase. 80 * passphrase.
81 */ 81 */
82
83static int 82static int
84key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, 83key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
85 const char *comment) 84 const char *comment)
86{ 85{
87 Buffer buffer, encrypted; 86 Buffer buffer, encrypted;
88 u_char buf[100], *cp; 87 u_char buf[100], *cp;
89 int fd, i, cipher_num; 88 int i, cipher_num;
90 CipherContext ciphercontext; 89 CipherContext ciphercontext;
91 Cipher *cipher; 90 Cipher *cipher;
92 u_int32_t rnd; 91 u_int32_t rnd;
@@ -157,163 +156,222 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
157 memset(buf, 0, sizeof(buf)); 156 memset(buf, 0, sizeof(buf));
158 buffer_free(&buffer); 157 buffer_free(&buffer);
159 158
160 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 159 buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
161 if (fd < 0) {
162 error("open %s failed: %s.", filename, strerror(errno));
163 buffer_free(&encrypted);
164 return 0;
165 }
166 if (atomicio(vwrite, fd, buffer_ptr(&encrypted),
167 buffer_len(&encrypted)) != buffer_len(&encrypted)) {
168 error("write to key file %s failed: %s", filename,
169 strerror(errno));
170 buffer_free(&encrypted);
171 close(fd);
172 unlink(filename);
173 return 0;
174 }
175 close(fd);
176 buffer_free(&encrypted); 160 buffer_free(&encrypted);
161
177 return 1; 162 return 1;
178} 163}
179 164
180/* save SSH v2 key in OpenSSL PEM format */ 165/* convert SSH v2 key in OpenSSL PEM format */
181static int 166static int
182key_save_private_pem(Key *key, const char *filename, const char *_passphrase, 167key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
183 const char *comment) 168 const char *comment)
184{ 169{
185 FILE *fp;
186 int fd;
187 int success = 0; 170 int success = 0;
188 int len = strlen(_passphrase); 171 int blen, len = strlen(_passphrase);
189 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; 172 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
190#if (OPENSSL_VERSION_NUMBER < 0x00907000L) 173#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
191 const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; 174 const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
192#else 175#else
193 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; 176 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
194#endif 177#endif
178 const u_char *bptr;
179 BIO *bio;
195 180
196 if (len > 0 && len <= 4) { 181 if (len > 0 && len <= 4) {
197 error("passphrase too short: have %d bytes, need > 4", len); 182 error("passphrase too short: have %d bytes, need > 4", len);
198 return 0; 183 return 0;
199 } 184 }
200 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 185 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
201 if (fd < 0) { 186 error("%s: BIO_new failed", __func__);
202 error("open %s failed: %s.", filename, strerror(errno));
203 return 0;
204 }
205 fp = fdopen(fd, "w");
206 if (fp == NULL) {
207 error("fdopen %s failed: %s.", filename, strerror(errno));
208 close(fd);
209 return 0; 187 return 0;
210 } 188 }
211 switch (key->type) { 189 switch (key->type) {
212 case KEY_DSA: 190 case KEY_DSA:
213 success = PEM_write_DSAPrivateKey(fp, key->dsa, 191 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
214 cipher, passphrase, len, NULL, NULL); 192 cipher, passphrase, len, NULL, NULL);
215 break; 193 break;
216#ifdef OPENSSL_HAS_ECC 194#ifdef OPENSSL_HAS_ECC
217 case KEY_ECDSA: 195 case KEY_ECDSA:
218 success = PEM_write_ECPrivateKey(fp, key->ecdsa, 196 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
219 cipher, passphrase, len, NULL, NULL); 197 cipher, passphrase, len, NULL, NULL);
220 break; 198 break;
221#endif 199#endif
222 case KEY_RSA: 200 case KEY_RSA:
223 success = PEM_write_RSAPrivateKey(fp, key->rsa, 201 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
224 cipher, passphrase, len, NULL, NULL); 202 cipher, passphrase, len, NULL, NULL);
225 break; 203 break;
226 } 204 }
227 fclose(fp); 205 if (success) {
206 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
207 success = 0;
208 else
209 buffer_append(blob, bptr, blen);
210 }
211 BIO_free(bio);
228 return success; 212 return success;
229} 213}
230 214
231int 215/* Save a key blob to a file */
232key_save_private(Key *key, const char *filename, const char *passphrase, 216static int
217key_save_private_blob(Buffer *keybuf, const char *filename)
218{
219 int fd;
220
221 if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
222 error("open %s failed: %s.", filename, strerror(errno));
223 return 0;
224 }
225 if (atomicio(vwrite, fd, buffer_ptr(keybuf),
226 buffer_len(keybuf)) != buffer_len(keybuf)) {
227 error("write to key file %s failed: %s", filename,
228 strerror(errno));
229 close(fd);
230 unlink(filename);
231 return 0;
232 }
233 close(fd);
234 return 1;
235}
236
237/* Serialise "key" to buffer "blob" */
238static int
239key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
233 const char *comment) 240 const char *comment)
234{ 241{
235 switch (key->type) { 242 switch (key->type) {
236 case KEY_RSA1: 243 case KEY_RSA1:
237 return key_save_private_rsa1(key, filename, passphrase, 244 return key_private_rsa1_to_blob(key, blob, passphrase, comment);
238 comment);
239 case KEY_DSA: 245 case KEY_DSA:
240 case KEY_ECDSA: 246 case KEY_ECDSA:
241 case KEY_RSA: 247 case KEY_RSA:
242 return key_save_private_pem(key, filename, passphrase, 248 return key_private_pem_to_blob(key, blob, passphrase, comment);
243 comment);
244 default: 249 default:
245 break; 250 error("%s: cannot save key type %d", __func__, key->type);
251 return 0;
246 } 252 }
247 error("key_save_private: cannot save key type %d", key->type); 253}
248 return 0; 254
255int
256key_save_private(Key *key, const char *filename, const char *passphrase,
257 const char *comment)
258{
259 Buffer keyblob;
260 int success = 0;
261
262 buffer_init(&keyblob);
263 if (!key_private_to_blob(key, &keyblob, passphrase, comment))
264 goto out;
265 if (!key_save_private_blob(&keyblob, filename))
266 goto out;
267 success = 1;
268 out:
269 buffer_free(&keyblob);
270 return success;
249} 271}
250 272
251/* 273/*
252 * Loads the public part of the ssh v1 key file. Returns NULL if an error was 274 * Parse the public, unencrypted portion of a RSA1 key.
253 * encountered (the file does not exist or is not readable), and the key
254 * otherwise.
255 */ 275 */
256
257static Key * 276static Key *
258key_load_public_rsa1(int fd, const char *filename, char **commentp) 277key_parse_public_rsa1(Buffer *blob, char **commentp)
259{ 278{
260 Buffer buffer;
261 Key *pub; 279 Key *pub;
262 struct stat st; 280
263 char *cp; 281 /* Check that it is at least big enough to contain the ID string. */
264 u_int i; 282 if (buffer_len(blob) < sizeof(authfile_id_string)) {
283 debug3("Truncated RSA1 identifier");
284 return NULL;
285 }
286
287 /*
288 * Make sure it begins with the id string. Consume the id string
289 * from the buffer.
290 */
291 if (memcmp(buffer_ptr(blob), authfile_id_string,
292 sizeof(authfile_id_string)) != 0) {
293 debug3("Incorrect RSA1 identifier");
294 return NULL;
295 }
296 buffer_consume(blob, sizeof(authfile_id_string));
297
298 /* Skip cipher type and reserved data. */
299 (void) buffer_get_char(blob); /* cipher type */
300 (void) buffer_get_int(blob); /* reserved */
301
302 /* Read the public key from the buffer. */
303 (void) buffer_get_int(blob);
304 pub = key_new(KEY_RSA1);
305 buffer_get_bignum(blob, pub->rsa->n);
306 buffer_get_bignum(blob, pub->rsa->e);
307 if (commentp)
308 *commentp = buffer_get_string(blob, NULL);
309 /* The encrypted private part is not parsed by this function. */
310 buffer_clear(blob);
311
312 return pub;
313}
314
315/* Load the contents of a key file into a buffer */
316static int
317key_load_file(int fd, const char *filename, Buffer *blob)
318{
265 size_t len; 319 size_t len;
320 u_char *cp;
321 struct stat st;
266 322
267 if (fstat(fd, &st) < 0) { 323 if (fstat(fd, &st) < 0) {
268 error("fstat for key file %.200s failed: %.100s", 324 error("%s: fstat of key file %.200s%sfailed: %.100s", __func__,
269 filename, strerror(errno)); 325 filename == NULL ? "" : filename,
270 return NULL; 326 filename == NULL ? "" : " ",
327 strerror(errno));
328 close(fd);
329 return 0;
271 } 330 }
272 if (st.st_size > 1*1024*1024) { 331 if (st.st_size > 1*1024*1024) {
273 error("key file %.200s too large", filename); 332 error("%s: key file %.200s%stoo large", __func__,
274 return NULL; 333 filename == NULL ? "" : filename,
334 filename == NULL ? "" : " ");
335 close(fd);
336 return 0;
275 } 337 }
276 len = (size_t)st.st_size; /* truncated */ 338 len = (size_t)st.st_size; /* truncated */
277 339
278 buffer_init(&buffer); 340 buffer_init(blob);
279 cp = buffer_append_space(&buffer, len); 341 cp = buffer_append_space(blob, len);
280 342
281 if (atomicio(read, fd, cp, len) != len) { 343 if (atomicio(read, fd, cp, len) != len) {
282 debug("Read from key file %.200s failed: %.100s", filename, 344 debug("%s: read from key file %.200s%sfailed: %.100s", __func__,
345 filename == NULL ? "" : filename,
346 filename == NULL ? "" : " ",
283 strerror(errno)); 347 strerror(errno));
284 buffer_free(&buffer); 348 buffer_clear(blob);
285 return NULL; 349 close(fd);
350 return 0;
286 } 351 }
352 return 1;
353}
287 354
288 /* Check that it is at least big enough to contain the ID string. */ 355/*
289 if (len < sizeof(authfile_id_string)) { 356 * Loads the public part of the ssh v1 key file. Returns NULL if an error was
290 debug3("Not a RSA1 key file %.200s.", filename); 357 * encountered (the file does not exist or is not readable), and the key
358 * otherwise.
359 */
360static Key *
361key_load_public_rsa1(int fd, const char *filename, char **commentp)
362{
363 Buffer buffer;
364 Key *pub;
365
366 buffer_init(&buffer);
367 if (!key_load_file(fd, filename, &buffer)) {
291 buffer_free(&buffer); 368 buffer_free(&buffer);
292 return NULL; 369 return NULL;
293 } 370 }
294 /*
295 * Make sure it begins with the id string. Consume the id string
296 * from the buffer.
297 */
298 for (i = 0; i < sizeof(authfile_id_string); i++)
299 if (buffer_get_char(&buffer) != authfile_id_string[i]) {
300 debug3("Not a RSA1 key file %.200s.", filename);
301 buffer_free(&buffer);
302 return NULL;
303 }
304 /* Skip cipher type and reserved data. */
305 (void) buffer_get_char(&buffer); /* cipher type */
306 (void) buffer_get_int(&buffer); /* reserved */
307
308 /* Read the public key from the buffer. */
309 (void) buffer_get_int(&buffer);
310 pub = key_new(KEY_RSA1);
311 buffer_get_bignum(&buffer, pub->rsa->n);
312 buffer_get_bignum(&buffer, pub->rsa->e);
313 if (commentp)
314 *commentp = buffer_get_string(&buffer, NULL);
315 /* The encrypted private part is not parsed by this function. */
316 371
372 pub = key_parse_public_rsa1(&buffer, commentp);
373 if (pub == NULL)
374 debug3("Could not load \"%s\" as a RSA1 public key", filename);
317 buffer_free(&buffer); 375 buffer_free(&buffer);
318 return pub; 376 return pub;
319} 377}
@@ -336,113 +394,73 @@ key_load_public_type(int type, const char *filename, char **commentp)
336 return NULL; 394 return NULL;
337} 395}
338 396
339/*
340 * Loads the private key from the file. Returns 0 if an error is encountered
341 * (file does not exist or is not readable, or passphrase is bad). This
342 * initializes the private key.
343 * Assumes we are called under uid of the owner of the file.
344 */
345
346static Key * 397static Key *
347key_load_private_rsa1(int fd, const char *filename, const char *passphrase, 398key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
348 char **commentp)
349{ 399{
350 u_int i;
351 int check1, check2, cipher_type; 400 int check1, check2, cipher_type;
352 size_t len; 401 Buffer decrypted;
353 Buffer buffer, decrypted;
354 u_char *cp; 402 u_char *cp;
355 CipherContext ciphercontext; 403 CipherContext ciphercontext;
356 Cipher *cipher; 404 Cipher *cipher;
357 Key *prv = NULL; 405 Key *prv = NULL;
358 struct stat st;
359
360 if (fstat(fd, &st) < 0) {
361 error("fstat for key file %.200s failed: %.100s",
362 filename, strerror(errno));
363 close(fd);
364 return NULL;
365 }
366 if (st.st_size > 1*1024*1024) {
367 error("key file %.200s too large", filename);
368 close(fd);
369 return (NULL);
370 }
371 len = (size_t)st.st_size; /* truncated */
372
373 buffer_init(&buffer);
374 cp = buffer_append_space(&buffer, len);
375
376 if (atomicio(read, fd, cp, len) != len) {
377 debug("Read from key file %.200s failed: %.100s", filename,
378 strerror(errno));
379 buffer_free(&buffer);
380 close(fd);
381 return NULL;
382 }
383 406
384 /* Check that it is at least big enough to contain the ID string. */ 407 /* Check that it is at least big enough to contain the ID string. */
385 if (len < sizeof(authfile_id_string)) { 408 if (buffer_len(blob) < sizeof(authfile_id_string)) {
386 debug3("Not a RSA1 key file %.200s.", filename); 409 debug3("Truncated RSA1 identifier");
387 buffer_free(&buffer);
388 close(fd);
389 return NULL; 410 return NULL;
390 } 411 }
412
391 /* 413 /*
392 * Make sure it begins with the id string. Consume the id string 414 * Make sure it begins with the id string. Consume the id string
393 * from the buffer. 415 * from the buffer.
394 */ 416 */
395 for (i = 0; i < sizeof(authfile_id_string); i++) 417 if (memcmp(buffer_ptr(blob), authfile_id_string,
396 if (buffer_get_char(&buffer) != authfile_id_string[i]) { 418 sizeof(authfile_id_string)) != 0) {
397 debug3("Not a RSA1 key file %.200s.", filename); 419 debug3("Incorrect RSA1 identifier");
398 buffer_free(&buffer); 420 return NULL;
399 close(fd); 421 }
400 return NULL; 422 buffer_consume(blob, sizeof(authfile_id_string));
401 }
402 423
403 /* Read cipher type. */ 424 /* Read cipher type. */
404 cipher_type = buffer_get_char(&buffer); 425 cipher_type = buffer_get_char(blob);
405 (void) buffer_get_int(&buffer); /* Reserved data. */ 426 (void) buffer_get_int(blob); /* Reserved data. */
406 427
407 /* Read the public key from the buffer. */ 428 /* Read the public key from the buffer. */
408 (void) buffer_get_int(&buffer); 429 (void) buffer_get_int(blob);
409 prv = key_new_private(KEY_RSA1); 430 prv = key_new_private(KEY_RSA1);
410 431
411 buffer_get_bignum(&buffer, prv->rsa->n); 432 buffer_get_bignum(blob, prv->rsa->n);
412 buffer_get_bignum(&buffer, prv->rsa->e); 433 buffer_get_bignum(blob, prv->rsa->e);
413 if (commentp) 434 if (commentp)
414 *commentp = buffer_get_string(&buffer, NULL); 435 *commentp = buffer_get_string(blob, NULL);
415 else 436 else
416 xfree(buffer_get_string(&buffer, NULL)); 437 (void)buffer_get_string_ptr(blob, NULL);
417 438
418 /* Check that it is a supported cipher. */ 439 /* Check that it is a supported cipher. */
419 cipher = cipher_by_number(cipher_type); 440 cipher = cipher_by_number(cipher_type);
420 if (cipher == NULL) { 441 if (cipher == NULL) {
421 debug("Unsupported cipher %d used in key file %.200s.", 442 debug("Unsupported RSA1 cipher %d", cipher_type);
422 cipher_type, filename);
423 buffer_free(&buffer);
424 goto fail; 443 goto fail;
425 } 444 }
426 /* Initialize space for decrypted data. */ 445 /* Initialize space for decrypted data. */
427 buffer_init(&decrypted); 446 buffer_init(&decrypted);
428 cp = buffer_append_space(&decrypted, buffer_len(&buffer)); 447 cp = buffer_append_space(&decrypted, buffer_len(blob));
429 448
430 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 449 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
431 cipher_set_key_string(&ciphercontext, cipher, passphrase, 450 cipher_set_key_string(&ciphercontext, cipher, passphrase,
432 CIPHER_DECRYPT); 451 CIPHER_DECRYPT);
433 cipher_crypt(&ciphercontext, cp, 452 cipher_crypt(&ciphercontext, cp,
434 buffer_ptr(&buffer), buffer_len(&buffer)); 453 buffer_ptr(blob), buffer_len(blob));
435 cipher_cleanup(&ciphercontext); 454 cipher_cleanup(&ciphercontext);
436 memset(&ciphercontext, 0, sizeof(ciphercontext)); 455 memset(&ciphercontext, 0, sizeof(ciphercontext));
437 buffer_free(&buffer); 456 buffer_clear(blob);
438 457
439 check1 = buffer_get_char(&decrypted); 458 check1 = buffer_get_char(&decrypted);
440 check2 = buffer_get_char(&decrypted); 459 check2 = buffer_get_char(&decrypted);
441 if (check1 != buffer_get_char(&decrypted) || 460 if (check1 != buffer_get_char(&decrypted) ||
442 check2 != buffer_get_char(&decrypted)) { 461 check2 != buffer_get_char(&decrypted)) {
443 if (strcmp(passphrase, "") != 0) 462 if (strcmp(passphrase, "") != 0)
444 debug("Bad passphrase supplied for key file %.200s.", 463 debug("Bad passphrase supplied for RSA1 key");
445 filename);
446 /* Bad passphrase. */ 464 /* Bad passphrase. */
447 buffer_free(&decrypted); 465 buffer_free(&decrypted);
448 goto fail; 466 goto fail;
@@ -461,38 +479,37 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
461 479
462 /* enable blinding */ 480 /* enable blinding */
463 if (RSA_blinding_on(prv->rsa, NULL) != 1) { 481 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
464 error("key_load_private_rsa1: RSA_blinding_on failed"); 482 error("%s: RSA_blinding_on failed", __func__);
465 goto fail; 483 goto fail;
466 } 484 }
467 close(fd);
468 return prv; 485 return prv;
469 486
470fail: 487fail:
471 if (commentp) 488 if (commentp)
472 xfree(*commentp); 489 xfree(*commentp);
473 close(fd);
474 key_free(prv); 490 key_free(prv);
475 return NULL; 491 return NULL;
476} 492}
477 493
478Key * 494static Key *
479key_load_private_pem(int fd, int type, const char *passphrase, 495key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
480 char **commentp) 496 char **commentp)
481{ 497{
482 FILE *fp;
483 EVP_PKEY *pk = NULL; 498 EVP_PKEY *pk = NULL;
484 Key *prv = NULL; 499 Key *prv = NULL;
485 char *name = "<no key>"; 500 char *name = "<no key>";
501 BIO *bio;
486 502
487 fp = fdopen(fd, "r"); 503 if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
488 if (fp == NULL) { 504 buffer_len(blob))) == NULL) {
489 error("fdopen failed: %s", strerror(errno)); 505 error("%s: BIO_new_mem_buf failed", __func__);
490 close(fd);
491 return NULL; 506 return NULL;
492 } 507 }
493 pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); 508
509 pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
510 BIO_free(bio);
494 if (pk == NULL) { 511 if (pk == NULL) {
495 debug("PEM_read_PrivateKey failed"); 512 debug("%s: PEM_read_PrivateKey failed", __func__);
496 (void)ERR_get_error(); 513 (void)ERR_get_error();
497 } else if (pk->type == EVP_PKEY_RSA && 514 } else if (pk->type == EVP_PKEY_RSA &&
498 (type == KEY_UNSPEC||type==KEY_RSA)) { 515 (type == KEY_UNSPEC||type==KEY_RSA)) {
@@ -504,7 +521,7 @@ key_load_private_pem(int fd, int type, const char *passphrase,
504 RSA_print_fp(stderr, prv->rsa, 8); 521 RSA_print_fp(stderr, prv->rsa, 8);
505#endif 522#endif
506 if (RSA_blinding_on(prv->rsa, NULL) != 1) { 523 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
507 error("key_load_private_pem: RSA_blinding_on failed"); 524 error("%s: RSA_blinding_on failed", __func__);
508 key_free(prv); 525 key_free(prv);
509 prv = NULL; 526 prv = NULL;
510 } 527 }
@@ -539,10 +556,9 @@ key_load_private_pem(int fd, int type, const char *passphrase,
539#endif 556#endif
540#endif /* OPENSSL_HAS_ECC */ 557#endif /* OPENSSL_HAS_ECC */
541 } else { 558 } else {
542 error("PEM_read_PrivateKey: mismatch or " 559 error("%s: PEM_read_PrivateKey: mismatch or "
543 "unknown EVP_PKEY save_type %d", pk->save_type); 560 "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
544 } 561 }
545 fclose(fp);
546 if (pk != NULL) 562 if (pk != NULL)
547 EVP_PKEY_free(pk); 563 EVP_PKEY_free(pk);
548 if (prv != NULL && commentp) 564 if (prv != NULL && commentp)
@@ -552,6 +568,23 @@ key_load_private_pem(int fd, int type, const char *passphrase,
552 return prv; 568 return prv;
553} 569}
554 570
571Key *
572key_load_private_pem(int fd, int type, const char *passphrase,
573 char **commentp)
574{
575 Buffer buffer;
576 Key *prv;
577
578 buffer_init(&buffer);
579 if (!key_load_file(fd, NULL, &buffer)) {
580 buffer_free(&buffer);
581 return NULL;
582 }
583 prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
584 buffer_free(&buffer);
585 return prv;
586}
587
555int 588int
556key_perm_ok(int fd, const char *filename) 589key_perm_ok(int fd, const char *filename)
557{ 590{
@@ -580,11 +613,31 @@ key_perm_ok(int fd, const char *filename)
580 return 1; 613 return 1;
581} 614}
582 615
616static Key *
617key_parse_private_type(Buffer *blob, int type, const char *passphrase,
618 char **commentp)
619{
620 switch (type) {
621 case KEY_RSA1:
622 return key_parse_private_rsa1(blob, passphrase, commentp);
623 case KEY_DSA:
624 case KEY_ECDSA:
625 case KEY_RSA:
626 case KEY_UNSPEC:
627 return key_parse_private_pem(blob, type, passphrase, commentp);
628 default:
629 break;
630 }
631 return NULL;
632}
633
583Key * 634Key *
584key_load_private_type(int type, const char *filename, const char *passphrase, 635key_load_private_type(int type, const char *filename, const char *passphrase,
585 char **commentp, int *perm_ok) 636 char **commentp, int *perm_ok)
586{ 637{
587 int fd; 638 int fd;
639 Key *ret;
640 Buffer buffer;
588 641
589 fd = open(filename, O_RDONLY); 642 fd = open(filename, O_RDONLY);
590 if (fd < 0) { 643 if (fd < 0) {
@@ -603,22 +656,17 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
603 } 656 }
604 if (perm_ok != NULL) 657 if (perm_ok != NULL)
605 *perm_ok = 1; 658 *perm_ok = 1;
606 switch (type) { 659
607 case KEY_RSA1: 660 buffer_init(&buffer);
608 return key_load_private_rsa1(fd, filename, passphrase, 661 if (!key_load_file(fd, filename, &buffer)) {
609 commentp); 662 buffer_free(&buffer);
610 /* closes fd */
611 case KEY_DSA:
612 case KEY_ECDSA:
613 case KEY_RSA:
614 case KEY_UNSPEC:
615 return key_load_private_pem(fd, type, passphrase, commentp);
616 /* closes fd */
617 default:
618 close(fd); 663 close(fd);
619 break; 664 return NULL;
620 } 665 }
621 return NULL; 666 close(fd);
667 ret = key_parse_private_type(&buffer, type, passphrase, commentp);
668 buffer_free(&buffer);
669 return ret;
622} 670}
623 671
624Key * 672Key *
@@ -626,6 +674,7 @@ key_load_private(const char *filename, const char *passphrase,
626 char **commentp) 674 char **commentp)
627{ 675{
628 Key *pub, *prv; 676 Key *pub, *prv;
677 Buffer buffer, pubcopy;
629 int fd; 678 int fd;
630 679
631 fd = open(filename, O_RDONLY); 680 fd = open(filename, O_RDONLY);
@@ -639,20 +688,32 @@ key_load_private(const char *filename, const char *passphrase,
639 close(fd); 688 close(fd);
640 return NULL; 689 return NULL;
641 } 690 }
642 pub = key_load_public_rsa1(fd, filename, commentp); 691
643 lseek(fd, (off_t) 0, SEEK_SET); /* rewind */ 692 buffer_init(&buffer);
693 if (!key_load_file(fd, filename, &buffer)) {
694 buffer_free(&buffer);
695 close(fd);
696 return NULL;
697 }
698 close(fd);
699
700 buffer_init(&pubcopy);
701 buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer));
702 /* it's a SSH v1 key if the public key part is readable */
703 pub = key_parse_public_rsa1(&pubcopy, commentp);
704 buffer_free(&pubcopy);
644 if (pub == NULL) { 705 if (pub == NULL) {
645 /* closes fd */ 706 prv = key_parse_private_type(&buffer, KEY_UNSPEC,
646 prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); 707 passphrase, NULL);
647 /* use the filename as a comment for PEM */ 708 /* use the filename as a comment for PEM */
648 if (commentp && prv) 709 if (commentp && prv)
649 *commentp = xstrdup(filename); 710 *commentp = xstrdup(filename);
650 } else { 711 } else {
651 /* it's a SSH v1 key if the public key part is readable */
652 key_free(pub); 712 key_free(pub);
653 /* closes fd */ 713 prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase,
654 prv = key_load_private_rsa1(fd, filename, passphrase, NULL); 714 commentp);
655 } 715 }
716 buffer_free(&buffer);
656 return prv; 717 return prv;
657} 718}
658 719