URI: 
       tpgpget.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tpgpget.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 */