/* * 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)))); } }
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); }
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); }
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); }
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); }
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); }
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)); }
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); }
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; }
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); }
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); }
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; }
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; }
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)); } }