mixmaster

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

pgpcreat.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 */