示例#1
0
文件: pgp-compress.c 项目: 50wu/gpdb
static int
decompress_init(void **priv_p, void *arg, PullFilter *src)
{
	PGP_Context *ctx = arg;
	struct DecomprData *dec;
	int			res;

	if (ctx->compress_algo != PGP_COMPR_ZLIB
		&& ctx->compress_algo != PGP_COMPR_ZIP)
		return PXE_PGP_UNSUPPORTED_COMPR;

	dec = px_alloc(sizeof(*dec));
	memset(dec, 0, sizeof(*dec));
	dec->buf_len = ZIP_OUT_BUF;
	*priv_p = dec;

	dec->stream.zalloc = z_alloc;
	dec->stream.zfree = z_free;

	if (ctx->compress_algo == PGP_COMPR_ZIP)
		res = inflateInit2(&dec->stream, -15);
	else
		res = inflateInit(&dec->stream);
	if (res != Z_OK)
	{
		px_free(dec);
		px_debug("decompress_init: inflateInit error");
		return PXE_PGP_COMPRESSION_ERROR;
	}

	return 0;
}
示例#2
0
文件: pgp-compress.c 项目: 50wu/gpdb
static int
decompress_read(void *priv, PullFilter *src, int len,
				uint8 **data_p, uint8 *buf, int buflen)
{
	int			res;
	int			flush;
	struct DecomprData *dec = priv;

restart:
	if (dec->buf_data > 0)
	{
		if (len > dec->buf_data)
			len = dec->buf_data;
		*data_p = dec->pos;
		dec->pos += len;
		dec->buf_data -= len;
		return len;
	}

	if (dec->eof)
		return 0;

	if (dec->stream.avail_in == 0)
	{
		uint8	   *tmp;

		res = pullf_read(src, 8192, &tmp);
		if (res < 0)
			return res;
		dec->stream.next_in = tmp;
		dec->stream.avail_in = res;
	}

	dec->stream.next_out = dec->buf;
	dec->stream.avail_out = dec->buf_len;
	dec->pos = dec->buf;

	/*
	 * Z_SYNC_FLUSH is tell zlib to output as much as possible. It should do
	 * it anyway (Z_NO_FLUSH), but seems to reserve the right not to.  So lets
	 * follow the API.
	 */
	flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
	res = inflate(&dec->stream, flush);
	if (res != Z_OK && res != Z_STREAM_END)
	{
		px_debug("decompress_read: inflate error: %d", res);
		return PXE_PGP_CORRUPT_DATA;
	}

	dec->buf_data = dec->buf_len - dec->stream.avail_out;
	if (res == Z_STREAM_END)
		dec->eof = 1;
	goto restart;
}
static BIGNUM *
mpi_to_bn(PGP_MPI * n)
{
	BIGNUM	   *bn = BN_bin2bn(n->data, n->bytes, NULL);

	if (!bn)
		return NULL;
	if (BN_num_bits(bn) != n->bits)
	{
		px_debug("mpi_to_bn: bignum conversion failed: mpi=%d, bn=%d",
				 n->bits, BN_num_bits(bn));
		BN_clear_free(bn);
		return NULL;
	}
	return bn;
}
示例#4
0
int
mbuf_append(MBuf *dst, const uint8 *buf, int len)
{
	if (dst->no_write)
	{
		px_debug("mbuf_append: no_write");
		return PXE_BUG;
	}

	prepare_room(dst, len);

	memcpy(dst->data_end, buf, len);
	dst->data_end += len;

	return 0;
}
static int
check_key_sha1(PullFilter *src, PGP_PubKey *pk)
{
	int			res;
	uint8		got_sha1[20];
	uint8		my_sha1[20];
	PX_MD	   *md;

	res = pullf_read_fixed(src, 20, got_sha1);
	if (res < 0)
		return res;

	res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
	if (res < 0)
		goto err;
	switch (pk->algo)
	{
		case PGP_PUB_ELG_ENCRYPT:
			pgp_mpi_hash(md, pk->sec.elg.x);
			break;
		case PGP_PUB_RSA_SIGN:
		case PGP_PUB_RSA_ENCRYPT:
		case PGP_PUB_RSA_ENCRYPT_SIGN:
			pgp_mpi_hash(md, pk->sec.rsa.d);
			pgp_mpi_hash(md, pk->sec.rsa.p);
			pgp_mpi_hash(md, pk->sec.rsa.q);
			pgp_mpi_hash(md, pk->sec.rsa.u);
			break;
		case PGP_PUB_DSA_SIGN:
			pgp_mpi_hash(md, pk->sec.dsa.x);
			break;
	}
	px_md_finish(md, my_sha1);
	px_md_free(md);

	if (memcmp(my_sha1, got_sha1, 20) != 0)
	{
		px_debug("key sha1 check failed");
		res = PXE_PGP_KEYPKT_CORRUPT;
	}
err:
	memset(got_sha1, 0, 20);
	memset(my_sha1, 0, 20);
	return res;
}
示例#6
0
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;
}
示例#7
0
/*
 * caller wants exatly len bytes and dont bother with references
 */
