Beispiel #1
0
/*
 * Call ereport(ERROR, ...), with an error code and message corresponding to
 * the PXE_* error code given as argument.
 *
 * This is similar to px_strerror(err), but for some errors, we fill in the
 * error code and detail fields more appropriately.
 */
void
px_THROW_ERROR(int err)
{
	if (err == PXE_NO_RANDOM)
	{
#ifdef HAVE_STRONG_RANDOM
		ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("could not generate a random number")));
#else
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("pg_random_bytes() is not supported by this build"),
				 errdetail("This functionality requires a source of strong random numbers"),
				 errhint("You need to rebuild PostgreSQL using --enable-strong-random")));
#endif
	}
	else
	{
		/* For other errors, use the message from the above list. */
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(err))));
	}
}
Beispiel #2
0
Datum
pg_dearmor(PG_FUNCTION_ARGS)
{
	text	   *data;
	bytea	   *res;
	int			data_len,
				res_len,
				guess_len;

	data = PG_GETARG_TEXT_P(0);
	data_len = VARSIZE(data) - VARHDRSZ;

	guess_len = pgp_armor_dec_len(data_len);
	res = palloc(VARHDRSZ + guess_len);

	res_len = pgp_armor_decode((uint8 *) VARDATA(data), data_len,
							   (uint8 *) VARDATA(res));
	if (res_len < 0)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(res_len))));
	if (res_len > guess_len)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("Overflow - decode estimate too small")));
	SET_VARSIZE(res, VARHDRSZ + res_len);

	PG_FREE_IF_COPY(data, 0);
	PG_RETURN_TEXT_P(res);
}
Beispiel #3
0
Datum
pg_dearmor(PG_FUNCTION_ARGS)
{
	text	   *data;
	bytea	   *res;
	int			data_len;
	int			ret;
	StringInfoData buf;

	data = PG_GETARG_TEXT_P(0);
	data_len = VARSIZE(data) - VARHDRSZ;

	initStringInfo(&buf);

	ret = pgp_armor_decode((uint8 *) VARDATA(data), data_len, &buf);
	if (ret < 0)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(ret))));
	res = palloc(VARHDRSZ + buf.len);
	SET_VARSIZE(res, VARHDRSZ + buf.len);
	memcpy(VARDATA(res), buf.data, buf.len);
	pfree(buf.data);

	PG_FREE_IF_COPY(data, 0);
	PG_RETURN_TEXT_P(res);
}
Beispiel #4
0
Datum
pg_gen_salt_rounds(PG_FUNCTION_ARGS)
{
	text	   *arg0;
	int			rounds;
	int			len;
	text	   *res;
	char		buf[PX_MAX_SALT_LEN + 1];

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
		PG_RETURN_NULL();

	arg0 = PG_GETARG_TEXT_P(0);
	rounds = PG_GETARG_INT32(1);

	len = VARSIZE(arg0) - VARHDRSZ;
	len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
	memcpy(buf, VARDATA(arg0), len);
	buf[len] = 0;
	len = px_gen_salt(buf, buf, rounds);
	if (len < 0)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("gen_salt: %s", px_strerror(len))));

	res = (text *) palloc(len + VARHDRSZ);
	VARATT_SIZEP(res) = len + VARHDRSZ;
	memcpy(VARDATA(res), buf, len);

	PG_FREE_IF_COPY(arg0, 0);

	PG_RETURN_TEXT_P(res);
}
Beispiel #5
0
Datum
pg_decrypt_iv(PG_FUNCTION_ARGS)
{
	int			err;
	bytea	   *data,
			   *key,
			   *iv,
			   *res;
	text	   *type;
	PX_Combo   *c;
	unsigned	dlen,
				klen,
				rlen,
				ivlen;

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
		|| PG_ARGISNULL(2) || PG_ARGISNULL(3))
		PG_RETURN_NULL();

	type = PG_GETARG_TEXT_P(3);
	c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);

	data = PG_GETARG_BYTEA_P(0);
	key = PG_GETARG_BYTEA_P(1);
	iv = PG_GETARG_BYTEA_P(2);
	dlen = VARSIZE(data) - VARHDRSZ;
	klen = VARSIZE(key) - VARHDRSZ;
	ivlen = VARSIZE(iv) - VARHDRSZ;

	rlen = px_combo_decrypt_len(c, dlen);
	res = palloc(VARHDRSZ + rlen);

	err = px_combo_init(c, (uint8 *) VARDATA(key), klen,
						(uint8 *) VARDATA(iv), ivlen);
	if (!err)
		px_combo_decrypt(c, (uint8 *) VARDATA(data), dlen,
						 (uint8 *) VARDATA(res), &rlen);

	px_combo_free(c);

	if (err)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("decrypt_iv error: %s", px_strerror(err))));

	VARATT_SIZEP(res) = VARHDRSZ + rlen;

	PG_FREE_IF_COPY(data, 0);
	PG_FREE_IF_COPY(key, 1);
	PG_FREE_IF_COPY(iv, 2);
	PG_FREE_IF_COPY(type, 3);

	PG_RETURN_BYTEA_P(res);
}
Beispiel #6
0
Datum
pg_encrypt(PG_FUNCTION_ARGS)
{
	int			err;
	bytea	   *data,
			   *key,
			   *res;
	text	   *type;
	PX_Combo   *c;
	unsigned	dlen,
				klen,
				rlen;

	type = PG_GETARG_TEXT_P(2);
	c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);

	data = PG_GETARG_BYTEA_P(0);
	key = PG_GETARG_BYTEA_P(1);
	dlen = VARSIZE(data) - VARHDRSZ;
	klen = VARSIZE(key) - VARHDRSZ;

	rlen = px_combo_encrypt_len(c, dlen);
	res = palloc(VARHDRSZ + rlen);

	err = px_combo_init(c, (uint8 *) VARDATA(key), klen, NULL, 0);
	if (!err)
		err = px_combo_encrypt(c, (uint8 *) VARDATA(data), dlen,
							   (uint8 *) VARDATA(res), &rlen);
	px_combo_free(c);

	PG_FREE_IF_COPY(data, 0);
	PG_FREE_IF_COPY(key, 1);
	PG_FREE_IF_COPY(type, 2);

	if (err)
	{
		pfree(res);
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("encrypt error: %s", px_strerror(err))));
	}

	SET_VARSIZE(res, VARHDRSZ + rlen);
	PG_RETURN_BYTEA_P(res);
}
Beispiel #7
0
Datum
pg_gen_salt(PG_FUNCTION_ARGS)
{
	text	   *arg0 = PG_GETARG_TEXT_PP(0);
	int			len;
	char		buf[PX_MAX_SALT_LEN + 1];

	text_to_cstring_buffer(arg0, buf, sizeof(buf));
	len = px_gen_salt(buf, buf, 0);
	if (len < 0)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("gen_salt: %s", px_strerror(len))));

	PG_FREE_IF_COPY(arg0, 0);

	PG_RETURN_TEXT_P(cstring_to_text_with_len(buf, len));
}
Beispiel #8
0
Datum
pgp_key_id_w(PG_FUNCTION_ARGS)
{
	bytea	   *data;
	text	   *res;
	int			res_len;
	MBuf	   *buf;

	data = PG_GETARG_BYTEA_P(0);
	buf = create_mbuf_from_vardata(data);
	res = palloc(VARHDRSZ + 17);

	res_len = pgp_get_keyid(buf, VARDATA(res));
	mbuf_free(buf);
	if (res_len < 0)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(res_len))));
	SET_VARSIZE(res, VARHDRSZ + res_len);

	PG_FREE_IF_COPY(data, 0);
	PG_RETURN_TEXT_P(res);
}
Beispiel #9
0
static void *
find_provider(text *name,
			  PFN provider_lookup,
			  char *desc, int silent)
{
	void	   *res;
	char	   *buf;
	int			err;

	buf = downcase_truncate_identifier(VARDATA(name),
									   VARSIZE(name) - VARHDRSZ,
									   false);

	err = provider_lookup(buf, &res);

	if (err && !silent)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("Cannot use \"%s\": %s", buf, px_strerror(err))));

	pfree(buf);

	return err ? NULL : res;
}
Beispiel #10
0
Datum
pg_random_bytes(PG_FUNCTION_ARGS)
{
	int			err;
	int			len = PG_GETARG_INT32(0);
	bytea	   *res;

	if (len < 1 || len > 1024)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("Length not in range")));

	res = palloc(VARHDRSZ + len);
	SET_VARSIZE(res, VARHDRSZ + len);

	/* generate result */
	err = px_get_random_bytes((uint8 *) VARDATA(res), len);
	if (err < 0)
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("Random generator error: %s", px_strerror(err))));

	PG_RETURN_BYTEA_P(res);
}
Beispiel #11
0
static void
init_work(PGP_Context **ctx_p, int is_text,
		  text *args, struct debug_expect * ex)
{
	int			err = pgp_init(ctx_p);

	fill_expect(ex, is_text);

	if (err == 0 && args != NULL)
		err = parse_args(*ctx_p, (uint8 *) VARDATA(args),
						 VARSIZE(args) - VARHDRSZ, ex);

	if (err)
	{
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(err))));
	}

	if (ex->debug)
		px_set_debug_handler(show_debug);

	pgp_set_text_mode(*ctx_p, is_text);
}
Beispiel #12
0
static bytea *
decrypt_internal(int is_pubenc, int need_text, text *data,
				 text *key, text *keypsw, text *args)
{
	int			err;
	MBuf	   *src = NULL,
			   *dst = NULL;
	uint8		tmp[VARHDRSZ];
	uint8	   *restmp;
	bytea	   *res;
	int			res_len;
	PGP_Context *ctx = NULL;
	struct debug_expect ex;
	int			got_unicode = 0;


	init_work(&ctx, need_text, args, &ex);

	src = mbuf_create_from_data((uint8 *) VARDATA(data),
								VARSIZE(data) - VARHDRSZ);
	dst = mbuf_create(VARSIZE(data) + 2048);

	/*
	 * reserve room for header
	 */
	mbuf_append(dst, tmp, VARHDRSZ);

	/*
	 * set key
	 */
	if (is_pubenc)
	{
		uint8	   *psw = NULL;
		int			psw_len = 0;
		MBuf	   *kbuf;

		if (keypsw)
		{
			psw = (uint8 *) VARDATA(keypsw);
			psw_len = VARSIZE(keypsw) - VARHDRSZ;
		}
		kbuf = create_mbuf_from_vardata(key);
		err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
		mbuf_free(kbuf);
	}
	else
		err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
							 VARSIZE(key) - VARHDRSZ);

	/*
	 * decrypt
	 */
	if (err >= 0)
		err = pgp_decrypt(ctx, src, dst);

	/*
	 * failed?
	 */
	if (err < 0)
		goto out;

	if (ex.expect)
		check_expect(ctx, &ex);

	/* remember the setting */
	got_unicode = pgp_get_unicode_mode(ctx);

