#include "libopgp.h"

#define BITSIZ 9
int PGP_elsgm(FILE * inf, FILE * outf, char *litn,
              int signf, int styp, int halg, keyid_t keyid2, char *pp)
{
  char dbuf[(1 << BITSIZ) + 20], *bp, xmat[256];
  int j, k, i, ll, salg = 0;
  void *signkey, *hctx = NULL;

  /* signature startup and one pass header */
  if (signf) {
    if (0 >= (salg = PGP_gtkey(&signkey, pp ? pp : "", &keyid2))) {
      fprintf(stderr, "No Secret key found");
      return -5;
    }
    if (signf == 1 || signf == 2 || signf == 5 || signf == 6) {  /* onepass */
      bp = dbuf, *bp++ = 0xc4, *bp++ = 0x0d, *bp++ = signf >= 4 ? 4 : 3;
      *bp++ = styp, *bp++ = halg, *bp++ = salg;
      for (i = 0; i < 8; i++)   /* keyid */
        *bp++ = keyid2 >> (56 - 8 * i);
      *bp++ = signf != 2;       /* nested */
      fwrite(dbuf, 1, 15, outf);
      if (signf == 2 || signf == 6)
        return 0;
    }
    hctx = PGP_hini(halg);
  }
  /* wrap in literal, add fname */
  if (litn) {
    /* enlit5 */
    bp = dbuf;
    *bp++ = 0xe0 + BITSIZ;
    fputc(0xcb, outf);
    *bp++ = styp == 1 ? 't' : 'b';
    *bp++ = strlen(litn);
    strcpy(bp, litn);
    bp += strlen(litn);
    *bp++ = 0, *bp++ = 0, *bp++ = 0, *bp++ = 0;
    j = bp - dbuf - 1;
    for (;;) {
      if (0 > (ll = fread(bp, 1, (1 << BITSIZ) - j, inf)))
        exit(-2);
      if (signf)
        PGP_hblk(hctx, bp, ll);
      j += ll;
      if (j != (1 << BITSIZ))
        break;
      fwrite(dbuf, 1, (1 << BITSIZ) + 1, outf);
      bp = &dbuf[1], j = 0;
    }
    if (j > 192) {
      fputc(0xc0 | ((j - 192) >> 8), outf);
      dbuf[0] = j - 192;
    } else
      dbuf[0] = j;
    fwrite(dbuf, 1, j + 1, outf);
  } else if (signf)             /* if no literal, make detached signature */
    do {
      if (0 > (k = fread(dbuf, 1, (1 << BITSIZ), inf)))
        exit(-2);
      PGP_hblk(hctx, dbuf, k);
    } while (k == (1 << BITSIZ) && !feof(inf));
  if (signf) {                  /* finish signature */
    memset(xmat, 0xff, 4);
    i = PGP_sigmk(signkey, hctx, dbuf, keyid2,
                  styp, halg, salg, (signf >= 4) ? xmat : NULL);
    fwrite(dbuf, 1, i, outf);
  }
  return 0;
}
