#include <stdio.h>
#include <string.h>
#include "libpgp2.h"

/*------------------------------------*/
/* decrypt PKE packet, using passwdhash for secret key, and */
/* returning passwdhash if successful (return zero) */
int pkedec2(FILE * pkt, unsigned char *passwdhash)
{
  unsigned char dbuf[2048], *bp, t;
  unsigned long i, ll;
  int j;
  unsigned long long keyid = 0;
  RSA *key;

  do {                          /* scan through pke headers */
    t = fgetc(pkt);
    if ((t & 0xfc) != 0x84) {
      ungetc(t, pkt);
      return -1;
    }
    ll = 1 << (t & 3);          /* length of length */
    fread(dbuf, 1, ll, pkt);
    for (j = 0, i = 0; j < ll; j++)
      i = (i << 8) + dbuf[j];
    fread(dbuf, i, 1, pkt);
    bp = dbuf;
    bp++;                       /* version: 2 or 3 */
    for (j = 0; j < 8; j++)     /* copy key */
      keyid = (keyid << 8) + *bp++;
    if (*bp++ != 1)
      continue;                 /* algorithm id */
  } while (getkey2(&key, NULL, passwdhash, &keyid));

  i -= 12;
  bp += 2;                      /* should verify mpi bits v.s. length in i */
  ll = BN_num_bytes(key->n);
  while (i < ll)
    memmove(&bp[1], bp, i++), bp[0] = 0;
  j = RSA_private_decrypt(ll, bp, dbuf, key, RSA_PKCS1_PADDING);
  RSA_free(key);
  if (j < 0)
    return j;
  memcpy(passwdhash, &dbuf[j - 18], 16);
  for (ll = 0, i = 0; ll < 16; ll++)  /* calculate checksum */
    i += passwdhash[ll];
  if (dbuf[j - 2] != (i >> 8) || dbuf[j - 1] != (i & 0xff))
    return -1;                  /*cksum */
  return 0;
}
