#include <stdio.h>
#include <malloc.h>

#include "libpgp5.h"

#define BSIZE 12000
int decrypt5(FILE * inf, FILE * outf, unsigned char *keybuf)
{
  int i, j, gaz, cvealg = 0;
  unsigned int ll;
  unsigned char *dbuf, convkey[30], ckeybuf[256], *bp;
  void *cfbc = NULL;

  for (;;) {
    if (keybuf)
      strncpy(ckeybuf, keybuf, 255);
    i = fgetc(inf);
    if ((i & 0xfc) == 0xa8) {   /* literal w/ len & string ("PGP"), bypass */
      free(gazinta(inf, i, NULL));
      i = fgetc(inf);
    }
    if ((i & 0xfd) != 0xc1 && (i & 0xf4) != 0x84)  /* new PKE ? */
      exit(-1);
    dbuf = gazinta(inf, i, &gaz);
    if (i == 0xc1 || (i & 0xfc) == 0x84) {
      if (pkedec5(dbuf, ckeybuf))
        continue;
      bp = ckeybuf;
      cvealg = *bp++;           /* crypttype */
      j = cnvkeysiz(cvealg);
      memcpy(convkey, bp, j);
      for (ll = 0, i = 0; i < j; i++)  /* accumulate and verify checksum */
        ll += *bp++;
      if (ll != (bp[0] * 256 + bp[1]))
        return -4;
    } else if (i == 0xc3 || (i & 0xfc) == 0x8c) {
      bp = dbuf;
      if (4 != getcfbkey(&bp, ckeybuf, &cfbc))
        continue;
      ll = gaz + dbuf - bp;
      if (ll) {
        docfb(bp, ll, cfbc);
        free(cfbc), cfbc = NULL;
        cvealg = *bp++;         /* crypttype */
        memcpy(convkey, bp, ll - 1);
      } else
        cvealg = -1;            /* inited from getcfbkey */
    }
    free(dbuf);
    memset(ckeybuf, 0, 32);
    if (!cfbc)
      cfbc = cfbinit(convkey, ckeybuf, cvealg, 0);
    /* collect the cfbc-s in a list */
    break;
  }
  /* repeat for each cfbc */
  return cnvdec5(inf, outf, cfbc);
}