int
pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
{
	int			res;
	uint8	   *p;

	res = pullf_read_max(src, len, &p, dst);
	if (res < 0)
		return res;
	if (res != len)
	{
		px_debug("pullf_read_fixed: need=%d got=%d", len, res);
		return PXE_MBUF_SHORT_READ;
	}
	if (p != dst)
		memcpy(dst, p, len);
	return 0;
}
static PGP_MPI *
bn_to_mpi(BIGNUM *bn)
{
	int			res;
	PGP_MPI    *n;

	res = pgp_mpi_alloc(BN_num_bits(bn), &n);
	if (res < 0)
		return NULL;

	if (BN_num_bytes(bn) != n->bytes)
	{
		px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d",
				 BN_num_bytes(bn), n->bytes);
		pgp_mpi_free(n);
		return NULL;
	}
	BN_bn2bin(bn, n->data);
	return n;
}
示例#9
0
/*
 * 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
check_key_cksum(PullFilter *src, PGP_PubKey *pk)
{
	int			res;
	unsigned	got_cksum,
				my_cksum = 0;
	uint8		buf[2];

	res = pullf_read_fixed(src, 2, buf);
	if (res < 0)
		return res;

	got_cksum = ((unsigned) buf[0] << 8) + buf[1];
	switch (pk->algo)
	{
		case PGP_PUB_ELG_ENCRYPT:
			my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
			break;
		case PGP_PUB_RSA_SIGN:
		case PGP_PUB_RSA_ENCRYPT:
		case PGP_PUB_RSA_ENCRYPT_SIGN:
			my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
			break;
		case PGP_PUB_DSA_SIGN:
			my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
			break;
	}
	if (my_cksum != got_cksum)
	{
		px_debug("key cksum check failed");
		return PXE_PGP_KEYPKT_CORRUPT;
	}
	return 0;
}
static int
internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
				  const uint8 *psw, int psw_len, int pubtype)
{
	PullFilter *pkt = NULL;
	int			res;
	uint8		tag;
	int			len;
	PGP_PubKey *enc_key = NULL;
	PGP_PubKey *pk = NULL;
	int			got_main_key = 0;

	/*
	 * Search for encryption key.
	 *
	 * Error out on anything fancy.
	 */
	while (1)
	{
		res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
		if (res <= 0)
			break;
		res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
		if (res < 0)
			break;

		switch (tag)
		{
			case PGP_PKT_PUBLIC_KEY:
			case PGP_PKT_SECRET_KEY:
				if (got_main_key)
				{
					res = PXE_PGP_MULTIPLE_KEYS;
					break;
				}
				got_main_key = 1;
				res = pgp_skip_packet(pkt);
				break;

			case PGP_PKT_PUBLIC_SUBKEY:
				if (pubtype != 0)
					res = PXE_PGP_EXPECT_SECRET_KEY;
				else
					res = _pgp_read_public_key(pkt, &pk);
				break;

			case PGP_PKT_SECRET_SUBKEY:
				if (pubtype != 1)
					res = PXE_PGP_EXPECT_PUBLIC_KEY;
				else
					res = process_secret_key(pkt, &pk, psw, psw_len);
				break;

			case PGP_PKT_SIGNATURE:
			case PGP_PKT_MARKER:
			case PGP_PKT_TRUST:
			case PGP_PKT_USER_ID:
			case PGP_PKT_USER_ATTR:
			case PGP_PKT_PRIV_61:
				res = pgp_skip_packet(pkt);
				break;
			default:
				px_debug("unknown/unexpected packet: %d", tag);
				res = PXE_PGP_UNEXPECTED_PKT;
		}
		pullf_free(pkt);
		pkt = NULL;

		if (pk != NULL)
		{
			if (res >= 0 && pk->can_encrypt)
			{
				if (enc_key == NULL)
				{
					enc_key = pk;
					pk = NULL;
				}
				else
					res = PXE_PGP_MULTIPLE_SUBKEYS;
			}

			if (pk)
				pgp_key_free(pk);
			pk = NULL;
		}

		if (res < 0)
			break;
	}

	if (pkt)
		pullf_free(pkt);

	if (res < 0)
	{
		if (enc_key)
			pgp_key_free(enc_key);
		return res;
	}

	if (!enc_key)
		res = PXE_PGP_NO_USABLE_KEY;
	else
		*pk_p = enc_key;
	return res;
}
static int
process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
				   const uint8 *key, int key_len)
{
	int			res;
	int			hide_type;
	int			cipher_algo;
	int			bs;
	uint8		iv[512];
	PullFilter *pf_decrypt = NULL,
			   *pf_key;
	PGP_CFB    *cfb = NULL;
	PGP_S2K		s2k;
	PGP_PubKey *pk;

	/* first read public key part */
	res = _pgp_read_public_key(pkt, &pk);
	if (res < 0)
		return res;

	/*
	 * is secret key encrypted?
	 */
	GETBYTE(pkt, hide_type);
	if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
	{
		if (key == NULL)
			return PXE_PGP_NEED_SECRET_PSW;
		GETBYTE(pkt, cipher_algo);
		res = pgp_s2k_read(pkt, &s2k);
		if (res < 0)
			return res;

		res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
		if (res < 0)
			return res;

		bs = pgp_get_cipher_block_size(cipher_algo);
		if (bs == 0)
		{
			px_debug("unknown cipher algo=%d", cipher_algo);
			return PXE_PGP_UNSUPPORTED_CIPHER;
		}
		res = pullf_read_fixed(pkt, bs, iv);
		if (res < 0)
			return res;

		/*
		 * create decrypt filter
		 */
		res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
		if (res < 0)
			return res;
		res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
		if (res < 0)
			return res;
		pf_key = pf_decrypt;
	}
	else if (hide_type == HIDE_CLEAR)
	{
		pf_key = pkt;
	}
	else
	{
		px_debug("unknown hide type");
		return PXE_PGP_KEYPKT_CORRUPT;
	}

	/* read secret key */
	switch (pk->algo)
	{
		case PGP_PUB_RSA_SIGN:
		case PGP_PUB_RSA_ENCRYPT:
		case PGP_PUB_RSA_ENCRYPT_SIGN:
			res = pgp_mpi_read(pkt, &pk->sec.rsa.d);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->sec.rsa.p);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->sec.rsa.q);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->sec.rsa.u);
			if (res < 0)
				break;
			break;
		case PGP_PUB_ELG_ENCRYPT:
			res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
			break;
		case PGP_PUB_DSA_SIGN:
			res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
			break;
		default:
			px_debug("unknown public algo: %d", pk->algo);
			res = PXE_PGP_KEYPKT_CORRUPT;
	}
	/* read checksum / sha1 */
	if (res >= 0)
	{
		if (hide_type == HIDE_SHA1)
			res = check_key_sha1(pf_key, pk);
		else
			res = check_key_cksum(pf_key, pk);
	}
	if (res >= 0)
		res = pgp_expect_packet_end(pf_key);

	if (pf_decrypt)
		pullf_free(pf_decrypt);
	if (cfb)
		pgp_cfb_free(cfb);

	if (res < 0)
		pgp_key_free(pk);
	else
		*pk_p = pk;

	return res;
}
int
_pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
{
	int			res;
	PGP_PubKey *pk;

	res = pgp_key_alloc(&pk);
	if (res < 0)
		return res;

	/* get version */
	GETBYTE(pkt, pk->ver);
	if (pk->ver != 4)
	{
		res = PXE_PGP_NOT_V4_KEYPKT;
		goto out;
	}

	/* read time */
	res = pullf_read_fixed(pkt, 4, pk->time);
	if (res < 0)
		goto out;

	/* pubkey algorithm */
	GETBYTE(pkt, pk->algo);

	switch (pk->algo)
	{
		case PGP_PUB_DSA_SIGN:
			res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
			if (res < 0)
				break;

			res = calc_key_id(pk);
			break;

		case PGP_PUB_RSA_SIGN:
		case PGP_PUB_RSA_ENCRYPT:
		case PGP_PUB_RSA_ENCRYPT_SIGN:
			res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
			if (res < 0)
				break;

			res = calc_key_id(pk);

			if (pk->algo != PGP_PUB_RSA_SIGN)
				pk->can_encrypt = 1;
			break;

		case PGP_PUB_ELG_ENCRYPT:
			res = pgp_mpi_read(pkt, &pk->pub.elg.p);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.elg.g);
			if (res < 0)
				break;
			res = pgp_mpi_read(pkt, &pk->pub.elg.y);
			if (res < 0)
				break;

			res = calc_key_id(pk);

			pk->can_encrypt = 1;
			break;

		default:
			px_debug("unknown public algo: %d", pk->algo);
			res = PXE_PGP_UNKNOWN_PUBALGO;
	}

out:
	if (res < 0)
		pgp_key_free(pk);
	else
		*pk_p = pk;

	return res;
}
示例#14
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);
}