tpgpcreat.c - mixmaster - mixmaster 3.0 patched for libressl
 (HTM) git clone git://parazyd.org/mixmaster.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       tpgpcreat.c (20018B)
       ---
            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    Create OpenPGP packets
            9    $Id: pgpcreat.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 <assert.h>
           17 #include <time.h>
           18 #include <string.h>
           19 
           20 int pgp_packet(BUFFER *in, int type)
           21 {
           22   int ctb;
           23   BUFFER *out;
           24 
           25   out = buf_new();
           26  if (type > 15) {
           27     ctb = 0xC0 | type; /* make v4 packet */
           28     buf_setc(out, ctb);
           29     if (in->length > 8383) {
           30       buf_appendc(out, 0xFF);
           31       buf_appendl(out, in->length);
           32     } else if (in->length > 191) {
           33 #if 0
           34       buf_appendc(out, ((in->length-192) >> 8) + 192);
           35       buf_appendc(out,  (in->length-192) & 0xFF);
           36 #else /* end of 0 */
           37       buf_appendi(out, in->length - 0xC0 + 0xC000);
           38 #endif /* else if not 0 */
           39     } else {
           40       buf_appendc(out, in->length);
           41     }
           42  } else {
           43   ctb = 128 + (type << 2);
           44   if (in->length < 256 && type != PGP_PUBKEY && type != PGP_SECKEY &&
           45       type != PGP_SIG && type != PGP_PUBSUBKEY && type != PGP_SECSUBKEY
           46 #ifdef MIMIC
           47       && type != PGP_ENCRYPTED
           48 #endif /* MIMIC */
           49     ) {
           50     buf_setc(out, ctb);
           51     buf_appendc(out, in->length);
           52   }
           53 #ifndef MIMIC
           54   else if (in->length < 65536)
           55 #else /* end of not MIMIC */
           56   else if ((type == PGP_PUBKEY || type == PGP_SECKEY || type == PGP_SIG
           57            || type == PGP_SESKEY || type == PGP_PUBSUBKEY ||
           58            type == PGP_SECSUBKEY) && in->length < 65536)
           59 #endif /* else if MIMIC */
           60   {
           61     buf_appendc(out, ctb | 1);
           62     buf_appendi(out, in->length);
           63   } else {
           64     buf_appendc(out, ctb | 2);
           65     buf_appendl(out, in->length);
           66   }
           67  }
           68   buf_cat(out, in);
           69   buf_move(in, out);
           70   buf_free(out);
           71   return (0);
           72 }
           73 
           74 int pgp_subpacket(BUFFER *in, int type)
           75 {
           76   BUFFER *out;
           77   int len;
           78 
           79   out = buf_new();
           80   len = in->length + 1;
           81   if (len < 192)
           82     buf_setc(out, len);
           83   else {
           84     buf_setc(out, 255);
           85     buf_appendl(out, len);
           86   }
           87   buf_appendc(out, type);
           88   buf_cat(out, in);
           89   buf_move(in, out);
           90   buf_free(out);
           91   return (0);
           92 }
           93 
           94 int pgp_packet3(BUFFER *in, int type)
           95 {
           96 #ifdef MIMIC
           97   int ctb;
           98   BUFFER *out;
           99 
          100   out = buf_new();
          101   ctb = 128 + (type << 2);
          102   buf_setc(out, ctb | 3);
          103   buf_cat(out, in);
          104   buf_move(in, out);
          105   buf_free(out);
          106   return (0);
          107 #else /* end of MIMIC */
          108   return pgp_packet(in, type);
          109 #endif /* else if not MIMIC */
          110 }
          111 
          112 #ifdef USE_IDEA
          113 static int pgp_ideaencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
          114 {
          115   byte iv[8];
          116   int i, n = 0;
          117   IDEA_KEY_SCHEDULE ks;
          118   SHA_CTX c;
          119 
          120   assert(key->length == 17);
          121 
          122   for (i = 0; i < 8; i++)
          123     iv[i] = 0;
          124 
          125   idea_set_encrypt_key(key->data + 1, &ks);
          126 
          127   if (mdc) {
          128     mdc = 1;
          129     out->data[0] = 1;
          130   }
          131   rnd_bytes(out->data + mdc, 8);
          132   out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
          133   if (mdc) {
          134     SHA1_Init(&c);
          135     SHA1_Update(&c, out->data + 1, 10);
          136     SHA1_Update(&c, in->data, in->length);
          137   }
          138   n = 0;
          139   idea_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, IDEA_ENCRYPT);
          140   if (!mdc) {
          141     iv[6] = iv[0], iv[7] = iv[1];
          142     memcpy(iv, out->data + 2, 6);
          143     n = 0;
          144   }
          145   idea_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
          146                      IDEA_ENCRYPT);
          147   if (mdc) {
          148     SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
          149     idea_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
          150                        IDEA_ENCRYPT);
          151     SHA1_Final(out->data + 13 + in->length, &c);
          152     idea_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
          153                        IDEA_ENCRYPT);
          154   }
          155   return (0);
          156 }
          157 #endif /* USE_IDEA */
          158 
          159 static int pgp_3desencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
          160 {
          161   DES_cblock iv;
          162   int i, n = 0;
          163   DES_key_schedule ks1;
          164   DES_key_schedule ks2;
          165   DES_key_schedule ks3;
          166   SHA_CTX c;
          167 
          168   assert(key->length == 25);
          169 
          170   for (i = 0; i < 8; i++)
          171     iv[i] = 0;
          172 
          173   DES_set_key((const_DES_cblock *) (key->data + 1), &ks1);
          174   DES_set_key((const_DES_cblock *) (key->data + 9), &ks2);
          175   DES_set_key((const_DES_cblock *) (key->data+ 17), &ks3);
          176 
          177   if (mdc) {
          178     mdc = 1;
          179     out->data[0] = 1;
          180   }
          181   rnd_bytes(out->data + mdc, 8);
          182   out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
          183   if (mdc) {
          184     SHA1_Init(&c);
          185     SHA1_Update(&c, out->data + 1, 10);
          186     SHA1_Update(&c, in->data, in->length);
          187   }
          188   n = 0;
          189   DES_ede3_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks1, &ks2, &ks3, &iv, &n,
          190                          ENCRYPT);
          191   if (!mdc) {
          192     iv[6] = iv[0], iv[7] = iv[1];
          193     memcpy(iv, out->data + 2, 6);
          194     n = 0;
          195   }
          196   DES_ede3_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks1, &ks2, &ks3,
          197                          &iv, &n, ENCRYPT);
          198   if (mdc) {
          199     SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
          200     DES_ede3_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks1, &ks2, &ks3,
          201                        &iv, &n, ENCRYPT);
          202     SHA1_Final(out->data + 13 + in->length, &c);
          203     DES_ede3_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks1, &ks2, &ks3,
          204                        &iv, &n, ENCRYPT);
          205   }
          206   return (0);
          207 }
          208 
          209 static int pgp_castencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
          210 {
          211   byte iv[8];
          212   int i, n = 0;
          213   CAST_KEY ks;
          214   SHA_CTX c;
          215 
          216   assert(key->length == 17);
          217 
          218   for (i = 0; i < 8; i++)
          219     iv[i] = 0;
          220 
          221   CAST_set_key(&ks, 16, key->data + 1);
          222 
          223   if (mdc) {
          224     mdc = 1;
          225     out->data[0] = 1;
          226   }
          227   rnd_bytes(out->data + mdc, 8);
          228   out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
          229   if (mdc) {
          230     SHA1_Init(&c);
          231     SHA1_Update(&c, out->data + 1, 10);
          232     SHA1_Update(&c, in->data, in->length);
          233   }
          234   n = 0;
          235   CAST_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, CAST_ENCRYPT);
          236   if (!mdc) {
          237     iv[6] = iv[0], iv[7] = iv[1];
          238     memcpy(iv, out->data + 2, 6);
          239     n = 0;
          240   }
          241   CAST_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
          242                      CAST_ENCRYPT);
          243   if (mdc) {
          244     SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
          245     CAST_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
          246                        CAST_ENCRYPT);
          247     SHA1_Final(out->data + 13 + in->length, &c);
          248     CAST_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
          249                        CAST_ENCRYPT);
          250   }
          251   return (0);
          252 }
          253 
          254 static int pgp_bfencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
          255 {
          256   byte iv[8];
          257   int i, n = 0;
          258   BF_KEY ks;
          259   SHA_CTX c;
          260 
          261   assert(key->length == 17);
          262 
          263   for (i = 0; i < 8; i++)
          264     iv[i] = 0;
          265 
          266   BF_set_key(&ks, 16, key->data + 1);
          267 
          268   if (mdc) {
          269     mdc = 1;
          270     out->data[0] = 1;
          271   }
          272   rnd_bytes(out->data + mdc, 8);
          273   out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
          274   if (mdc) {
          275     SHA1_Init(&c);
          276     SHA1_Update(&c, out->data + 1, 10);
          277     SHA1_Update(&c, in->data, in->length);
          278   }
          279   n = 0;
          280   BF_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, BF_ENCRYPT);
          281   if (!mdc) {
          282     iv[6] = iv[0], iv[7] = iv[1];
          283     memcpy(iv, out->data + 2, 6);
          284     n = 0;
          285   }
          286   BF_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
          287                      BF_ENCRYPT);
          288   if (mdc) {
          289     SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
          290     BF_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
          291                        BF_ENCRYPT);
          292     SHA1_Final(out->data + 13 + in->length, &c);
          293     BF_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
          294                        BF_ENCRYPT);
          295   }
          296   return (0);
          297 }
          298 
          299 #ifdef USE_AES
          300 static int pgp_aesencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
          301 {
          302   byte iv[16];
          303   int i, n = 0;
          304   AES_KEY ks;
          305   SHA_CTX c;
          306 
          307   assert(key->length == 17 || key->length == 25 || key->length == 33);
          308 
          309   for (i = 0; i < 16; i++)
          310     iv[i] = 0;
          311 
          312   AES_set_encrypt_key(key->data + 1, (key->length-1)<<3, &ks);
          313 
          314   if (mdc) {
          315     mdc = 1;
          316     out->data[0] = 1;
          317   }
          318   rnd_bytes(out->data + mdc, 16);
          319   out->data[16 + mdc] = out->data[14 + mdc], out->data[17 + mdc] = out->data[15 + mdc];
          320   if (mdc) {
          321     SHA1_Init(&c);
          322     SHA1_Update(&c, out->data + 1, 18);
          323     SHA1_Update(&c, in->data, in->length);
          324   }
          325   n = 0;
          326   AES_cfb128_encrypt(out->data + mdc, out->data + mdc, 18, &ks, iv, &n, AES_ENCRYPT);
          327   if (!mdc) {
          328     iv[14] = iv[0], iv[15] = iv[1];
          329     memcpy(iv, out->data + 2, 14);
          330     n = 0;
          331   }
          332   AES_cfb128_encrypt(in->data, out->data + 18 + mdc, in->length, &ks, iv, &n,
          333                      AES_ENCRYPT);
          334   if (mdc) {
          335     SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
          336     AES_cfb128_encrypt("\xD3\x14", out->data + 19 + in->length, 2, &ks, iv, &n,
          337                        AES_ENCRYPT);
          338     SHA1_Final(out->data + 21 + in->length, &c);
          339     AES_cfb128_encrypt(out->data + 21 + in->length, out->data + 21 + in->length, 20, &ks, iv, &n,
          340                        AES_ENCRYPT);
          341   }
          342   return (0);
          343 }
          344 #endif /* USE_AES */
          345 
          346 int pgp_symmetric(BUFFER *in, BUFFER *key, int mdc)
          347 {
          348   BUFFER *out;
          349   int sym;
          350 
          351   out = buf_new();
          352   if (pgp_blocklen(sym = buf_getc(key)) > 8)
          353     mdc = 1; /* force MDC for AES */
          354   buf_prepare(out, in->length + (mdc?(1+2+22):2) + pgp_blocklen(sym));
          355   switch (sym) {
          356 #ifdef USE_IDEA
          357    case PGP_K_IDEA:
          358     pgp_ideaencrypt(in, out, key, mdc);
          359     break;
          360 #endif /* USE_IDEA */
          361 #ifdef USE_AES
          362    case PGP_K_AES128:
          363    case PGP_K_AES192:
          364    case PGP_K_AES256:
          365     pgp_aesencrypt(in, out, key, mdc);
          366     break;
          367 #endif /* USE_AES */
          368    case PGP_K_3DES:
          369     pgp_3desencrypt(in, out, key, mdc);
          370     break;
          371   case PGP_K_CAST5:
          372     pgp_castencrypt(in, out, key, mdc);
          373     break;
          374   case PGP_K_BF:
          375     pgp_bfencrypt(in, out, key, mdc);
          376     break;
          377    default:
          378     errlog(ERRORMSG, "Unknown symmetric algorithm.\n");
          379   }
          380   pgp_packet(out, mdc?PGP_ENCRYPTEDMDC:PGP_ENCRYPTED);
          381 
          382   buf_move(in, out);
          383   buf_free(out);
          384   return (0);
          385 }
          386 
          387 int pgp_literal(BUFFER *b, char *filename, int text)
          388 {
          389   BUFFER *out;
          390   BUFFER *line;
          391 
          392   if (filename == NULL)
          393     filename = "stdin";
          394 
          395   if (strlen(filename) > 255)
          396     return (-1);
          397 
          398   out = buf_new();
          399   line = buf_new();
          400 
          401   if (text)
          402     buf_setc(out, 't');
          403   else
          404     buf_setc(out, 'b');
          405   buf_appendc(out, strlen(filename));
          406   buf_appends(out, filename);
          407   buf_appendl(out, 0);                /* timestamp */
          408 
          409   if (b->length > 0) {
          410     if (text)
          411       while (buf_getline(b, line) != -1) {
          412         buf_cat(out, line);
          413         buf_appends(out, "\r\n");
          414       } else
          415         buf_cat(out, b);
          416   }
          417   pgp_packet(out, PGP_LITERAL);
          418   buf_move(b, out);
          419   buf_free(out);
          420   buf_free(line);
          421 
          422   return (0);
          423 }
          424 
          425 int pgp_compress(BUFFER *in)
          426 {
          427   int err;
          428   BUFFER *out;
          429 
          430   out = buf_new();
          431   buf_setc(out, 1);
          432   err = buf_zip(out, in, 13);
          433   if (err == 0) {
          434     pgp_packet3(out, PGP_COMPRESSED);
          435     buf_move(in, out);
          436   }
          437   buf_free(out);
          438   return (err);
          439 }
          440 
          441 int pgp_sessionkey(BUFFER *out, BUFFER *user, BUFFER *keyid, BUFFER *seskey,
          442                    char *pubring)
          443 {
          444   BUFFER *encrypt, *key, *id;
          445   int algo, sym, err = -1;
          446   int i, csum = 0;
          447   int tempbuf = 0;
          448 
          449   encrypt = buf_new();
          450   key = buf_new();
          451   id = buf_new();
          452   if (keyid == NULL) {
          453     keyid = buf_new();
          454     tempbuf = 1;
          455   }
          456   sym = seskey->data[0];
          457   if ((algo = pgpdb_getkey(PK_ENCRYPT, PGP_ANY, &sym, NULL, NULL, key, user, NULL, keyid,
          458                            pubring, NULL)) == -1)
          459     goto end;
          460 
          461   buf_setc(out, 3);                /* type */
          462   buf_cat(out, keyid);
          463   buf_appendc(out, algo);        /* algorithm */
          464 
          465   buf_set(encrypt, seskey);
          466 
          467   for (i = 1; i < encrypt->length; i++)
          468     csum = (csum + encrypt->data[i]) % 65536;
          469   buf_appendi(encrypt, csum);
          470 
          471   switch (algo) {
          472   case PGP_ES_RSA:
          473     err = pgp_rsa(encrypt, key, PK_ENCRYPT);
          474     mpi_put(out, encrypt);
          475     break;
          476    case PGP_E_ELG:
          477     err = pgp_elgencrypt(encrypt, key);
          478     buf_cat(out, encrypt);
          479     break;
          480   default:
          481     errlog(NOTICE, "Unknown encryption algorithm.\n");
          482     err = -1;
          483     goto end;
          484   }
          485   if (err == -1) {
          486     errlog(ERRORMSG, "Encryption failed!\n");
          487     goto end;
          488   }
          489   pgp_packet(out, PGP_SESKEY);
          490 end:
          491   if (tempbuf)
          492     buf_free(keyid);
          493   buf_free(id);
          494   buf_free(encrypt);
          495   buf_free(key);
          496   return (err);
          497 }
          498 
          499 void pgp_marker(BUFFER *out)
          500 {
          501   buf_clear(out);
          502   buf_append(out, "PGP", 3);
          503   pgp_packet(out, PGP_MARKER);
          504 }
          505 
          506 int pgp_symsessionkey(BUFFER *out, BUFFER *seskey, BUFFER *pass)
          507 {
          508   BUFFER *key;
          509   int sym;
          510   key = buf_new();
          511 
          512   sym = seskey->data[0];
          513   buf_setc(out, 4); /* version */
          514 #ifdef MIMICPGP5
          515   pgp_makesk(out, key, sym, 1, PGP_H_MD5, pass);
          516 #else /* end of MIMICPGP5 */
          517   pgp_makesk(out, key, sym, 3, PGP_H_SHA1, pass);
          518 #endif /* else if not MIMICPGP5 */
          519   if (seskey->length > 1)
          520     buf_cat(out, seskey);
          521   else {
          522     buf_setc(seskey, sym);
          523     buf_cat(seskey, key);
          524   }
          525   pgp_packet(out, PGP_SYMSESKEY);
          526   buf_free(key);
          527   return (0);
          528 }
          529 
          530 int pgp_digest(int hashalgo, BUFFER *in, BUFFER *d)
          531 {
          532   switch (hashalgo) {
          533    case PGP_H_MD5:
          534     digest_md5(in, d);
          535     return (0);
          536    case PGP_H_SHA1:
          537     digest_sha1(in, d);
          538     return (0);
          539   case PGP_H_RIPEMD:
          540     digest_rmd160(in, d);
          541     return (0);
          542    default:
          543     return (-1);
          544   }
          545 }
          546 
          547 int asnprefix(BUFFER *b, int hashalgo)
          548 {
          549   switch (hashalgo) {
          550   case PGP_H_MD5:
          551     buf_append(b, MD5PREFIX, sizeof(MD5PREFIX) - 1);
          552     return (0);
          553   case PGP_H_SHA1:
          554     buf_append(b, SHA1PREFIX, sizeof(SHA1PREFIX) - 1);
          555     return (0);
          556   default:
          557     return (-1);
          558   }
          559 }
          560 
          561 int pgp_expandsk(BUFFER *key, int skalgo, int hashalgo, BUFFER *data)
          562 {
          563   BUFFER *temp;
          564   int keylen;
          565   int err = 0;
          566   temp = buf_new();
          567 
          568   keylen = pgp_keylen(skalgo);
          569   buf_clear(key);
          570   while (key->length < keylen) {
          571     if (pgp_digest(hashalgo, data, temp) == -1) {
          572       err = -1;
          573       goto end;
          574     }
          575     buf_cat(key, temp);
          576 
          577     buf_setc(temp, 0);
          578     buf_cat(temp, data);
          579     buf_move(data, temp);
          580   }
          581 
          582   if (key->length > keylen) {
          583     buf_set(temp, key);
          584     buf_get(temp, key, keylen);
          585   }
          586  end:
          587   buf_free(temp);
          588   return(err);
          589 }
          590 
          591 int pgp_makesk(BUFFER *out, BUFFER *key, int sym, int type, int hash,
          592                BUFFER *pass)
          593 {
          594   int err = 0;
          595   BUFFER *salted;
          596   salted = buf_new();
          597 
          598   buf_appendc(out, sym);
          599   buf_appendc(out, type);
          600   buf_appendc(out, hash);
          601   switch (type) {
          602   case 0:
          603     buf_set(salted, pass);
          604     break;
          605   case 1:
          606     buf_appendrnd(salted, 8); /* salt */
          607     buf_cat(out, salted);
          608     buf_cat(salted, pass);
          609     break;
          610   case 3:
          611     buf_appendrnd(salted, 8); /* salt */
          612     buf_cat(out, salted);
          613     buf_appendc(out, 96); /* encoded count value 65536 */
          614     pgp_iteratedsk(salted, salted, pass, 96);
          615     break;
          616   default:
          617     err = -1;
          618   }
          619   pgp_expandsk(key, sym, hash, salted);
          620   buf_free(salted);
          621   return (err);
          622 }
          623 
          624 /* PGP/MIME needs to know the hash algorithm */
          625 int pgp_signhashalgo(BUFFER *algo, BUFFER *userid, char *secring, BUFFER *pass)
          626 {
          627   int pkalgo;
          628 
          629   pkalgo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, NULL, userid, NULL, NULL,
          630                         secring, pass);
          631   if (pkalgo == PGP_S_DSA)
          632     buf_sets(algo, "sha1");
          633   if (pkalgo == PGP_ES_RSA)
          634     buf_sets(algo, "md5");
          635   return (pkalgo > 0 ? 0 : -1);
          636 }
          637 
          638 int pgp_sign(BUFFER *msg, BUFFER *msg2, BUFFER *sig, BUFFER *userid,
          639              BUFFER *pass, int type, int self, long now, int remail,
          640              BUFFER *keypacket, char *secring)
          641 /*  msg:      data to be signed (buffer is modified)
          642     msg2:     additional data to be signed for certain sig types
          643     sig:      signature is placed here
          644     userid:   select signing key
          645     pass:     pass phrase for signing key
          646     type:     PGP signature type
          647     self:     is this a self-signature?
          648     now:      time of signature creation
          649     remail:   is this an anonymous message?
          650     keypacket: signature key
          651     secring:   key ring with signature key */
          652 {
          653   BUFFER *key, *id, *d, *sub, *enc;
          654   int algo, err = -1;
          655   int version = 3, hashalgo;
          656   int type1;
          657 
          658   id = buf_new();
          659   d = buf_new();
          660   sub = buf_new();
          661   enc = buf_new();
          662   key = buf_new();
          663 
          664   if (now == 0) {
          665     now = time(NULL);
          666     if (remail)
          667       now -= rnd_number(4 * 24 * 60 * 60);
          668   }
          669   if (keypacket) {
          670     buf_rewind(keypacket);
          671     algo = pgp_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, keypacket, key, id, NULL, pass);
          672   } else
          673     algo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, key, userid, NULL, id, secring,
          674                         pass);
          675   if (algo <= -1) {
          676     err = algo;
          677     goto end;
          678   }
          679   if (algo == PGP_S_DSA || algo == PGP_E_ELG)
          680     version = 4;
          681   if (version == 3)
          682     hashalgo = PGP_H_MD5;
          683   else
          684     hashalgo = PGP_H_SHA1;
          685 
          686   if (!self && type != PGP_SIG_BINDSUBKEY)
          687     version = 3;
          688 
          689   switch (type) {
          690    case PGP_SIG_CERT:
          691    case PGP_SIG_CERT1:
          692    case PGP_SIG_CERT2:
          693    case PGP_SIG_CERT3:
          694      type1 = pgp_getpacket(msg, d) == PGP_PUBKEY;
          695      assert (type1);
          696      buf_setc(msg, 0x99);
          697      buf_appendi(msg, d->length);
          698      buf_cat(msg, d);
          699 
          700      pgp_getpacket(msg2, d);
          701      switch (version) {
          702      case 3:
          703        buf_cat(msg, d);
          704        break;
          705      case 4:
          706        buf_appendc(msg, 0xb4);
          707        buf_appendl(msg, d->length);
          708        buf_cat(msg, d);
          709        break;
          710      }
          711      break;
          712    case PGP_SIG_BINDSUBKEY:
          713      type1 = pgp_getpacket(msg, d) == PGP_PUBKEY;
          714      assert (type1);
          715      buf_clear(msg);
          716      buf_appendc(msg, 0x99);
          717      buf_appendi(msg, d->length);
          718      buf_cat(msg, d);
          719 
          720      type1 = pgp_getpacket(msg2, d) == PGP_PUBSUBKEY;
          721      assert (type1);
          722      buf_appendc(msg, 0x99);
          723      buf_appendi(msg, d->length);
          724      buf_cat(msg, d);
          725      break;
          726    case PGP_SIG_BINARY:
          727      break;
          728    case PGP_SIG_CANONIC:
          729     pgp_sigcanonic(msg);
          730     break;
          731    default:
          732     NOT_IMPLEMENTED;
          733   }
          734   switch (version) {
          735    case 3:
          736     buf_set(d, msg);
          737     buf_appendc(d, type);
          738     buf_appendl(d, now);
          739     pgp_digest(hashalgo, d, d);
          740     if (algo == PGP_ES_RSA)
          741       asnprefix(enc, hashalgo);
          742     buf_cat(enc, d);
          743     err = pgp_dosign(algo, enc, key);
          744 
          745     buf_setc(sig, version);
          746     buf_appendc(sig, 5);
          747     buf_appendc(sig, type);
          748     buf_appendl(sig, now);
          749     buf_cat(sig, id);
          750     buf_appendc(sig, algo);
          751     buf_appendc(sig, hashalgo);
          752     buf_append(sig, d->data, 2);
          753     buf_cat(sig, enc);
          754     break;
          755 
          756    case 4:
          757     buf_setc(sig, version);
          758     buf_appendc(sig, type);
          759     buf_appendc(sig, algo);
          760     buf_appendc(sig, hashalgo);
          761 
          762     buf_clear(d);
          763     buf_appendl(d, now);
          764     pgp_subpacket(d, PGP_SUB_CREATIME);
          765     buf_cat(sub, d);
          766 
          767     if (self || type == PGP_SIG_BINDSUBKEY) {
          768       /* until we can handle the case where our pgp keys expire, don't create keys that expire */
          769       if (0 && KEYLIFETIME) { /* add key expirtaion time */
          770         buf_clear(d);
          771         buf_appendl(d, KEYLIFETIME);
          772         pgp_subpacket(d, PGP_SUB_KEYEXPIRETIME);
          773         buf_cat(sub, d);
          774       }
          775     }
          776 
          777     if (self) {
          778       buf_setc(d, PGP_K_CAST5);
          779 #ifdef USE_AES
          780       buf_appendc(d, PGP_K_AES128);
          781 #endif /* USE_AES */
          782       buf_appendc(d, PGP_K_3DES);
          783       pgp_subpacket(d, PGP_SUB_PSYMMETRIC);
          784       buf_cat(sub, d);
          785 
          786       buf_setc(d, 0x01); /* now we support MDC, so we can add MDC flag */
          787       pgp_subpacket(d, PGP_SUB_FEATURES);
          788       buf_cat(sub, d);
          789     }
          790 
          791     buf_appendi(sig, sub->length); /* hashed subpacket length */
          792     buf_cat(sig, sub);
          793 
          794     /* compute message digest */
          795     buf_set(d, msg);
          796     buf_cat(d, sig);
          797     buf_appendc(d, version);
          798     buf_appendc(d, 0xff);
          799     buf_appendl(d, sig->length);
          800     pgp_digest(hashalgo, d, d);
          801 
          802     pgp_subpacket(id, PGP_SUB_ISSUER);
          803     buf_appendi(sig, id->length); /* unhashed subpacket length */
          804     buf_cat(sig, id);
          805 
          806     buf_append(sig, d->data, 2);
          807 
          808     if (algo == PGP_ES_RSA)
          809       asnprefix(enc, hashalgo);
          810     buf_cat(enc, d);
          811     err = pgp_dosign(algo, enc, key);
          812     buf_cat(sig, enc);
          813     break;
          814   }
          815   pgp_packet(sig, PGP_SIG);
          816 
          817 end:
          818   buf_free(key);
          819   buf_free(id);
          820   buf_free(d);
          821   buf_free(sub);
          822   buf_free(enc);
          823   return (err);
          824 }
          825 
          826 int pgp_pubkeycert(BUFFER *userid, char *keyring, BUFFER *pass,
          827                    BUFFER *out, int remail)
          828 {
          829   BUFFER *key;
          830   KEYRING *r;
          831   int err = -1;
          832 
          833   key = buf_new();
          834   r = pgpdb_open(keyring, pass, 0, PGP_TYPE_UNDEFINED);
          835   if (r != NULL)
          836     while (pgpdb_getnext(r, key, NULL, userid) != -1) {
          837       if (pgp_makepubkey(key, NULL, out, pass, 0) != -1)
          838         err = 0;
          839     }
          840   if (err == 0)
          841     pgp_armor(out, remail);
          842   else
          843     buf_clear(out);
          844   buf_free(key);
          845   return (err);
          846 }
          847 
          848 #endif /* USE_PGP */