3
* PostgreSQL wrappers for pgp.
5
* Copyright (c) 2005 Marko Kreen
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* contrib/pgcrypto/pgp-pgsql.c
34
#include "lib/stringinfo.h"
35
#include "catalog/pg_type.h"
36
#include "mb/pg_wchar.h"
37
#include "utils/builtins.h"
38
#include "utils/array.h"
48
PG_FUNCTION_INFO_V1(pgp_sym_encrypt_bytea);
49
PG_FUNCTION_INFO_V1(pgp_sym_encrypt_text);
50
PG_FUNCTION_INFO_V1(pgp_sym_decrypt_bytea);
51
PG_FUNCTION_INFO_V1(pgp_sym_decrypt_text);
53
PG_FUNCTION_INFO_V1(pgp_pub_encrypt_bytea);
54
PG_FUNCTION_INFO_V1(pgp_pub_encrypt_text);
55
PG_FUNCTION_INFO_V1(pgp_pub_decrypt_bytea);
56
PG_FUNCTION_INFO_V1(pgp_pub_decrypt_text);
58
PG_FUNCTION_INFO_V1(pgp_key_id_w);
60
PG_FUNCTION_INFO_V1(pg_armor);
61
PG_FUNCTION_INFO_V1(pg_dearmor);
62
PG_FUNCTION_INFO_V1(pgp_armor_headers);
65
* returns src in case of no conversion or error
68
convert_charset(text *src, int cset_from, int cset_to)
70
int src_len = VARSIZE_ANY_EXHDR(src);
72
unsigned char *csrc = (unsigned char *) VARDATA_ANY(src);
75
dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
79
res = cstring_to_text((char *) dst);
85
convert_from_utf8(text *src)
87
return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
91
convert_to_utf8(text *src)
93
return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
97
string_is_ascii(const char *str)
101
for (p = str; *p; p++)
103
if (IS_HIGHBIT_SET(*p))
110
clear_and_pfree(text *p)
112
px_memset(p, 0, VARSIZE_ANY(p));
117
* expect-* arguments storage
135
fill_expect(struct debug_expect *ex, int text_mode)
139
ex->cipher_algo = -1;
142
ex->s2k_cipher_algo = -1;
143
ex->s2k_digest_algo = -1;
144
ex->compress_algo = -1;
145
ex->use_sess_key = -1;
146
ex->disable_mdc = -1;
147
ex->unicode_mode = -1;
150
#define EX_MSG(arg) \
151
ereport(NOTICE, (errmsg( \
152
"pgp_decrypt: unexpected %s: expected %d got %d", \
153
CppAsString(arg), ex->arg, ctx->arg)))
155
#define EX_CHECK(arg) do { \
156
if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
160
check_expect(PGP_Context *ctx, struct debug_expect *ex)
162
EX_CHECK(cipher_algo);
165
EX_CHECK(s2k_digest_algo);
166
EX_CHECK(use_sess_key);
167
if (ctx->use_sess_key)
168
EX_CHECK(s2k_cipher_algo);
169
EX_CHECK(disable_mdc);
170
EX_CHECK(compress_algo);
171
EX_CHECK(unicode_mode);
175
show_debug(const char *msg)
177
ereport(NOTICE, (errmsg("dbg: %s", msg)));
181
set_arg(PGP_Context *ctx, char *key, char *val,
182
struct debug_expect *ex)
186
if (strcmp(key, "cipher-algo") == 0)
187
res = pgp_set_cipher_algo(ctx, val);
188
else if (strcmp(key, "disable-mdc") == 0)
189
res = pgp_disable_mdc(ctx, atoi(val));
190
else if (strcmp(key, "sess-key") == 0)
191
res = pgp_set_sess_key(ctx, atoi(val));
192
else if (strcmp(key, "s2k-mode") == 0)
193
res = pgp_set_s2k_mode(ctx, atoi(val));
194
else if (strcmp(key, "s2k-count") == 0)
195
res = pgp_set_s2k_count(ctx, atoi(val));
196
else if (strcmp(key, "s2k-digest-algo") == 0)
197
res = pgp_set_s2k_digest_algo(ctx, val);
198
else if (strcmp(key, "s2k-cipher-algo") == 0)
199
res = pgp_set_s2k_cipher_algo(ctx, val);
200
else if (strcmp(key, "compress-algo") == 0)
201
res = pgp_set_compress_algo(ctx, atoi(val));
202
else if (strcmp(key, "compress-level") == 0)
203
res = pgp_set_compress_level(ctx, atoi(val));
204
else if (strcmp(key, "convert-crlf") == 0)
205
res = pgp_set_convert_crlf(ctx, atoi(val));
206
else if (strcmp(key, "unicode-mode") == 0)
207
res = pgp_set_unicode_mode(ctx, atoi(val));
210
* The remaining options are for debugging/testing and are therefore not
211
* documented in the user-facing docs.
213
else if (ex != NULL && strcmp(key, "debug") == 0)
214
ex->debug = atoi(val);
215
else if (ex != NULL && strcmp(key, "expect-cipher-algo") == 0)
218
ex->cipher_algo = pgp_get_cipher_code(val);
220
else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
223
ex->disable_mdc = atoi(val);
225
else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
228
ex->use_sess_key = atoi(val);
230
else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
233
ex->s2k_mode = atoi(val);
235
else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
238
ex->s2k_count = atoi(val);
240
else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
243
ex->s2k_digest_algo = pgp_get_digest_code(val);
245
else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
248
ex->s2k_cipher_algo = pgp_get_cipher_code(val);
250
else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
253
ex->compress_algo = atoi(val);
255
else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
258
ex->unicode_mode = atoi(val);
261
res = PXE_ARGUMENT_ERROR;
267
* Find next word. Handle ',' and '=' as words. Skip whitespace.
268
* Put word info into res_p, res_len.
269
* Returns ptr to next word.
272
getword(char *p, char **res_p, int *res_len)
274
/* whitespace at start */
275
while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
280
if (*p == '=' || *p == ',')
283
while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
284
|| *p == '=' || *p == ','))
288
*res_len = p - *res_p;
290
/* whitespace at end */
291
while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
298
* Convert to lowercase asciiz string.
301
downcase_convert(const uint8 *s, int len)
305
char *res = palloc(len + 1);
307
for (i = 0; i < len; i++)
310
if (c >= 'A' && c <= 'Z')
319
parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
320
struct debug_expect *ex)
322
char *str = downcase_convert(args, arg_len);
332
res = PXE_ARGUMENT_ERROR;
333
p = getword(p, &key, &key_len);
336
p = getword(p, &val, &val_len);
339
else if (*p++ != ',')
342
if (*key == 0 || *val == 0 || val_len == 0)
348
res = set_arg(ctx, key, val, ex);
357
create_mbuf_from_vardata(text *data)
359
return mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
360
VARSIZE_ANY_EXHDR(data));
364
init_work(PGP_Context **ctx_p, int is_text,
365
text *args, struct debug_expect *ex)
367
int err = pgp_init(ctx_p);
369
fill_expect(ex, is_text);
371
if (err == 0 && args != NULL)
372
err = parse_args(*ctx_p, (uint8 *) VARDATA_ANY(args),
373
VARSIZE_ANY_EXHDR(args), ex);
379
px_set_debug_handler(show_debug);
381
pgp_set_text_mode(*ctx_p, is_text);
385
encrypt_internal(int is_pubenc, int is_text,
386
text *data, text *key, text *args)
396
struct debug_expect ex;
397
text *tmp_data = NULL;
399
init_work(&ctx, is_text, args, &ex);
401
if (is_text && pgp_get_unicode_mode(ctx))
403
tmp_data = convert_to_utf8(data);
404
if (tmp_data == data)
410
src = create_mbuf_from_vardata(data);
411
dst = mbuf_create(VARSIZE_ANY(data) + 128);
414
* reserve room for header
416
mbuf_append(dst, tmp, VARHDRSZ);
423
MBuf *kbuf = create_mbuf_from_vardata(key);
425
err = pgp_set_pubkey(ctx, kbuf,
430
err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
431
VARSIZE_ANY_EXHDR(key));
437
err = pgp_encrypt(ctx, src, dst);
445
px_set_debug_handler(NULL);
447
clear_and_pfree(tmp_data);
454
/* res_len includes VARHDRSZ */
455
res_len = mbuf_steal_data(dst, &restmp);
456
res = (bytea *) restmp;
457
SET_VARSIZE(res, res_len);
460
clear_and_pfree(tmp_data);
465
px_set_debug_handler(NULL);
471
decrypt_internal(int is_pubenc, int need_text, text *data,
472
text *key, text *keypsw, text *args)
481
PGP_Context *ctx = NULL;
482
struct debug_expect ex;
486
init_work(&ctx, need_text, args, &ex);
488
src = mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
489
VARSIZE_ANY_EXHDR(data));
490
dst = mbuf_create(VARSIZE_ANY(data) + 2048);
493
* reserve room for header
495
mbuf_append(dst, tmp, VARHDRSZ);
508
psw = (uint8 *) VARDATA_ANY(keypsw);
509
psw_len = VARSIZE_ANY_EXHDR(keypsw);
511
kbuf = create_mbuf_from_vardata(key);
512
err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
516
err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
517
VARSIZE_ANY_EXHDR(key));
522
err = pgp_decrypt(ctx, src, dst);
525
check_expect(ctx, &ex);
527
/* remember the setting */
528
got_unicode = pgp_get_unicode_mode(ctx);
536
px_set_debug_handler(NULL);
541
res_len = mbuf_steal_data(dst, &restmp);
544
/* res_len includes VARHDRSZ */
545
res = (bytea *) restmp;
546
SET_VARSIZE(res, res_len);
548
if (need_text && got_unicode)
550
text *utf = convert_from_utf8(res);
554
clear_and_pfree(res);
558
px_set_debug_handler(NULL);
564
* Wrappers for symmetric-key functions
567
pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
574
data = PG_GETARG_BYTEA_PP(0);
575
key = PG_GETARG_BYTEA_PP(1);
577
arg = PG_GETARG_BYTEA_PP(2);
579
res = encrypt_internal(0, 0, data, key, arg);
581
PG_FREE_IF_COPY(data, 0);
582
PG_FREE_IF_COPY(key, 1);
584
PG_FREE_IF_COPY(arg, 2);
585
PG_RETURN_TEXT_P(res);
589
pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
596
data = PG_GETARG_BYTEA_PP(0);
597
key = PG_GETARG_BYTEA_PP(1);
599
arg = PG_GETARG_BYTEA_PP(2);
601
res = encrypt_internal(0, 1, data, key, arg);
603
PG_FREE_IF_COPY(data, 0);
604
PG_FREE_IF_COPY(key, 1);
606
PG_FREE_IF_COPY(arg, 2);
607
PG_RETURN_TEXT_P(res);
612
pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
619
data = PG_GETARG_BYTEA_PP(0);
620
key = PG_GETARG_BYTEA_PP(1);
622
arg = PG_GETARG_BYTEA_PP(2);
624
res = decrypt_internal(0, 0, data, key, NULL, arg);
626
PG_FREE_IF_COPY(data, 0);
627
PG_FREE_IF_COPY(key, 1);
629
PG_FREE_IF_COPY(arg, 2);
630
PG_RETURN_TEXT_P(res);
634
pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
641
data = PG_GETARG_BYTEA_PP(0);
642
key = PG_GETARG_BYTEA_PP(1);
644
arg = PG_GETARG_BYTEA_PP(2);
646
res = decrypt_internal(0, 1, data, key, NULL, arg);
648
PG_FREE_IF_COPY(data, 0);
649
PG_FREE_IF_COPY(key, 1);
651
PG_FREE_IF_COPY(arg, 2);
652
PG_RETURN_TEXT_P(res);
656
* Wrappers for public-key functions
660
pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
667
data = PG_GETARG_BYTEA_PP(0);
668
key = PG_GETARG_BYTEA_PP(1);
670
arg = PG_GETARG_BYTEA_PP(2);
672
res = encrypt_internal(1, 0, data, key, arg);
674
PG_FREE_IF_COPY(data, 0);
675
PG_FREE_IF_COPY(key, 1);
677
PG_FREE_IF_COPY(arg, 2);
678
PG_RETURN_TEXT_P(res);
682
pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
689
data = PG_GETARG_BYTEA_PP(0);
690
key = PG_GETARG_BYTEA_PP(1);
692
arg = PG_GETARG_BYTEA_PP(2);
694
res = encrypt_internal(1, 1, data, key, arg);
696
PG_FREE_IF_COPY(data, 0);
697
PG_FREE_IF_COPY(key, 1);
699
PG_FREE_IF_COPY(arg, 2);
700
PG_RETURN_TEXT_P(res);
705
pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
713
data = PG_GETARG_BYTEA_PP(0);
714
key = PG_GETARG_BYTEA_PP(1);
716
psw = PG_GETARG_BYTEA_PP(2);
718
arg = PG_GETARG_BYTEA_PP(3);
720
res = decrypt_internal(1, 0, data, key, psw, arg);
722
PG_FREE_IF_COPY(data, 0);
723
PG_FREE_IF_COPY(key, 1);
725
PG_FREE_IF_COPY(psw, 2);
727
PG_FREE_IF_COPY(arg, 3);
728
PG_RETURN_TEXT_P(res);
732
pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
740
data = PG_GETARG_BYTEA_PP(0);
741
key = PG_GETARG_BYTEA_PP(1);
743
psw = PG_GETARG_BYTEA_PP(2);
745
arg = PG_GETARG_BYTEA_PP(3);
747
res = decrypt_internal(1, 1, data, key, psw, arg);
749
PG_FREE_IF_COPY(data, 0);
750
PG_FREE_IF_COPY(key, 1);
752
PG_FREE_IF_COPY(psw, 2);
754
PG_FREE_IF_COPY(arg, 3);
755
PG_RETURN_TEXT_P(res);
760
* Wrappers for PGP ascii armor
764
* Helper function for pgp_armor. Converts arrays of keys and values into
765
* plain C arrays, and checks that they don't contain invalid characters.
768
parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
769
char ***p_keys, char ***p_values)
771
int nkdims = ARR_NDIM(key_array);
772
int nvdims = ARR_NDIM(val_array);
783
if (nkdims > 1 || nkdims != nvdims)
785
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
786
errmsg("wrong number of array subscripts")));
790
deconstruct_array(key_array,
791
TEXTOID, -1, false, 'i',
792
&key_datums, &key_nulls, &key_count);
794
deconstruct_array(val_array,
795
TEXTOID, -1, false, 'i',
796
&val_datums, &val_nulls, &val_count);
798
if (key_count != val_count)
800
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
801
errmsg("mismatched array dimensions")));
803
keys = (char **) palloc(sizeof(char *) * key_count);
804
values = (char **) palloc(sizeof(char *) * val_count);
806
for (i = 0; i < key_count; i++)
810
/* Check that the key doesn't contain anything funny */
813
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
814
errmsg("null value not allowed for header key")));
816
v = TextDatumGetCString(key_datums[i]);
818
if (!string_is_ascii(v))
820
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
821
errmsg("header key must not contain non-ASCII characters")));
824
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
825
errmsg("header key must not contain \": \"")));
828
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
829
errmsg("header key must not contain newlines")));
832
/* And the same for the value */
835
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
836
errmsg("null value not allowed for header value")));
838
v = TextDatumGetCString(val_datums[i]);
840
if (!string_is_ascii(v))
842
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
843
errmsg("header value must not contain non-ASCII characters")));
846
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
847
errmsg("header value must not contain newlines")));
858
pg_armor(PG_FUNCTION_ARGS)
868
data = PG_GETARG_BYTEA_PP(0);
869
data_len = VARSIZE_ANY_EXHDR(data);
872
num_headers = parse_key_value_arrays(PG_GETARG_ARRAYTYPE_P(1),
873
PG_GETARG_ARRAYTYPE_P(2),
876
else if (PG_NARGS() == 1)
879
elog(ERROR, "unexpected number of arguments %d", PG_NARGS());
881
initStringInfo(&buf);
883
pgp_armor_encode((uint8 *) VARDATA_ANY(data), data_len, &buf,
884
num_headers, keys, values);
886
res = palloc(VARHDRSZ + buf.len);
887
SET_VARSIZE(res, VARHDRSZ + buf.len);
888
memcpy(VARDATA(res), buf.data, buf.len);
891
PG_FREE_IF_COPY(data, 0);
892
PG_RETURN_TEXT_P(res);
896
pg_dearmor(PG_FUNCTION_ARGS)
904
data = PG_GETARG_TEXT_PP(0);
905
data_len = VARSIZE_ANY_EXHDR(data);
907
initStringInfo(&buf);
909
ret = pgp_armor_decode((uint8 *) VARDATA_ANY(data), data_len, &buf);
912
res = palloc(VARHDRSZ + buf.len);
913
SET_VARSIZE(res, VARHDRSZ + buf.len);
914
memcpy(VARDATA(res), buf.data, buf.len);
917
PG_FREE_IF_COPY(data, 0);
918
PG_RETURN_TEXT_P(res);
921
/* cross-call state for pgp_armor_headers */
927
} pgp_armor_headers_state;
930
pgp_armor_headers(PG_FUNCTION_ARGS)
932
FuncCallContext *funcctx;
933
pgp_armor_headers_state *state;
938
AttInMetadata *attinmeta;
940
if (SRF_IS_FIRSTCALL())
942
text *data = PG_GETARG_TEXT_PP(0);
944
MemoryContext oldcontext;
946
funcctx = SRF_FIRSTCALL_INIT();
948
/* we need the state allocated in the multi call context */
949
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
951
/* Build a tuple descriptor for our result type */
952
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
953
elog(ERROR, "return type must be a row type");
955
attinmeta = TupleDescGetAttInMetadata(tupdesc);
956
funcctx->attinmeta = attinmeta;
958
state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
960
res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
961
VARSIZE_ANY_EXHDR(data),
962
&state->nheaders, &state->keys,
967
MemoryContextSwitchTo(oldcontext);
968
funcctx->user_fctx = state;
971
funcctx = SRF_PERCALL_SETUP();
972
state = (pgp_armor_headers_state *) funcctx->user_fctx;
974
if (funcctx->call_cntr >= state->nheaders)
975
SRF_RETURN_DONE(funcctx);
980
/* we assume that the keys (and values) are in UTF-8. */
981
utf8key = state->keys[funcctx->call_cntr];
982
utf8val = state->values[funcctx->call_cntr];
984
values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
985
values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);
988
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
989
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
996
* Wrappers for PGP key id
1000
pgp_key_id_w(PG_FUNCTION_ARGS)
1007
data = PG_GETARG_BYTEA_PP(0);
1008
buf = create_mbuf_from_vardata(data);
1009
res = palloc(VARHDRSZ + 17);
1011
res_len = pgp_get_keyid(buf, VARDATA(res));
1014
px_THROW_ERROR(res_len);
1015
SET_VARSIZE(res, VARHDRSZ + res_len);
1017
PG_FREE_IF_COPY(data, 0);
1018
PG_RETURN_TEXT_P(res);