mixmaster

mixmaster 3.0 patched for libressl
git clone git://parazyd.org/mixmaster.git
Log | Files | Refs | README

pgpget.c (18668B)


      1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
      2 
      3    Mixmaster may be redistributed and modified under certain conditions.
      4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
      5    ANY KIND, either express or implied. See the file COPYRIGHT for
      6    details.
      7 
      8    Read OpenPGP packets
      9    $Id: pgpget.c 934 2006-06-24 13:40:39Z rabbi $ */
     10 
     11 
     12 #include "mix3.h"
     13 #ifdef USE_PGP
     14 #include "pgp.h"
     15 #include "crypto.h"
     16 #include <time.h>
     17 #include <assert.h>
     18 #include <string.h>
     19 
     20 int pgp_getmsg(BUFFER *in, BUFFER *key, BUFFER *sig, char *pubring,
     21 	       char *secring)
     22 {
     23   BUFFER *p;
     24   BUFFER *out;
     25   int type, algo = 0;
     26   int err = PGP_NOMSG;
     27   pgpsig signature = {0, NULL, 0, 0, {0,} };
     28 
     29   p = buf_new();
     30   out = buf_new();
     31 
     32   if (sig)
     33     signature.userid = buf_new();
     34 
     35   while ((type = pgp_getpacket(in, p)) > 0)
     36     switch (type) {
     37     case PGP_LITERAL:
     38       pgp_getliteral(p);
     39       buf_move(out, p);
     40       err = 0;
     41       break;
     42     case PGP_COMPRESSED:
     43       err = pgp_uncompress(p);
     44       if (err == 0)
     45 	err = pgp_getmsg(p, key, sig, pubring, secring);
     46       if (err != PGP_ERR && err != PGP_PASS)
     47 	buf_move(out, p);
     48       break;
     49     case PGP_ENCRYPTED:
     50     case PGP_ENCRYPTEDMDC:
     51       if (!key) {
     52 	err = -1;
     53 	break;
     54       }
     55       if (/*key->length > 0 &&*/ algo == 0) {
     56 	algo = PGP_K_IDEA;
     57 	digest_md5(key, key);
     58       }
     59       if (key->length > 0)
     60 	err = pgp_getsymmetric(p, key, algo, type==PGP_ENCRYPTEDMDC);
     61       else
     62 	err = -1;
     63       if (err == 0)
     64 	err = pgp_getmsg(p, NULL, sig, pubring, secring);
     65       if (err != PGP_ERR)
     66 	buf_move(out, p);
     67       break;
     68     case PGP_SESKEY:
     69       if (!key) {
     70 	err = -1;
     71 	break;
     72       }
     73       err = pgp_getsessionkey(p, key, secring);
     74       if (err >= 0) {
     75 	algo = err;
     76 	err = 0;
     77 	buf_set(key, p);
     78       }
     79       break;
     80     case PGP_SYMSESKEY:
     81       if (!key) {
     82 	err = -1;
     83 	break;
     84       }
     85       err = pgp_getsymsessionkey(p, key);
     86       if (err >= 0) {
     87 	algo = err;
     88 	err = 0;
     89 	if (key) buf_set(key, p);
     90       }
     91       break;
     92     case PGP_MARKER:
     93 	err = 0;
     94 	break; /* ignore per RFC2440 */
     95     case PGP_SIG:
     96       pgp_getsig(p, &signature, pubring);
     97       /* fallthru */
     98     default:
     99       if (err == PGP_NOMSG)
    100 	err = PGP_NODATA;
    101     }
    102 
    103   if (signature.ok == PGP_SIGVRFY)
    104     pgp_verify(out, sig, &signature);
    105   if (signature.ok == PGP_SIGOK) {
    106     char line[LINELEN];
    107     time_t t;
    108     struct tm *tc;
    109 
    110     t = signature.sigtime;
    111     tc = localtime(&t);
    112 #if 0
    113     strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S]", tc);
    114 #else /* end of 0 */
    115     strftime(line, LINELEN, "[%a %b %d %H:%M:%S %Y]", tc);
    116 #endif /* else if not 0 */
    117     if (sig) {
    118       buf_cat(sig, signature.userid);
    119       buf_appendc(sig, ' ');
    120       buf_appends(sig, line);
    121     }
    122   }
    123   if (sig) {
    124     if (signature.ok == PGP_SIGNKEY)
    125       buf_appendf(sig, "%02X%02X%02X%02X", signature.userid->data[4],
    126 		  signature.userid->data[5], signature.userid->data[6],
    127 		  signature.userid->data[7]);
    128     buf_free(signature.userid);
    129   }
    130 
    131   if ((err == 0 || err == PGP_NODATA) && signature.ok != 0)
    132     err = signature.ok;
    133 
    134   buf_move(in, out);
    135   buf_free(out);
    136   buf_free(p);
    137 
    138   return (err);
    139 }
    140 
    141 int pgp_ispacket(BUFFER *b)
    142 {
    143   return ((b->data[b->ptr] >> 6) == 2 || (b->data[b->ptr] >> 6) == 3);
    144 }
    145 
    146 int pgp_packettype(BUFFER *b, long *len, int *partial)
    147 {
    148   int ctb;
    149 
    150   ctb = buf_getc(b);
    151   switch (ctb >> 6) {
    152   case 2:
    153     /* old packet type */
    154     switch (ctb & 3) {
    155     case 0:
    156       *len = buf_getc(b);
    157       break;
    158     case 1:
    159       *len = buf_geti(b);
    160       break;
    161     case 2:
    162       *len = buf_getl(b);
    163       break;
    164     case 3:
    165       *len = b->length - b->ptr;
    166       break;
    167     }
    168     *partial = 0;
    169     return (ctb >> 2) & 15;
    170   case 3:
    171   case 1: /* in GnuPG secret key ring */
    172     /* new packet type */
    173     *len = buf_getc(b);
    174     if (*len >= 192 && *len <= 223)
    175       *len = (*len - 192) * 256 + buf_getc(b) + 192;
    176     else if (*len == 255)
    177       *len = buf_getl(b);
    178     else if (*len > 223) {
    179       *len = 1 <<(*len & 0x1f);
    180       *partial = 1;
    181     }
    182     return (ctb & 63);
    183   }
    184   return (-1);
    185 }
    186 
    187 int pgp_packetpartial(BUFFER *b, long *len, int *partial)
    188 {
    189   *partial = 0;
    190   *len = buf_getc(b);
    191   if (*len >= 192 && *len <= 223)
    192     *len = (*len - 192) * 256 + buf_getc(b) + 192;
    193   else if (*len == 255)
    194     *len = buf_getl(b);
    195   else if (*len > 223) {
    196     *len = 1 <<(*len & 0x1f);
    197     *partial = 1;
    198   }
    199   return 1;
    200 }
    201 
    202 int pgp_isconventional(BUFFER *b)
    203 {
    204   int type;
    205   BUFFER *p;
    206   p = buf_new();
    207 
    208   type = pgp_getpacket(b, p);
    209   if (type == PGP_MARKER)
    210     type = pgp_getpacket(b, p);
    211   buf_rewind(b);
    212   buf_free(p);
    213   return (type == PGP_ENCRYPTED || type == PGP_SYMSESKEY);
    214 }
    215 
    216 int pgp_getpacket(BUFFER *in, BUFFER *p)
    217      /*  returns <0 = error, >0 = packet type */
    218 {
    219   int type;
    220   long len;
    221   int partial = 0;
    222   BUFFER *tmp;
    223 
    224   tmp = buf_new();
    225   type = pgp_packettype(in, &len, &partial);
    226   if (type > 0 && len > 0) {
    227     buf_clear(p);
    228     while(partial && len > 0) {
    229       buf_get(in, tmp, len);
    230       buf_cat(p, tmp);
    231       pgp_packetpartial(in, &len, &partial);
    232     }
    233     if (len > 0) {
    234       buf_get(in, tmp, len);
    235       buf_cat(p, tmp);
    236     }
    237   }
    238 
    239   buf_free(tmp);
    240   return (type);
    241 }
    242 
    243 int pgp_getsig(BUFFER *p, pgpsig *sig, char *pubring)
    244 {
    245   BUFFER *sigkey, *id, *i;
    246   int algo, hashalgo;
    247   int hash;
    248 
    249   sigkey = buf_new();
    250   id = buf_new();
    251   i = buf_new();
    252 
    253   sig->ok = PGP_SIGBAD;
    254 
    255   if (buf_getc(p) > 3)
    256     goto end;
    257   if (buf_getc(p) != 5)
    258     goto end;
    259   sig->sigtype = buf_getc(p);
    260   sig->sigtime = buf_getl(p);
    261   buf_get(p, id, 8);
    262   algo = buf_getc(p);
    263   hashalgo = buf_getc(p);
    264   if (hashalgo != PGP_H_MD5)
    265     goto end;
    266   hash = buf_geti(p);
    267   if (pgpdb_getkey(PK_VERIFY, algo, NULL, NULL, NULL, sigkey, NULL, sig->userid, id,
    268 		   pubring, NULL) < 0) {
    269     sig->ok = PGP_SIGNKEY;
    270     if (sig->userid)
    271       buf_set(sig->userid, id);
    272     goto end;
    273   }
    274   switch (algo) {
    275   case PGP_ES_RSA:
    276     mpi_get(p, i);
    277     if (pgp_rsa(i, sigkey, PK_VERIFY) == -1 ||
    278 	memcmp(i->data, MD5PREFIX, sizeof(MD5PREFIX) - 1) != 0)
    279       goto end;
    280     memcpy(sig->hash, i->data + sizeof(MD5PREFIX) - 1, 16);
    281     if (sig->hash[0] * 256 + sig->hash[1] != hash)
    282       goto end;
    283     sig->ok = PGP_SIGVRFY;
    284     break;
    285   default:
    286     break;
    287   }
    288 end:
    289   buf_free(sigkey);
    290   buf_free(id);
    291   buf_free(i);
    292   return (sig->ok);
    293 }
    294 
    295 void pgp_verify(BUFFER *msg, BUFFER *detached, pgpsig *sig)
    296 {
    297   MD5_CTX c;
    298   BUFFER *t;
    299   byte md[16];
    300 
    301   t = buf_new();
    302   sig->ok = PGP_SIGBAD;
    303 
    304   if (msg->length == 0) {	/* detached signature */
    305     if (detached && detached->length) {
    306       buf_move(msg, detached);
    307       if (sig->sigtype == PGP_SIG_CANONIC)
    308 	pgp_sigcanonic(msg); /* for cleartext signatures */
    309     } else
    310       sig->ok = PGP_NODATA;
    311   }
    312   MD5_Init(&c);
    313   switch (sig->sigtype) {
    314   case PGP_SIG_BINARY:
    315     MD5_Update(&c, msg->data, msg->length);
    316     break;
    317   case PGP_SIG_CANONIC:
    318     while (buf_getline(msg, t) != -1) {
    319 #if 0
    320       pgp_sigcanonic(t); /* according to OpenPGP */
    321 #else /* end of 0 */
    322       buf_appends(t, "\r\n");
    323 #endif /* else if not 0 */
    324       MD5_Update(&c, t->data, t->length);
    325     }
    326     break;
    327   default:
    328     sig->ok = PGP_SIGBAD;
    329   }
    330   MD5_Update(&c, &(sig->sigtype), 1);
    331   buf_appendl(t, sig->sigtime);
    332   MD5_Update(&c, t->data, 4);
    333   MD5_Final(md, &c);
    334   if (memcmp(md, sig->hash, 16) == 0)
    335     sig->ok = PGP_SIGOK;
    336   buf_free(t);
    337 }
    338 
    339 #ifdef USE_IDEA
    340 static int pgp_ideadecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
    341 {
    342   int err = 0;
    343   byte iv[8];
    344   byte hdr[10];
    345   int i, n;
    346   IDEA_KEY_SCHEDULE ks;
    347   SHA_CTX c;
    348   char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
    349 
    350   if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
    351     return (-1);
    352 
    353   if (mdc) {
    354     mdc = 1;
    355     if (in->data[0] != 1)
    356       return (-1);
    357   }
    358 
    359   buf_prepare(out, in->length - 10 - mdc);
    360 
    361   for (i = 0; i < 8; i++)
    362     iv[i] = 0;
    363 
    364   idea_set_encrypt_key(key->data, &ks);
    365 
    366   n = 0;
    367   idea_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, IDEA_DECRYPT);
    368   if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
    369     err = -1;
    370     goto end;
    371   }
    372   if (mdc) {
    373     SHA1_Init(&c);
    374     SHA1_Update(&c, hdr, 10);
    375   } else {
    376     iv[6] = iv[0], iv[7] = iv[1];
    377     memcpy(iv, in->data + 2, 6);
    378     n = 0;
    379   }
    380   idea_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks, iv, &n,
    381 		     IDEA_DECRYPT);
    382   if (mdc) {
    383     if (out->length > 22) {
    384       out->length -= 22;
    385       if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
    386 	SHA1_Update(&c, out->data, out->length + 2);
    387 	SHA1_Final(md, &c);
    388 	if (memcmp(out->data + out->length + 2, md, 20))
    389 	  err = -1;
    390       } else
    391 	err = -1;
    392     } else
    393       err = -1;
    394   }
    395 end:
    396   return (err);
    397 }
    398 #endif /* USE_IDEA */
    399 
    400 static int pgp_3desdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
    401 {
    402   int err = 0;
    403   DES_cblock iv;
    404   byte hdr[10];
    405   int i, n;
    406   DES_key_schedule ks1;
    407   DES_key_schedule ks2;
    408   DES_key_schedule ks3;
    409   SHA_CTX c;
    410   char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
    411 
    412   if (key->length != 24 || in->length <= (mdc?(1+10+22):10))
    413     return (-1);
    414 
    415   if (mdc) {
    416     mdc = 1;
    417     if (in->data[0] != 1)
    418       return (-1);
    419   }
    420 
    421   buf_prepare(out, in->length - 10 - mdc);
    422 
    423   for (i = 0; i < 8; i++)
    424     iv[i] = 0;
    425 
    426   DES_set_key((const_DES_cblock *) key->data, &ks1);
    427   DES_set_key((const_DES_cblock *) (key->data + 8), &ks2);
    428   DES_set_key((const_DES_cblock *) (key->data+ 16), &ks3);
    429 
    430   n = 0;
    431   DES_ede3_cfb64_encrypt(in->data + mdc, hdr, 10, &ks1, &ks2, &ks3, &iv, &n, DECRYPT);
    432   if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
    433     err = -1;
    434     goto end;
    435   }
    436   if (mdc) {
    437     SHA1_Init(&c);
    438     SHA1_Update(&c, hdr, 10);
    439   } else {
    440     iv[6] = iv[0], iv[7] = iv[1];
    441     memcpy(iv, in->data + 2, 6);
    442     n = 0;
    443   }
    444   DES_ede3_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 + mdc, &ks1,
    445 			 &ks2, &ks3, &iv, &n, DECRYPT);
    446   if (mdc) {
    447     if (out->length > 22) {
    448       out->length -= 22;
    449       if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
    450 	SHA1_Update(&c, out->data, out->length + 2);
    451 	SHA1_Final(md, &c);
    452 	if (memcmp(out->data + out->length + 2, md, 20))
    453 	  err = -1;
    454       } else
    455 	err = -1;
    456     } else
    457       err = -1;
    458   }
    459 end:
    460   return (err);
    461 }
    462 
    463 static int pgp_castdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
    464 {
    465   int err = 0;
    466   byte iv[8];
    467   byte hdr[10];
    468   int i, n;
    469   SHA_CTX c;
    470   char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
    471 
    472   CAST_KEY ks;
    473 
    474   if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
    475     return (-1);
    476 
    477   if (mdc) {
    478     mdc = 1;
    479     if (in->data[0] != 1)
    480       return (-1);
    481   }
    482 
    483   buf_prepare(out, in->length - 10 - mdc);
    484 
    485   for (i = 0; i < 8; i++)
    486     iv[i] = 0;
    487 
    488   CAST_set_key(&ks, 16, key->data);
    489 
    490   n = 0;
    491   CAST_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, CAST_DECRYPT);
    492   if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
    493     err = -1;
    494     goto end;
    495   }
    496   if (mdc) {
    497     SHA1_Init(&c);
    498     SHA1_Update(&c, hdr, 10);
    499   } else {
    500     iv[6] = iv[0], iv[7] = iv[1];
    501     memcpy(iv, in->data + 2, 6);
    502     n = 0;
    503   }
    504   CAST_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
    505 		     iv, &n, CAST_DECRYPT);
    506   if (mdc) {
    507     if (out->length > 22) {
    508       out->length -= 22;
    509       if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
    510 	SHA1_Update(&c, out->data, out->length + 2);
    511 	SHA1_Final(md, &c);
    512 	if (memcmp(out->data + out->length + 2, md, 20))
    513 	  err = -1;
    514       } else
    515 	err = -1;
    516     } else
    517       err = -1;
    518   }
    519 end:
    520   return (err);
    521 }
    522 
    523 static int pgp_bfdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
    524 {
    525   int err = 0;
    526   byte iv[8];
    527   byte hdr[10];
    528   int i, n;
    529   SHA_CTX c;
    530   char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
    531 
    532   BF_KEY ks;
    533 
    534   if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
    535     return (-1);
    536 
    537   if (mdc) {
    538     mdc = 1;
    539     if (in->data[0] != 1)
    540       return (-1);
    541   }
    542 
    543   buf_prepare(out, in->length - 10 - mdc);
    544 
    545   for (i = 0; i < 8; i++)
    546     iv[i] = 0;
    547 
    548   BF_set_key(&ks, 16, key->data);
    549 
    550   n = 0;
    551   BF_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, BF_DECRYPT);
    552   if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
    553     err = -1;
    554     goto end;
    555   }
    556   if (mdc) {
    557     SHA1_Init(&c);
    558     SHA1_Update(&c, hdr, 10);
    559   } else {
    560     iv[6] = iv[0], iv[7] = iv[1];
    561     memcpy(iv, in->data + 2, 6);
    562     n = 0;
    563   }
    564   BF_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
    565 		   iv, &n, BF_DECRYPT);
    566   if (mdc) {
    567     if (out->length > 22) {
    568       out->length -= 22;
    569       if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
    570 	SHA1_Update(&c, out->data, out->length + 2);
    571 	SHA1_Final(md, &c);
    572 	if (memcmp(out->data + out->length + 2, md, 20))
    573 	  err = -1;
    574       } else
    575 	err = -1;
    576     } else
    577       err = -1;
    578   }
    579 end:
    580   return (err);
    581 }
    582 
    583 #ifdef USE_AES
    584 static int pgp_aesdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
    585 {
    586   int err = 0;
    587   byte iv[16];
    588   byte hdr[18];
    589   int i, n;
    590   SHA_CTX c;
    591   char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
    592 
    593   AES_KEY ks;
    594 
    595   if ((key->length != 16 && key->length != 24 && key->length != 32) || in->length <= (mdc?(1+18+22):18))
    596     return (-1);
    597 
    598   if (mdc) {
    599     mdc = 1;
    600     if (in->data[0] != 1)
    601       return (-1);
    602   }
    603 
    604   buf_prepare(out, in->length - 18 - mdc);
    605 
    606   for (i = 0; i < 16; i++)
    607     iv[i] = 0;
    608 
    609   AES_set_encrypt_key(key->data, key->length<<3, &ks);
    610 
    611   n = 0;
    612   AES_cfb128_encrypt(in->data + mdc, hdr, 18, &ks, iv, &n, AES_DECRYPT);
    613   if (n != 2 || hdr[16] != hdr[14] || hdr[17] != hdr[15]) {
    614     err = -1;
    615     goto end;
    616   }
    617   if (mdc) {
    618     SHA1_Init(&c);
    619     SHA1_Update(&c, hdr, 18);
    620   } else {
    621     iv[14] = iv[0], iv[15] = iv[1];
    622     memcpy(iv, in->data + 2, 14);
    623     n = 0;
    624   }
    625   AES_cfb128_encrypt(in->data + 18 + mdc, out->data, in->length - 18 - mdc, &ks,
    626 		   iv, &n, AES_DECRYPT);
    627   if (mdc) {
    628     if (out->length > 22) {
    629       out->length -= 22;
    630       if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
    631 	SHA1_Update(&c, out->data, out->length + 2);
    632 	SHA1_Final(md, &c);
    633 	if (memcmp(out->data + out->length + 2, md, 20))
    634 	  err = -1;
    635       } else
    636 	err = -1;
    637     } else
    638       err = -1;
    639   }
    640 end:
    641   return (err);
    642 }
    643 #endif /* USE_AES */
    644 
    645 int pgp_getsymmetric(BUFFER *in, BUFFER *key, int algo, int mdc)
    646 {
    647   int err = -1;
    648   BUFFER *out;
    649 
    650   out = buf_new();
    651 
    652   switch (algo) {
    653 #ifdef USE_AES
    654    case PGP_K_AES128:
    655    case PGP_K_AES192:
    656    case PGP_K_AES256:
    657     err = pgp_aesdecrypt(in, out, key, mdc);
    658     break;
    659 #endif /* USE_AES */
    660 #ifdef USE_IDEA
    661    case PGP_K_IDEA:
    662     err = pgp_ideadecrypt(in, out, key, mdc);
    663     break;
    664 #endif /* USE_IDEA */
    665    case PGP_K_3DES:
    666     err = pgp_3desdecrypt(in, out, key, mdc);
    667     break;
    668    case PGP_K_CAST5:
    669     err = pgp_castdecrypt(in, out, key, mdc);
    670     break;
    671   case PGP_K_BF:
    672     err = pgp_bfdecrypt(in, out, key, mdc);
    673     break;
    674   }
    675 
    676   if (err < 0)
    677     errlog(ERRORMSG, "PGP decryption failed.\n");
    678 
    679   buf_move(in, out);
    680   buf_free(out);
    681   return (err);
    682 }
    683 
    684 int pgp_getliteral(BUFFER *in)
    685 {
    686   long fnlen;
    687   int err = 0;
    688   int mode;
    689   BUFFER *out;
    690   BUFFER *line;
    691 
    692   out = buf_new();
    693   line = buf_new();
    694   mode = buf_getc(in);
    695   fnlen = buf_getc(in);
    696   in->ptr += fnlen;		/* skip filename */
    697   if (in->ptr + 4 > in->length)
    698     err = -1;
    699   else {
    700     buf_getl(in);		/* timestamp */
    701     if (mode == 't')
    702       while (buf_getline(in, line) != -1) {
    703 	buf_cat(out, line);
    704 	buf_nl(out);
    705     } else
    706       buf_rest(out, in);
    707   }
    708   buf_move(in, out);
    709   buf_free(line);
    710   buf_free(out);
    711   return (err);
    712 }
    713 
    714 int pgp_uncompress(BUFFER *in)
    715 {
    716   int err = -1;
    717 
    718   switch(buf_getc(in)) {
    719   case 0:
    720     err = 0;
    721     break;
    722   case 1:
    723     err = buf_unzip(in, 0);
    724     break;
    725   case 2:
    726     err = buf_unzip(in, 1);
    727     break;
    728   default:
    729      err = -1;
    730      break;
    731   }
    732   return (err);
    733 }
    734 
    735 int pgp_getsessionkey(BUFFER *in, BUFFER *pass, char *secring)
    736 {
    737   BUFFER *out;
    738   BUFFER *key;
    739   BUFFER *keyid;
    740   int type;
    741   int i, csum = 0;
    742   int algo = 0;
    743   int err = -1;
    744   long expires;
    745 
    746   out = buf_new();
    747   key = buf_new();
    748   keyid = buf_new();
    749   type = buf_getc(in);		/* packet type */
    750   if (type < 2 || type > 3)
    751     goto end;
    752   buf_get(in, keyid, 8);
    753   algo = buf_getc(in);
    754   err = pgpdb_getkey(PK_DECRYPT, algo, NULL, NULL, &expires, key, NULL, NULL, keyid,
    755 		     secring, pass);
    756   if (err < 0)
    757     goto end;
    758   if (expires > 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
    759     errlog(DEBUGINFO, "Key expired.\n"); /* DEBUGINFO ? */
    760     err = -1;
    761     goto end;
    762   }
    763   switch (algo) {
    764   case PGP_ES_RSA:
    765     mpi_get(in, out);
    766     err = pgp_rsa(out, key, PK_DECRYPT);
    767     break;
    768    case PGP_E_ELG:
    769     buf_rest(out, in);
    770     err = pgp_elgdecrypt(out, key);
    771     break;
    772   default:
    773     err = -1;
    774   }
    775   if (err == 0 && out->length > 3) {
    776     algo = buf_getc(out);
    777     buf_get(out, in, out->length - 3); /* return recovered key */
    778     csum = buf_geti(out);
    779     for (i = 0; i < in->length; i++)
    780       csum = (csum - in->data[i]) % 65536;
    781     if (csum != 0)
    782       err = -1;
    783   } else
    784     err = -1;
    785 end:
    786   buf_free(out);
    787   buf_free(key);
    788   buf_free(keyid);
    789   return (err == 0 ? algo : err);
    790 }
    791 
    792 void pgp_iteratedsk(BUFFER *out, BUFFER *salt, BUFFER *pass, byte c)
    793 {
    794   int count;
    795   BUFFER *temp;
    796   temp = buf_new();
    797 
    798   count = (16l + (c & 15)) << ((c >> 4) + 6);
    799   while (temp->length < count) {
    800     buf_cat(temp, salt);
    801     buf_cat(temp, pass);
    802   }
    803   buf_get(temp, out, count);
    804   buf_free(temp);
    805 }
    806 
    807 int pgp_getsk(BUFFER *p, BUFFER *pass, BUFFER *key)
    808 {
    809   int skalgo, skspecifier, hashalgo;
    810   BUFFER *salted; /* passphrase with salt */
    811 
    812   if (!pass)
    813     return(-1);
    814 
    815   salted = buf_new();
    816 
    817   skalgo = buf_getc(p);
    818   skspecifier = buf_getc(p);
    819   hashalgo = buf_getc(p);
    820   switch (skspecifier) {
    821   case 0:
    822     buf_set(salted, pass);
    823     break;
    824   case 1:
    825     buf_get(p, salted, 8); /* salt */
    826     buf_cat(salted, pass);
    827     break;
    828   case 3:
    829     buf_get(p, salted, 8); /* salt */
    830     pgp_iteratedsk(salted, salted, pass, buf_getc(p));
    831     break;
    832   default:
    833     skalgo = -1;
    834     goto end;
    835   }
    836   if (pgp_expandsk(key, skalgo, hashalgo, salted) == -1)
    837     skalgo = -1;
    838 
    839  end:
    840   buf_free(salted);
    841   return (skalgo);
    842 }
    843 
    844 int pgp_getsymsessionkey(BUFFER *in, BUFFER *pass)
    845 {
    846   BUFFER *temp, *key, *iv;
    847   int algo = -1;
    848   temp = buf_new();
    849   key = buf_new();
    850   iv = buf_new();
    851 
    852   if (buf_getc(in) == 4) {  /* version */
    853     algo = pgp_getsk(in, pass, key);
    854     buf_rest(temp, in);
    855     if (temp->length) {
    856       /* encrypted session key present */
    857       buf_appendzero(iv, pgp_blocklen(algo));
    858       skcrypt(temp, algo, key, iv, DECRYPT);
    859       algo = buf_getc(temp);
    860       buf_rest(in, temp);
    861     } else
    862       buf_set(in, key);
    863   }
    864   buf_free(temp);
    865   buf_free(key);
    866   buf_free(iv);
    867   return (algo);
    868 }
    869 
    870 #endif /* USE_PGP */