/*
 * pgp-pubdec.c
 *	  Decrypt public-key encrypted session key.
 *
 * Copyright (c) 2005 Marko Kreen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *	  notice, this list of conditions and the following disclaimer in the
 *	  documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * contrib/pgcrypto/pgp-pubdec.c
 */
#include "postgres.h"

#include "px.h"
#include "mbuf.h"
#include "pgp.h"

/*
 * padded msg = 02 || PS || 00 || M
 * PS - pad bytes
 * M - msg
 */
static uint8 *
check_eme_pkcs1_v15(uint8 *data, int len)
{
	uint8	   *data_end = data + len;
	uint8	   *p = data;
	int			rnd = 0;

	if (len < 1 + 8 + 1)
		return NULL;

	if (*p++ != 2)
		return NULL;

	while (p < data_end && *p)
	{
		p++;
		rnd++;
	}

	if (p == data_end)
		return NULL;
	if (*p != 0)
		return NULL;
	if (rnd < 8)
		return NULL;
	return p + 1;
}

/*
 * secret message: 1 byte algo, sesskey, 2 byte cksum
 * ignore algo in cksum
 */
static int
control_cksum(uint8 *msg, int msglen)
{
	int			i;
	unsigned	my_cksum,
				got_cksum;

	if (msglen < 3)
		return PXE_PGP_WRONG_KEY;

	my_cksum = 0;
	for (i = 1; i < msglen - 2; i++)
		my_cksum += msg[i];
	my_cksum &= 0xFFFF;
	got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
	if (my_cksum != got_cksum)
	{
		px_debug("pubenc cksum failed");
		return PXE_PGP_WRONG_KEY;
	}
	return 0;
}

static int
decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
{
	int			res;
	PGP_MPI    *c1 = NULL;
	PGP_MPI    *c2 = NULL;

	if (pk->algo != PGP_PUB_ELG_ENCRYPT)
		return PXE_PGP_WRONG_KEY;

	/* read elgamal encrypted data */
	res = pgp_mpi_read(pkt, &c1);
	if (res < 0)
		goto out;
	res = pgp_mpi_read(pkt, &c2);
	if (res < 0)
		goto out;

	/* decrypt */
	res = pgp_elgamal_decrypt(pk, c1, c2, m_p);

out:
	pgp_mpi_free(c1);
	pgp_mpi_free(c2);
	return res;
}

static int
decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
{
	int			res;
	PGP_MPI    *c;

	if (pk->algo != PGP_PUB_RSA_ENCRYPT
		&& pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
		return PXE_PGP_WRONG_KEY;

	/* read rsa encrypted data */
	res = pgp_mpi_read(pkt, &c);
	if (res < 0)
		return res;

	/* decrypt */
	res = pgp_rsa_decrypt(pk, c, m_p);

	pgp_mpi_free(c);
	return res;
}

/* key id is missing - user is expected to try all keys */
static const uint8
			any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};

int
pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
{
	int			ver;
	int			algo;
	int			res;
	uint8		key_id[8];
	PGP_PubKey *pk;
	uint8	   *msg;
	int			msglen;
	PGP_MPI    *m;

	pk = ctx->pub_key;
	if (pk == NULL)
	{
		px_debug("no pubkey?");
		return PXE_BUG;
	}

	GETBYTE(pkt, ver);
	if (ver != 3)
	{
		px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
		return PXE_PGP_CORRUPT_DATA;
	}

	/*
	 * check if keyid's match - user-friendly msg
	 */
	res = pullf_read_fixed(pkt, 8, key_id);
	if (res < 0)
		return res;
	if (memcmp(key_id, any_key, 8) != 0
		&& memcmp(key_id, pk->key_id, 8) != 0)
	{
		px_debug("key_id's does not match");
		return PXE_PGP_WRONG_KEY;
	}

	/*
	 * Decrypt
	 */
	GETBYTE(pkt, algo);
	switch (algo)
	{
		case PGP_PUB_ELG_ENCRYPT:
			res = decrypt_elgamal(pk, pkt, &m);
			break;
		case PGP_PUB_RSA_ENCRYPT:
		case PGP_PUB_RSA_ENCRYPT_SIGN:
			res = decrypt_rsa(pk, pkt, &m);
			break;
		default:
			res = PXE_PGP_UNKNOWN_PUBALGO;
	}
	if (res < 0)
		return res;

	/*
	 * extract message
	 */
	msg = check_eme_pkcs1_v15(m->data, m->bytes);
	if (msg == NULL)
	{
		px_debug("check_eme_pkcs1_v15 failed");
		res = PXE_PGP_WRONG_KEY;
		goto out;
	}
	msglen = m->bytes - (msg - m->data);

	res = control_cksum(msg, msglen);
	if (res < 0)
		goto out;

	/*
	 * got sesskey
	 */
	ctx->cipher_algo = *msg;
	ctx->sess_key_len = msglen - 3;
	memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);

out:
	pgp_mpi_free(m);
	if (res < 0)
		return res;
	return pgp_expect_packet_end(pkt);
}
