/*
 * pgp-mpi.c
 *	  OpenPGP MPI helper functions.
 *
 * 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-mpi.c
 */
#include "postgres.h"

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

int
pgp_mpi_alloc(int bits, PGP_MPI **mpi)
{
	PGP_MPI    *n;
	int			len = (bits + 7) / 8;

	if (bits < 0 || bits > 0xFFFF)
	{
		px_debug("pgp_mpi_alloc: unreasonable request: bits=%d", bits);
		return PXE_PGP_CORRUPT_DATA;
	}
	n = px_alloc(sizeof(*n) + len);
	n->bits = bits;
	n->bytes = len;
	n->data = (uint8 *) (n) + sizeof(*n);
	*mpi = n;
	return 0;
}

int
pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
{
	int			res;
	PGP_MPI    *n;

	res = pgp_mpi_alloc(bits, &n);
	if (res < 0)
		return res;
	memcpy(n->data, data, n->bytes);
	*mpi = n;
	return 0;
}

int
pgp_mpi_free(PGP_MPI *mpi)
{
	if (mpi == NULL)
		return 0;
	memset(mpi, 0, sizeof(*mpi) + mpi->bytes);
	px_free(mpi);
	return 0;
}

int
pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
{
	int			res;
	uint8		hdr[2];
	int			bits;
	PGP_MPI    *n;

	res = pullf_read_fixed(src, 2, hdr);
	if (res < 0)
		return res;
	bits = ((unsigned) hdr[0] << 8) + hdr[1];

	res = pgp_mpi_alloc(bits, &n);
	if (res < 0)
		return res;

	res = pullf_read_fixed(src, n->bytes, n->data);
	if (res < 0)
		pgp_mpi_free(n);
	else
		*mpi = n;
	return res;
}

int
pgp_mpi_write(PushFilter *dst, PGP_MPI *n)
{
	int			res;
	uint8		buf[2];

	buf[0] = n->bits >> 8;
	buf[1] = n->bits & 0xFF;
	res = pushf_write(dst, buf, 2);
	if (res >= 0)
		res = pushf_write(dst, n->data, n->bytes);
	return res;
}

int
pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
{
	uint8		buf[2];

	buf[0] = n->bits >> 8;
	buf[1] = n->bits & 0xFF;
	px_md_update(md, buf, 2);
	px_md_update(md, n->data, n->bytes);

	return 0;
}

unsigned
pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
{
	int			i;

	cksum += n->bits >> 8;
	cksum += n->bits & 0xFF;
	for (i = 0; i < n->bytes; i++)
		cksum += n->data[i];

	return cksum & 0xFFFF;
}