out:
	if (src)
		mbuf_free(src);
	if (ctx)
		pgp_free(ctx);

	if (err)
	{
		px_set_debug_handler(NULL);
		if (dst)
			mbuf_free(dst);
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(err))));
	}

	res_len = mbuf_steal_data(dst, &restmp);
	mbuf_free(dst);

	/* res_len includes VARHDRSZ */
	res = (bytea *) restmp;
	SET_VARSIZE(res, res_len);

	if (need_text && got_unicode)
	{
		text	   *utf = convert_from_utf8(res);

		if (utf != res)
		{
			clear_and_pfree(res);
			res = utf;
		}
	}
	px_set_debug_handler(NULL);

	/*
	 * add successfull decryptions also into RNG
	 */
	add_entropy(res, key, keypsw);

	return res;
}
Beispiel #13
0
static bytea *
encrypt_internal(int is_pubenc, int is_text,
				 text *data, text *key, text *args)
{
	MBuf	   *src,
			   *dst;
	uint8		tmp[VARHDRSZ];
	uint8	   *restmp;
	bytea	   *res;
	int			res_len;
	PGP_Context *ctx;
	int			err;
	struct debug_expect ex;
	text	   *tmp_data = NULL;

	/*
	 * Add data and key info RNG.
	 */
	add_entropy(data, key, NULL);

	init_work(&ctx, is_text, args, &ex);

	if (is_text && pgp_get_unicode_mode(ctx))
	{
		tmp_data = convert_to_utf8(data);
		if (tmp_data == data)
			tmp_data = NULL;
		else
			data = tmp_data;
	}

	src = create_mbuf_from_vardata(data);
	dst = mbuf_create(VARSIZE(data) + 128);

	/*
	 * reserve room for header
	 */
	mbuf_append(dst, tmp, VARHDRSZ);

	/*
	 * set key
	 */
	if (is_pubenc)
	{
		MBuf	   *kbuf = create_mbuf_from_vardata(key);

		err = pgp_set_pubkey(ctx, kbuf,
							 NULL, 0, 0);
		mbuf_free(kbuf);
	}
	else
		err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
							 VARSIZE(key) - VARHDRSZ);

	/*
	 * encrypt
	 */
	if (err >= 0)
		err = pgp_encrypt(ctx, src, dst);

	/*
	 * check for error
	 */
	if (err)
	{
		if (ex.debug)
			px_set_debug_handler(NULL);
		if (tmp_data)
			clear_and_pfree(tmp_data);
		pgp_free(ctx);
		mbuf_free(src);
		mbuf_free(dst);
		ereport(ERROR,
				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
				 errmsg("%s", px_strerror(err))));
	}

	/* res_len includes VARHDRSZ */
	res_len = mbuf_steal_data(dst, &restmp);
	res = (bytea *) restmp;
	SET_VARSIZE(res, res_len);

	if (tmp_data)
		clear_and_pfree(tmp_data);
	pgp_free(ctx);
	mbuf_free(src);
	mbuf_free(dst);

	px_set_debug_handler(NULL);

	return res;
}
Beispiel #14
0
Datum
pgp_armor_headers(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	pgp_armor_headers_state *state;
	char	   *utf8key;
	char	   *utf8val;
	HeapTuple	tuple;
	TupleDesc	tupdesc;
	AttInMetadata *attinmeta;

	if (SRF_IS_FIRSTCALL())
	{
		text	   *data = PG_GETARG_TEXT_PP(0);
		int			res;
		MemoryContext oldcontext;

		funcctx = SRF_FIRSTCALL_INIT();

		/* we need the state allocated in the multi call context */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		/* Build a tuple descriptor for our result type */
		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
			elog(ERROR, "return type must be a row type");

		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));

		res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
										VARSIZE_ANY_EXHDR(data),
										&state->nheaders, &state->keys,
										&state->values);
		if (res < 0)
			ereport(ERROR,
					(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
					 errmsg("%s", px_strerror(res))));

		MemoryContextSwitchTo(oldcontext);
		funcctx->user_fctx = state;
	}

	funcctx = SRF_PERCALL_SETUP();
	state = (pgp_armor_headers_state *) funcctx->user_fctx;

	if (funcctx->call_cntr >= state->nheaders)
		SRF_RETURN_DONE(funcctx);
	else
	{
		char	   *values[2];

		/* we assume that the keys (and values) are in UTF-8. */
		utf8key = state->keys[funcctx->call_cntr];
		utf8val = state->values[funcctx->call_cntr];

		values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
		values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);

		/* build a tuple */
		tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
	}
}