1 /*
   2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
   3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
   4  *                    All rights reserved
   5  * This file contains functions for reading and writing identity files, and
   6  * for reading the passphrase from the user.
   7  *
   8  * As far as I am concerned, the code I have written for this software
   9  * can be used freely for any purpose.  Any derived versions of this
  10  * software must be clearly marked as such, and if the derived work is
  11  * incompatible with the protocol description in the RFC file, it must be
  12  * called by a name other than "ssh" or "Secure Shell".
  13  *
  14  *
  15  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  16  *
  17  * Redistribution and use in source and binary forms, with or without
  18  * modification, are permitted provided that the following conditions
  19  * are met:
  20  * 1. Redistributions of source code must retain the above copyright
  21  *    notice, this list of conditions and the following disclaimer.
  22  * 2. Redistributions in binary form must reproduce the above copyright
  23  *    notice, this list of conditions and the following disclaimer in the
  24  *    documentation and/or other materials provided with the distribution.
  25  *
  26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36  */
  37 
  38 #include "includes.h"
  39 RCSID("$OpenBSD: authfile.c,v 1.50 2002/06/24 14:55:38 markus Exp $");
  40 
  41 #pragma ident   "%Z%%M% %I%     %E% SMI"
  42 
  43 #include <openssl/opensslconf.h>
  44 #include <openssl/err.h>
  45 #include <openssl/evp.h>
  46 #include <openssl/pem.h>
  47 
  48 #include "cipher.h"
  49 #include "xmalloc.h"
  50 #include "buffer.h"
  51 #include "bufaux.h"
  52 #include "key.h"
  53 #include "ssh.h"
  54 #include "log.h"
  55 #include "authfile.h"
  56 #include "rsa.h"
  57 
  58 /* Version identification string for SSH v1 identity files. */
  59 static const char authfile_id_string[] =
  60     "SSH PRIVATE KEY FILE FORMAT 1.1\n";
  61 
  62 /*
  63  * Saves the authentication (private) key in a file, encrypting it with
  64  * passphrase.  The identification of the file (lowest 64 bits of n) will
  65  * precede the key to provide identification of the key without needing a
  66  * passphrase.
  67  */
  68 
  69 static int
  70 key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
  71     const char *comment)
  72 {
  73         Buffer buffer, encrypted;
  74         u_char buf[100], *cp;
  75         int fd, i, cipher_num;
  76         CipherContext ciphercontext;
  77         Cipher *cipher;
  78         u_int32_t rand;
  79 
  80         /*
  81          * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
  82          * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
  83          */
  84         cipher_num = (strcmp(passphrase, "") == 0) ?
  85             SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
  86         if ((cipher = cipher_by_number(cipher_num)) == NULL)
  87                 fatal("save_private_key_rsa: bad cipher");
  88 
  89         /* This buffer is used to built the secret part of the private key. */
  90         buffer_init(&buffer);
  91 
  92         /* Put checkbytes for checking passphrase validity. */
  93         rand = arc4random();
  94         buf[0] = rand & 0xff;
  95         buf[1] = (rand >> 8) & 0xff;
  96         buf[2] = buf[0];
  97         buf[3] = buf[1];
  98         buffer_append(&buffer, buf, 4);
  99 
 100         /*
 101          * Store the private key (n and e will not be stored because they
 102          * will be stored in plain text, and storing them also in encrypted
 103          * format would just give known plaintext).
 104          */
 105         buffer_put_bignum(&buffer, key->rsa->d);
 106         buffer_put_bignum(&buffer, key->rsa->iqmp);
 107         buffer_put_bignum(&buffer, key->rsa->q);      /* reverse from SSL p */
 108         buffer_put_bignum(&buffer, key->rsa->p);      /* reverse from SSL q */
 109 
 110         /* Pad the part to be encrypted until its size is a multiple of 8. */
 111         while (buffer_len(&buffer) % 8 != 0)
 112                 buffer_put_char(&buffer, 0);
 113 
 114         /* This buffer will be used to contain the data in the file. */
 115         buffer_init(&encrypted);
 116 
 117         /* First store keyfile id string. */
 118         for (i = 0; authfile_id_string[i]; i++)
 119                 buffer_put_char(&encrypted, authfile_id_string[i]);
 120         buffer_put_char(&encrypted, 0);
 121 
 122         /* Store cipher type. */
 123         buffer_put_char(&encrypted, cipher_num);
 124         buffer_put_int(&encrypted, 0);      /* For future extension */
 125 
 126         /* Store public key.  This will be in plain text. */
 127         buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
 128         buffer_put_bignum(&encrypted, key->rsa->n);
 129         buffer_put_bignum(&encrypted, key->rsa->e);
 130         buffer_put_cstring(&encrypted, comment);
 131 
 132         /* Allocate space for the private part of the key in the buffer. */
 133         cp = buffer_append_space(&encrypted, buffer_len(&buffer));
 134 
 135         cipher_set_key_string(&ciphercontext, cipher, passphrase,
 136             CIPHER_ENCRYPT);
 137         cipher_crypt(&ciphercontext, cp,
 138             buffer_ptr(&buffer), buffer_len(&buffer));
 139         cipher_cleanup(&ciphercontext);
 140         memset(&ciphercontext, 0, sizeof(ciphercontext));
 141 
 142         /* Destroy temporary data. */
 143         memset(buf, 0, sizeof(buf));
 144         buffer_free(&buffer);
 145 
 146         fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 147         if (fd < 0) {
 148                 error("open %s failed: %s.", filename, strerror(errno));
 149                 return 0;
 150         }
 151         if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
 152             buffer_len(&encrypted)) {
 153                 error("write to key file %s failed: %s", filename,
 154                     strerror(errno));
 155                 buffer_free(&encrypted);
 156                 close(fd);
 157                 unlink(filename);
 158                 return 0;
 159         }
 160         close(fd);
 161         buffer_free(&encrypted);
 162         return 1;
 163 }
 164 
 165 /* save SSH v2 key in OpenSSL PEM format */
 166 static int
 167 key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
 168     const char *comment)
 169 {
 170         FILE *fp;
 171         int fd;
 172         int success = 0;
 173         int len = strlen(_passphrase);
 174         u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
 175         const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
 176 
 177         if (len > 0 && len <= 4) {
 178                 error("passphrase too short: have %d bytes, need > 4", len);
 179                 return 0;
 180         }
 181         fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 182         if (fd < 0) {
 183                 error("open %s failed: %s.", filename, strerror(errno));
 184                 return 0;
 185         }
 186         fp = fdopen(fd, "w");
 187         if (fp == NULL ) {
 188                 error("fdopen %s failed: %s.", filename, strerror(errno));
 189                 close(fd);
 190                 return 0;
 191         }
 192         switch (key->type) {
 193         case KEY_DSA:
 194                 success = PEM_write_DSAPrivateKey(fp, key->dsa,
 195                     cipher, passphrase, len, NULL, NULL);
 196                 break;
 197         case KEY_RSA:
 198                 success = PEM_write_RSAPrivateKey(fp, key->rsa,
 199                     cipher, passphrase, len, NULL, NULL);
 200                 break;
 201         }
 202         fclose(fp);
 203         return success;
 204 }
 205 
 206 int
 207 key_save_private(Key *key, const char *filename, const char *passphrase,
 208     const char *comment)
 209 {
 210         switch (key->type) {
 211         case KEY_RSA1:
 212                 return key_save_private_rsa1(key, filename, passphrase,
 213                     comment);
 214                 break;
 215         case KEY_DSA:
 216         case KEY_RSA:
 217                 return key_save_private_pem(key, filename, passphrase,
 218                     comment);
 219                 break;
 220         default:
 221                 break;
 222         }
 223         error("key_save_private: cannot save key type %d", key->type);
 224         return 0;
 225 }
 226 
 227 /*
 228  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
 229  * encountered (the file does not exist or is not readable), and the key
 230  * otherwise.
 231  */
 232 
 233 static Key *
 234 key_load_public_rsa1(int fd, const char *filename, char **commentp)
 235 {
 236         Buffer buffer;
 237         Key *pub;
 238         char *cp;
 239         int i;
 240         off_t len;
 241 
 242         len = lseek(fd, (off_t) 0, SEEK_END);
 243         lseek(fd, (off_t) 0, SEEK_SET);
 244 
 245         buffer_init(&buffer);
 246         cp = buffer_append_space(&buffer, len);
 247 
 248         if (read(fd, cp, (size_t) len) != (size_t) len) {
 249                 debug("Read from key file %.200s failed: %.100s", filename,
 250                     strerror(errno));
 251                 buffer_free(&buffer);
 252                 return NULL;
 253         }
 254 
 255         /* Check that it is at least big enough to contain the ID string. */
 256         if (len < sizeof(authfile_id_string)) {
 257                 debug3("Not a RSA1 key file %.200s.", filename);
 258                 buffer_free(&buffer);
 259                 return NULL;
 260         }
 261         /*
 262          * Make sure it begins with the id string.  Consume the id string
 263          * from the buffer.
 264          */
 265         for (i = 0; i < sizeof(authfile_id_string); i++)
 266                 if (buffer_get_char(&buffer) != authfile_id_string[i]) {
 267                         debug3("Not a RSA1 key file %.200s.", filename);
 268                         buffer_free(&buffer);
 269                         return NULL;
 270                 }
 271         /* Skip cipher type and reserved data. */
 272         (void) buffer_get_char(&buffer);    /* cipher type */
 273         (void) buffer_get_int(&buffer);             /* reserved */
 274 
 275         /* Read the public key from the buffer. */
 276         (void) buffer_get_int(&buffer);
 277         pub = key_new(KEY_RSA1);
 278         buffer_get_bignum(&buffer, pub->rsa->n);
 279         buffer_get_bignum(&buffer, pub->rsa->e);
 280         if (commentp)
 281                 *commentp = buffer_get_string(&buffer, NULL);
 282         /* The encrypted private part is not parsed by this function. */
 283 
 284         buffer_free(&buffer);
 285         return pub;
 286 }
 287 
 288 /* load public key from private-key file, works only for SSH v1 */
 289 Key *
 290 key_load_public_type(int type, const char *filename, char **commentp)
 291 {
 292         Key *pub;
 293         int fd;
 294 
 295         if (type == KEY_RSA1) {
 296                 fd = open(filename, O_RDONLY);
 297                 if (fd < 0)
 298                         return NULL;
 299                 pub = key_load_public_rsa1(fd, filename, commentp);
 300                 close(fd);
 301                 return pub;
 302         }
 303         return NULL;
 304 }
 305 
 306 /*
 307  * Loads the private key from the file.  Returns 0 if an error is encountered
 308  * (file does not exist or is not readable, or passphrase is bad). This
 309  * initializes the private key.
 310  * Assumes we are called under uid of the owner of the file.
 311  */
 312 
 313 static Key *
 314 key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
 315     char **commentp)
 316 {
 317         int i, check1, check2, cipher_type;
 318         off_t len;
 319         Buffer buffer, decrypted;
 320         u_char *cp;
 321         CipherContext ciphercontext;
 322         Cipher *cipher;
 323         Key *prv = NULL;
 324 
 325         len = lseek(fd, (off_t) 0, SEEK_END);
 326         lseek(fd, (off_t) 0, SEEK_SET);
 327 
 328         buffer_init(&buffer);
 329         cp = buffer_append_space(&buffer, len);
 330 
 331         if (read(fd, cp, (size_t) len) != (size_t) len) {
 332                 debug("Read from key file %.200s failed: %.100s", filename,
 333                     strerror(errno));
 334                 buffer_free(&buffer);
 335                 close(fd);
 336                 return NULL;
 337         }
 338 
 339         /* Check that it is at least big enough to contain the ID string. */
 340         if (len < sizeof(authfile_id_string)) {
 341                 debug3("Not a RSA1 key file %.200s.", filename);
 342                 buffer_free(&buffer);
 343                 close(fd);
 344                 return NULL;
 345         }
 346         /*
 347          * Make sure it begins with the id string.  Consume the id string
 348          * from the buffer.
 349          */
 350         for (i = 0; i < sizeof(authfile_id_string); i++)
 351                 if (buffer_get_char(&buffer) != authfile_id_string[i]) {
 352                         debug3("Not a RSA1 key file %.200s.", filename);
 353                         buffer_free(&buffer);
 354                         close(fd);
 355                         return NULL;
 356                 }
 357 
 358         /* Read cipher type. */
 359         cipher_type = buffer_get_char(&buffer);
 360         (void) buffer_get_int(&buffer);     /* Reserved data. */
 361 
 362         /* Read the public key from the buffer. */
 363         (void) buffer_get_int(&buffer);
 364         prv = key_new_private(KEY_RSA1);
 365 
 366         buffer_get_bignum(&buffer, prv->rsa->n);
 367         buffer_get_bignum(&buffer, prv->rsa->e);
 368         if (commentp)
 369                 *commentp = buffer_get_string(&buffer, NULL);
 370         else
 371                 xfree(buffer_get_string(&buffer, NULL));
 372 
 373         /* Check that it is a supported cipher. */
 374         cipher = cipher_by_number(cipher_type);
 375         if (cipher == NULL) {
 376                 debug("Unsupported cipher %d used in key file %.200s.",
 377                     cipher_type, filename);
 378                 buffer_free(&buffer);
 379                 goto fail;
 380         }
 381         /* Initialize space for decrypted data. */
 382         buffer_init(&decrypted);
 383         cp = buffer_append_space(&decrypted, buffer_len(&buffer));
 384 
 385         /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
 386         cipher_set_key_string(&ciphercontext, cipher, passphrase,
 387             CIPHER_DECRYPT);
 388         cipher_crypt(&ciphercontext, cp,
 389             buffer_ptr(&buffer), buffer_len(&buffer));
 390         cipher_cleanup(&ciphercontext);
 391         memset(&ciphercontext, 0, sizeof(ciphercontext));
 392         buffer_free(&buffer);
 393 
 394         check1 = buffer_get_char(&decrypted);
 395         check2 = buffer_get_char(&decrypted);
 396         if (check1 != buffer_get_char(&decrypted) ||
 397             check2 != buffer_get_char(&decrypted)) {
 398                 if (strcmp(passphrase, "") != 0)
 399                         debug("Bad passphrase supplied for key file %.200s.",
 400                             filename);
 401                 /* Bad passphrase. */
 402                 buffer_free(&decrypted);
 403                 goto fail;
 404         }
 405         /* Read the rest of the private key. */
 406         buffer_get_bignum(&decrypted, prv->rsa->d);
 407         buffer_get_bignum(&decrypted, prv->rsa->iqmp);                /* u */
 408         /* in SSL and SSH v1 p and q are exchanged */
 409         buffer_get_bignum(&decrypted, prv->rsa->q);           /* p */
 410         buffer_get_bignum(&decrypted, prv->rsa->p);           /* q */
 411 
 412         /* calculate p-1 and q-1 */
 413         rsa_generate_additional_parameters(prv->rsa);
 414 
 415         buffer_free(&decrypted);
 416         close(fd);
 417         return prv;
 418 
 419 fail:
 420         if (commentp)
 421                 xfree(*commentp);
 422         close(fd);
 423         key_free(prv);
 424         return NULL;
 425 }
 426 
 427 Key *
 428 key_load_private_pem(int fd, int type, const char *passphrase,
 429     char **commentp)
 430 {
 431         FILE *fp;
 432         EVP_PKEY *pk = NULL;
 433         Key *prv = NULL;
 434         char *name = "<no key>";
 435 
 436         fp = fdopen(fd, "r");
 437         if (fp == NULL) {
 438                 error("fdopen failed: %s", strerror(errno));
 439                 close(fd);
 440                 return NULL;
 441         }
 442         pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
 443         if (pk == NULL) {
 444                 debug("PEM_read_PrivateKey failed");
 445                 (void)ERR_get_error();
 446         } else if (pk->type == EVP_PKEY_RSA &&
 447             (type == KEY_UNSPEC||type==KEY_RSA)) {
 448                 prv = key_new(KEY_UNSPEC);
 449                 prv->rsa = EVP_PKEY_get1_RSA(pk);
 450                 prv->type = KEY_RSA;
 451                 name = "rsa w/o comment";
 452 #ifdef DEBUG_PK
 453                 RSA_print_fp(stderr, prv->rsa, 8);
 454 #endif
 455         } else if (pk->type == EVP_PKEY_DSA &&
 456             (type == KEY_UNSPEC||type==KEY_DSA)) {
 457                 prv = key_new(KEY_UNSPEC);
 458                 prv->dsa = EVP_PKEY_get1_DSA(pk);
 459                 prv->type = KEY_DSA;
 460                 name = "dsa w/o comment";
 461 #ifdef DEBUG_PK
 462                 DSA_print_fp(stderr, prv->dsa, 8);
 463 #endif
 464         } else {
 465                 error("PEM_read_PrivateKey: mismatch or "
 466                     "unknown EVP_PKEY save_type %d", pk->save_type);
 467         }
 468         fclose(fp);
 469         if (pk != NULL)
 470                 EVP_PKEY_free(pk);
 471         if (prv != NULL && commentp)
 472                 *commentp = xstrdup(name);
 473         debug("read PEM private key done: type %s",
 474             prv ? key_type(prv) : "<unknown>");
 475         return prv;
 476 }
 477 
 478 static int
 479 key_perm_ok(int fd, const char *filename)
 480 {
 481         struct stat st;
 482 
 483         if (fstat(fd, &st) < 0)
 484                 return 0;
 485         /*
 486          * if a key owned by the user is accessed, then we check the
 487          * permissions of the file. if the key owned by a different user,
 488          * then we don't care.
 489          */
 490 #ifdef HAVE_CYGWIN
 491         if (check_ntsec(filename))
 492 #endif
 493         if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
 494                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 495                 error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
 496                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 497                 error("Permissions 0%3.3o for '%s' are too open.",
 498                     (int)(st.st_mode & 0777), filename);
 499                 error("It is recommended that your private key files are NOT accessible by others.");
 500                 error("This private key will be ignored.");
 501                 return 0;
 502         }
 503         return 1;
 504 }
 505 
 506 Key *
 507 key_load_private_type(int type, const char *filename, const char *passphrase,
 508     char **commentp)
 509 {
 510         int fd;
 511 
 512         fd = open(filename, O_RDONLY);
 513         if (fd < 0)
 514                 return NULL;
 515         if (!key_perm_ok(fd, filename)) {
 516                 error("bad permissions: ignore key: %s", filename);
 517                 close(fd);
 518                 return NULL;
 519         }
 520         switch (type) {
 521         case KEY_RSA1:
 522                 return key_load_private_rsa1(fd, filename, passphrase,
 523                     commentp);
 524                 /* closes fd */
 525                 break;
 526         case KEY_DSA:
 527         case KEY_RSA:
 528         case KEY_UNSPEC:
 529                 return key_load_private_pem(fd, type, passphrase, commentp);
 530                 /* closes fd */
 531                 break;
 532         default:
 533                 close(fd);
 534                 break;
 535         }
 536         return NULL;
 537 }
 538 
 539 Key *
 540 key_load_private(const char *filename, const char *passphrase,
 541     char **commentp)
 542 {
 543         Key *pub, *prv;
 544         int fd;
 545 
 546         fd = open(filename, O_RDONLY);
 547         if (fd < 0)
 548                 return NULL;
 549         if (!key_perm_ok(fd, filename)) {
 550                 error("bad permissions: ignore key: %s", filename);
 551                 close(fd);
 552                 return NULL;
 553         }
 554         pub = key_load_public_rsa1(fd, filename, commentp);
 555         lseek(fd, (off_t) 0, SEEK_SET);         /* rewind */
 556         if (pub == NULL) {
 557                 /* closes fd */
 558                 prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
 559                 /* use the filename as a comment for PEM */
 560                 if (commentp && prv)
 561                         *commentp = xstrdup(filename);
 562         } else {
 563                 /* it's a SSH v1 key if the public key part is readable */
 564                 key_free(pub);
 565                 /* closes fd */
 566                 prv = key_load_private_rsa1(fd, filename, passphrase, NULL);
 567         }
 568         return prv;
 569 }
 570 
 571 static int
 572 key_try_load_public(Key *k, const char *filename, char **commentp)
 573 {
 574         FILE *f;
 575         char line[4096];
 576         char *cp;
 577 
 578         f = fopen(filename, "r");
 579         if (f != NULL) {
 580                 while (fgets(line, sizeof(line), f)) {
 581                         line[sizeof(line)-1] = '\0';
 582                         cp = line;
 583                         switch (*cp) {
 584                         case '#':
 585                         case '\n':
 586                         case '\0':
 587                                 continue;
 588                         }
 589                         /* Skip leading whitespace. */
 590                         for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
 591                                 ;
 592                         if (*cp) {
 593                                 if (key_read(k, &cp) == 1) {
 594                                         if (commentp)
 595                                                 *commentp=xstrdup(filename);
 596                                         fclose(f);
 597                                         return 1;
 598                                 }
 599                         }
 600                 }
 601                 fclose(f);
 602         }
 603         return 0;
 604 }
 605 
 606 /* load public key from ssh v1 private or any pubkey file */
 607 Key *
 608 key_load_public(const char *filename, char **commentp)
 609 {
 610         Key *pub;
 611         char file[MAXPATHLEN];
 612 
 613         pub = key_load_public_type(KEY_RSA1, filename, commentp);
 614         if (pub != NULL)
 615                 return pub;
 616         pub = key_new(KEY_UNSPEC);
 617         if (key_try_load_public(pub, filename, commentp) == 1)
 618                 return pub;
 619         if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
 620             (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
 621             (key_try_load_public(pub, file, commentp) == 1))
 622                 return pub;
 623         key_free(pub);
 624         return NULL;
 625 }