~ubuntu-branches/debian/experimental/postgresql-11/experimental

« back to all changes in this revision

Viewing changes to contrib/pgcrypto/pgp-pgsql.c

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2018-05-22 14:19:08 UTC
  • Revision ID: package-import@ubuntu.com-20180522141908-0oy9ujs1b5vrda74
Tags: upstream-11~beta1
ImportĀ upstreamĀ versionĀ 11~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pgp-pgsql.c
 
3
 *              PostgreSQL wrappers for pgp.
 
4
 *
 
5
 * Copyright (c) 2005 Marko Kreen
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
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.
 
16
 *
 
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
 
27
 * SUCH DAMAGE.
 
28
 *
 
29
 * contrib/pgcrypto/pgp-pgsql.c
 
30
 */
 
31
 
 
32
#include "postgres.h"
 
33
 
 
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"
 
39
#include "funcapi.h"
 
40
 
 
41
#include "mbuf.h"
 
42
#include "px.h"
 
43
#include "pgp.h"
 
44
 
 
45
/*
 
46
 * public functions
 
47
 */
 
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);
 
52
 
 
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);
 
57
 
 
58
PG_FUNCTION_INFO_V1(pgp_key_id_w);
 
59
 
 
60
PG_FUNCTION_INFO_V1(pg_armor);
 
61
PG_FUNCTION_INFO_V1(pg_dearmor);
 
62
PG_FUNCTION_INFO_V1(pgp_armor_headers);
 
63
 
 
64
/*
 
65
 * returns src in case of no conversion or error
 
66
 */
 
67
static text *
 
68
convert_charset(text *src, int cset_from, int cset_to)
 
69
{
 
70
        int                     src_len = VARSIZE_ANY_EXHDR(src);
 
71
        unsigned char *dst;
 
72
        unsigned char *csrc = (unsigned char *) VARDATA_ANY(src);
 
73
        text       *res;
 
74
 
 
75
        dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
 
76
        if (dst == csrc)
 
77
                return src;
 
78
 
 
79
        res = cstring_to_text((char *) dst);
 
80
        pfree(dst);
 
81
        return res;
 
82
}
 
83
 
 
84
static text *
 
85
convert_from_utf8(text *src)
 
86
{
 
87
        return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
 
88
}
 
89
 
 
90
static text *
 
91
convert_to_utf8(text *src)
 
92
{
 
93
        return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
 
94
}
 
95
 
 
96
static bool
 
97
string_is_ascii(const char *str)
 
98
{
 
99
        const char *p;
 
100
 
 
101
        for (p = str; *p; p++)
 
102
        {
 
103
                if (IS_HIGHBIT_SET(*p))
 
104
                        return false;
 
105
        }
 
106
        return true;
 
107
}
 
108
 
 
109
static void
 
110
clear_and_pfree(text *p)
 
111
{
 
112
        px_memset(p, 0, VARSIZE_ANY(p));
 
113
        pfree(p);
 
114
}
 
115
 
 
116
/*
 
117
 * expect-* arguments storage
 
118
 */
 
119
struct debug_expect
 
120
{
 
121
        int                     debug;
 
122
        int                     expect;
 
123
        int                     cipher_algo;
 
124
        int                     s2k_mode;
 
125
        int                     s2k_count;
 
126
        int                     s2k_cipher_algo;
 
127
        int                     s2k_digest_algo;
 
128
        int                     compress_algo;
 
129
        int                     use_sess_key;
 
130
        int                     disable_mdc;
 
131
        int                     unicode_mode;
 
132
};
 
133
 
 
134
static void
 
135
fill_expect(struct debug_expect *ex, int text_mode)
 
136
{
 
137
        ex->debug = 0;
 
138
        ex->expect = 0;
 
139
        ex->cipher_algo = -1;
 
140
        ex->s2k_mode = -1;
 
141
        ex->s2k_count = -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;
 
148
}
 
149
 
 
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)))
 
154
 
 
155
#define EX_CHECK(arg) do { \
 
156
                if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
 
157
        } while (0)
 
158
 
 
159
static void
 
160
check_expect(PGP_Context *ctx, struct debug_expect *ex)
 
161
{
 
162
        EX_CHECK(cipher_algo);
 
163
        EX_CHECK(s2k_mode);
 
164
        EX_CHECK(s2k_count);
 
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);
 
172
}
 
173
 
 
174
static void
 
175
show_debug(const char *msg)
 
176
{
 
177
        ereport(NOTICE, (errmsg("dbg: %s", msg)));
 
178
}
 
179
 
 
180
static int
 
181
set_arg(PGP_Context *ctx, char *key, char *val,
 
182
                struct debug_expect *ex)
 
183
{
 
184
        int                     res = 0;
 
185
 
 
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));
 
208
 
 
209
        /*
 
210
         * The remaining options are for debugging/testing and are therefore not
 
211
         * documented in the user-facing docs.
 
212
         */
 
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)
 
216
        {
 
217
                ex->expect = 1;
 
218
                ex->cipher_algo = pgp_get_cipher_code(val);
 
219
        }
 
220
        else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
 
221
        {
 
222
                ex->expect = 1;
 
223
                ex->disable_mdc = atoi(val);
 
224
        }
 
225
        else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
 
226
        {
 
227
                ex->expect = 1;
 
228
                ex->use_sess_key = atoi(val);
 
229
        }
 
230
        else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
 
231
        {
 
232
                ex->expect = 1;
 
233
                ex->s2k_mode = atoi(val);
 
234
        }
 
235
        else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
 
236
        {
 
237
                ex->expect = 1;
 
238
                ex->s2k_count = atoi(val);
 
239
        }
 
240
        else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
 
241
        {
 
242
                ex->expect = 1;
 
243
                ex->s2k_digest_algo = pgp_get_digest_code(val);
 
244
        }
 
245
        else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
 
246
        {
 
247
                ex->expect = 1;
 
248
                ex->s2k_cipher_algo = pgp_get_cipher_code(val);
 
249
        }
 
250
        else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
 
251
        {
 
252
                ex->expect = 1;
 
253
                ex->compress_algo = atoi(val);
 
254
        }
 
255
        else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
 
256
        {
 
257
                ex->expect = 1;
 
258
                ex->unicode_mode = atoi(val);
 
259
        }
 
260
        else
 
261
                res = PXE_ARGUMENT_ERROR;
 
262
 
 
263
        return res;
 
264
}
 
265
 
 
266
/*
 
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.
 
270
 */
 
271
static char *
 
272
getword(char *p, char **res_p, int *res_len)
 
273
{
 
274
        /* whitespace at start */
 
275
        while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
 
276
                p++;
 
277
 
 
278
        /* word data */
 
279
        *res_p = p;
 
280
        if (*p == '=' || *p == ',')
 
281
                p++;
 
282
        else
 
283
                while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
 
284
                                           || *p == '=' || *p == ','))
 
285
                        p++;
 
286
 
 
287
        /* word end */
 
288
        *res_len = p - *res_p;
 
289
 
 
290
        /* whitespace at end */
 
291
        while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
 
292
                p++;
 
293
 
 
294
        return p;
 
295
}
 
296
 
 
297
/*
 
298
 * Convert to lowercase asciiz string.
 
299
 */
 
300
static char *
 
301
downcase_convert(const uint8 *s, int len)
 
302
{
 
303
        int                     c,
 
304
                                i;
 
305
        char       *res = palloc(len + 1);
 
306
 
 
307
        for (i = 0; i < len; i++)
 
308
        {
 
309
                c = s[i];
 
310
                if (c >= 'A' && c <= 'Z')
 
311
                        c += 'a' - 'A';
 
312
                res[i] = c;
 
313
        }
 
314
        res[len] = 0;
 
315
        return res;
 
316
}
 
317
 
 
318
static int
 
319
parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
 
320
                   struct debug_expect *ex)
 
321
{
 
322
        char       *str = downcase_convert(args, arg_len);
 
323
        char       *key,
 
324
                           *val;
 
325
        int                     key_len,
 
326
                                val_len;
 
327
        int                     res = 0;
 
328
        char       *p = str;
 
329
 
 
330
        while (*p)
 
331
        {
 
332
                res = PXE_ARGUMENT_ERROR;
 
333
                p = getword(p, &key, &key_len);
 
334
                if (*p++ != '=')
 
335
                        break;
 
336
                p = getword(p, &val, &val_len);
 
337
                if (*p == '\0')
 
338
                        ;
 
339
                else if (*p++ != ',')
 
340
                        break;
 
341
 
 
342
                if (*key == 0 || *val == 0 || val_len == 0)
 
343
                        break;
 
344
 
 
345
                key[key_len] = 0;
 
346
                val[val_len] = 0;
 
347
 
 
348
                res = set_arg(ctx, key, val, ex);
 
349
                if (res < 0)
 
350
                        break;
 
351
        }
 
352
        pfree(str);
 
353
        return res;
 
354
}
 
355
 
 
356
static MBuf *
 
357
create_mbuf_from_vardata(text *data)
 
358
{
 
359
        return mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
 
360
                                                                 VARSIZE_ANY_EXHDR(data));
 
361
}
 
362
 
 
363
static void
 
364
init_work(PGP_Context **ctx_p, int is_text,
 
365
                  text *args, struct debug_expect *ex)
 
366
{
 
367
        int                     err = pgp_init(ctx_p);
 
368
 
 
369
        fill_expect(ex, is_text);
 
370
 
 
371
        if (err == 0 && args != NULL)
 
372
                err = parse_args(*ctx_p, (uint8 *) VARDATA_ANY(args),
 
373
                                                 VARSIZE_ANY_EXHDR(args), ex);
 
374
 
 
375
        if (err)
 
376
                px_THROW_ERROR(err);
 
377
 
 
378
        if (ex->debug)
 
379
                px_set_debug_handler(show_debug);
 
380
 
 
381
        pgp_set_text_mode(*ctx_p, is_text);
 
382
}
 
383
 
 
384
static bytea *
 
385
encrypt_internal(int is_pubenc, int is_text,
 
386
                                 text *data, text *key, text *args)
 
387
{
 
388
        MBuf       *src,
 
389
                           *dst;
 
390
        uint8           tmp[VARHDRSZ];
 
391
        uint8      *restmp;
 
392
        bytea      *res;
 
393
        int                     res_len;
 
394
        PGP_Context *ctx;
 
395
        int                     err;
 
396
        struct debug_expect ex;
 
397
        text       *tmp_data = NULL;
 
398
 
 
399
        init_work(&ctx, is_text, args, &ex);
 
400
 
 
401
        if (is_text && pgp_get_unicode_mode(ctx))
 
402
        {
 
403
                tmp_data = convert_to_utf8(data);
 
404
                if (tmp_data == data)
 
405
                        tmp_data = NULL;
 
406
                else
 
407
                        data = tmp_data;
 
408
        }
 
409
 
 
410
        src = create_mbuf_from_vardata(data);
 
411
        dst = mbuf_create(VARSIZE_ANY(data) + 128);
 
412
 
 
413
        /*
 
414
         * reserve room for header
 
415
         */
 
416
        mbuf_append(dst, tmp, VARHDRSZ);
 
417
 
 
418
        /*
 
419
         * set key
 
420
         */
 
421
        if (is_pubenc)
 
422
        {
 
423
                MBuf       *kbuf = create_mbuf_from_vardata(key);
 
424
 
 
425
                err = pgp_set_pubkey(ctx, kbuf,
 
426
                                                         NULL, 0, 0);
 
427
                mbuf_free(kbuf);
 
428
        }
 
429
        else
 
430
                err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
 
431
                                                         VARSIZE_ANY_EXHDR(key));
 
432
 
 
433
        /*
 
434
         * encrypt
 
435
         */
 
436
        if (err >= 0)
 
437
                err = pgp_encrypt(ctx, src, dst);
 
438
 
 
439
        /*
 
440
         * check for error
 
441
         */
 
442
        if (err)
 
443
        {
 
444
                if (ex.debug)
 
445
                        px_set_debug_handler(NULL);
 
446
                if (tmp_data)
 
447
                        clear_and_pfree(tmp_data);
 
448
                pgp_free(ctx);
 
449
                mbuf_free(src);
 
450
                mbuf_free(dst);
 
451
                px_THROW_ERROR(err);
 
452
        }
 
453
 
 
454
        /* res_len includes VARHDRSZ */
 
455
        res_len = mbuf_steal_data(dst, &restmp);
 
456
        res = (bytea *) restmp;
 
457
        SET_VARSIZE(res, res_len);
 
458
 
 
459
        if (tmp_data)
 
460
                clear_and_pfree(tmp_data);
 
461
        pgp_free(ctx);
 
462
        mbuf_free(src);
 
463
        mbuf_free(dst);
 
464
 
 
465
        px_set_debug_handler(NULL);
 
466
 
 
467
        return res;
 
468
}
 
469
 
 
470
static bytea *
 
471
decrypt_internal(int is_pubenc, int need_text, text *data,
 
472
                                 text *key, text *keypsw, text *args)
 
473
{
 
474
        int                     err;
 
475
        MBuf       *src = NULL,
 
476
                           *dst = NULL;
 
477
        uint8           tmp[VARHDRSZ];
 
478
        uint8      *restmp;
 
479
        bytea      *res;
 
480
        int                     res_len;
 
481
        PGP_Context *ctx = NULL;
 
482
        struct debug_expect ex;
 
483
        int                     got_unicode = 0;
 
484
 
 
485
 
 
486
        init_work(&ctx, need_text, args, &ex);
 
487
 
 
488
        src = mbuf_create_from_data((uint8 *) VARDATA_ANY(data),
 
489
                                                                VARSIZE_ANY_EXHDR(data));
 
490
        dst = mbuf_create(VARSIZE_ANY(data) + 2048);
 
491
 
 
492
        /*
 
493
         * reserve room for header
 
494
         */
 
495
        mbuf_append(dst, tmp, VARHDRSZ);
 
496
 
 
497
        /*
 
498
         * set key
 
499
         */
 
500
        if (is_pubenc)
 
501
        {
 
502
                uint8      *psw = NULL;
 
503
                int                     psw_len = 0;
 
504
                MBuf       *kbuf;
 
505
 
 
506
                if (keypsw)
 
507
                {
 
508
                        psw = (uint8 *) VARDATA_ANY(keypsw);
 
509
                        psw_len = VARSIZE_ANY_EXHDR(keypsw);
 
510
                }
 
511
                kbuf = create_mbuf_from_vardata(key);
 
512
                err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
 
513
                mbuf_free(kbuf);
 
514
        }
 
515
        else
 
516
                err = pgp_set_symkey(ctx, (uint8 *) VARDATA_ANY(key),
 
517
                                                         VARSIZE_ANY_EXHDR(key));
 
518
 
 
519
        /* decrypt */
 
520
        if (err >= 0)
 
521
        {
 
522
                err = pgp_decrypt(ctx, src, dst);
 
523
 
 
524
                if (ex.expect)
 
525
                        check_expect(ctx, &ex);
 
526
 
 
527
                /* remember the setting */
 
528
                got_unicode = pgp_get_unicode_mode(ctx);
 
529
        }
 
530
 
 
531
        mbuf_free(src);
 
532
        pgp_free(ctx);
 
533
 
 
534
        if (err)
 
535
        {
 
536
                px_set_debug_handler(NULL);
 
537
                mbuf_free(dst);
 
538
                px_THROW_ERROR(err);
 
539
        }
 
540
 
 
541
        res_len = mbuf_steal_data(dst, &restmp);
 
542
        mbuf_free(dst);
 
543
 
 
544
        /* res_len includes VARHDRSZ */
 
545
        res = (bytea *) restmp;
 
546
        SET_VARSIZE(res, res_len);
 
547
 
 
548
        if (need_text && got_unicode)
 
549
        {
 
550
                text       *utf = convert_from_utf8(res);
 
551
 
 
552
                if (utf != res)
 
553
                {
 
554
                        clear_and_pfree(res);
 
555
                        res = utf;
 
556
                }
 
557
        }
 
558
        px_set_debug_handler(NULL);
 
559
 
 
560
        return res;
 
561
}
 
562
 
 
563
/*
 
564
 * Wrappers for symmetric-key functions
 
565
 */
 
566
Datum
 
567
pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
 
568
{
 
569
        bytea      *data,
 
570
                           *key;
 
571
        text       *arg = NULL;
 
572
        text       *res;
 
573
 
 
574
        data = PG_GETARG_BYTEA_PP(0);
 
575
        key = PG_GETARG_BYTEA_PP(1);
 
576
        if (PG_NARGS() > 2)
 
577
                arg = PG_GETARG_BYTEA_PP(2);
 
578
 
 
579
        res = encrypt_internal(0, 0, data, key, arg);
 
580
 
 
581
        PG_FREE_IF_COPY(data, 0);
 
582
        PG_FREE_IF_COPY(key, 1);
 
583
        if (PG_NARGS() > 2)
 
584
                PG_FREE_IF_COPY(arg, 2);
 
585
        PG_RETURN_TEXT_P(res);
 
586
}
 
587
 
 
588
Datum
 
589
pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
 
590
{
 
591
        bytea      *data,
 
592
                           *key;
 
593
        text       *arg = NULL;
 
594
        text       *res;
 
595
 
 
596
        data = PG_GETARG_BYTEA_PP(0);
 
597
        key = PG_GETARG_BYTEA_PP(1);
 
598
        if (PG_NARGS() > 2)
 
599
                arg = PG_GETARG_BYTEA_PP(2);
 
600
 
 
601
        res = encrypt_internal(0, 1, data, key, arg);
 
602
 
 
603
        PG_FREE_IF_COPY(data, 0);
 
604
        PG_FREE_IF_COPY(key, 1);
 
605
        if (PG_NARGS() > 2)
 
606
                PG_FREE_IF_COPY(arg, 2);
 
607
        PG_RETURN_TEXT_P(res);
 
608
}
 
609
 
 
610
 
 
611
Datum
 
612
pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
 
613
{
 
614
        bytea      *data,
 
615
                           *key;
 
616
        text       *arg = NULL;
 
617
        text       *res;
 
618
 
 
619
        data = PG_GETARG_BYTEA_PP(0);
 
620
        key = PG_GETARG_BYTEA_PP(1);
 
621
        if (PG_NARGS() > 2)
 
622
                arg = PG_GETARG_BYTEA_PP(2);
 
623
 
 
624
        res = decrypt_internal(0, 0, data, key, NULL, arg);
 
625
 
 
626
        PG_FREE_IF_COPY(data, 0);
 
627
        PG_FREE_IF_COPY(key, 1);
 
628
        if (PG_NARGS() > 2)
 
629
                PG_FREE_IF_COPY(arg, 2);
 
630
        PG_RETURN_TEXT_P(res);
 
631
}
 
632
 
 
633
Datum
 
634
pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
 
635
{
 
636
        bytea      *data,
 
637
                           *key;
 
638
        text       *arg = NULL;
 
639
        text       *res;
 
640
 
 
641
        data = PG_GETARG_BYTEA_PP(0);
 
642
        key = PG_GETARG_BYTEA_PP(1);
 
643
        if (PG_NARGS() > 2)
 
644
                arg = PG_GETARG_BYTEA_PP(2);
 
645
 
 
646
        res = decrypt_internal(0, 1, data, key, NULL, arg);
 
647
 
 
648
        PG_FREE_IF_COPY(data, 0);
 
649
        PG_FREE_IF_COPY(key, 1);
 
650
        if (PG_NARGS() > 2)
 
651
                PG_FREE_IF_COPY(arg, 2);
 
652
        PG_RETURN_TEXT_P(res);
 
653
}
 
654
 
 
655
/*
 
656
 * Wrappers for public-key functions
 
657
 */
 
658
 
 
659
Datum
 
660
pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
 
661
{
 
662
        bytea      *data,
 
663
                           *key;
 
664
        text       *arg = NULL;
 
665
        text       *res;
 
666
 
 
667
        data = PG_GETARG_BYTEA_PP(0);
 
668
        key = PG_GETARG_BYTEA_PP(1);
 
669
        if (PG_NARGS() > 2)
 
670
                arg = PG_GETARG_BYTEA_PP(2);
 
671
 
 
672
        res = encrypt_internal(1, 0, data, key, arg);
 
673
 
 
674
        PG_FREE_IF_COPY(data, 0);
 
675
        PG_FREE_IF_COPY(key, 1);
 
676
        if (PG_NARGS() > 2)
 
677
                PG_FREE_IF_COPY(arg, 2);
 
678
        PG_RETURN_TEXT_P(res);
 
679
}
 
680
 
 
681
Datum
 
682
pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
 
683
{
 
684
        bytea      *data,
 
685
                           *key;
 
686
        text       *arg = NULL;
 
687
        text       *res;
 
688
 
 
689
        data = PG_GETARG_BYTEA_PP(0);
 
690
        key = PG_GETARG_BYTEA_PP(1);
 
691
        if (PG_NARGS() > 2)
 
692
                arg = PG_GETARG_BYTEA_PP(2);
 
693
 
 
694
        res = encrypt_internal(1, 1, data, key, arg);
 
695
 
 
696
        PG_FREE_IF_COPY(data, 0);
 
697
        PG_FREE_IF_COPY(key, 1);
 
698
        if (PG_NARGS() > 2)
 
699
                PG_FREE_IF_COPY(arg, 2);
 
700
        PG_RETURN_TEXT_P(res);
 
701
}
 
702
 
 
703
 
 
704
Datum
 
705
pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
 
706
{
 
707
        bytea      *data,
 
708
                           *key;
 
709
        text       *psw = NULL,
 
710
                           *arg = NULL;
 
711
        text       *res;
 
712
 
 
713
        data = PG_GETARG_BYTEA_PP(0);
 
714
        key = PG_GETARG_BYTEA_PP(1);
 
715
        if (PG_NARGS() > 2)
 
716
                psw = PG_GETARG_BYTEA_PP(2);
 
717
        if (PG_NARGS() > 3)
 
718
                arg = PG_GETARG_BYTEA_PP(3);
 
719
 
 
720
        res = decrypt_internal(1, 0, data, key, psw, arg);
 
721
 
 
722
        PG_FREE_IF_COPY(data, 0);
 
723
        PG_FREE_IF_COPY(key, 1);
 
724
        if (PG_NARGS() > 2)
 
725
                PG_FREE_IF_COPY(psw, 2);
 
726
        if (PG_NARGS() > 3)
 
727
                PG_FREE_IF_COPY(arg, 3);
 
728
        PG_RETURN_TEXT_P(res);
 
729
}
 
730
 
 
731
Datum
 
732
pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
 
733
{
 
734
        bytea      *data,
 
735
                           *key;
 
736
        text       *psw = NULL,
 
737
                           *arg = NULL;
 
738
        text       *res;
 
739
 
 
740
        data = PG_GETARG_BYTEA_PP(0);
 
741
        key = PG_GETARG_BYTEA_PP(1);
 
742
        if (PG_NARGS() > 2)
 
743
                psw = PG_GETARG_BYTEA_PP(2);
 
744
        if (PG_NARGS() > 3)
 
745
                arg = PG_GETARG_BYTEA_PP(3);
 
746
 
 
747
        res = decrypt_internal(1, 1, data, key, psw, arg);
 
748
 
 
749
        PG_FREE_IF_COPY(data, 0);
 
750
        PG_FREE_IF_COPY(key, 1);
 
751
        if (PG_NARGS() > 2)
 
752
                PG_FREE_IF_COPY(psw, 2);
 
753
        if (PG_NARGS() > 3)
 
754
                PG_FREE_IF_COPY(arg, 3);
 
755
        PG_RETURN_TEXT_P(res);
 
756
}
 
757
 
 
758
 
 
759
/*
 
760
 * Wrappers for PGP ascii armor
 
761
 */
 
762
 
 
763
/*
 
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.
 
766
 */
 
767
static int
 
768
parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
 
769
                                           char ***p_keys, char ***p_values)
 
770
{
 
771
        int                     nkdims = ARR_NDIM(key_array);
 
772
        int                     nvdims = ARR_NDIM(val_array);
 
773
        char      **keys,
 
774
                          **values;
 
775
        Datum      *key_datums,
 
776
                           *val_datums;
 
777
        bool       *key_nulls,
 
778
                           *val_nulls;
 
779
        int                     key_count,
 
780
                                val_count;
 
781
        int                     i;
 
782
 
 
783
        if (nkdims > 1 || nkdims != nvdims)
 
784
                ereport(ERROR,
 
785
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 
786
                                 errmsg("wrong number of array subscripts")));
 
787
        if (nkdims == 0)
 
788
                return 0;
 
789
 
 
790
        deconstruct_array(key_array,
 
791
                                          TEXTOID, -1, false, 'i',
 
792
                                          &key_datums, &key_nulls, &key_count);
 
793
 
 
794
        deconstruct_array(val_array,
 
795
                                          TEXTOID, -1, false, 'i',
 
796
                                          &val_datums, &val_nulls, &val_count);
 
797
 
 
798
        if (key_count != val_count)
 
799
                ereport(ERROR,
 
800
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 
801
                                 errmsg("mismatched array dimensions")));
 
802
 
 
803
        keys = (char **) palloc(sizeof(char *) * key_count);
 
804
        values = (char **) palloc(sizeof(char *) * val_count);
 
805
 
 
806
        for (i = 0; i < key_count; i++)
 
807
        {
 
808
                char       *v;
 
809
 
 
810
                /* Check that the key doesn't contain anything funny */
 
811
                if (key_nulls[i])
 
812
                        ereport(ERROR,
 
813
                                        (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 
814
                                         errmsg("null value not allowed for header key")));
 
815
 
 
816
                v = TextDatumGetCString(key_datums[i]);
 
817
 
 
818
                if (!string_is_ascii(v))
 
819
                        ereport(ERROR,
 
820
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
821
                                         errmsg("header key must not contain non-ASCII characters")));
 
822
                if (strstr(v, ": "))
 
823
                        ereport(ERROR,
 
824
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
825
                                         errmsg("header key must not contain \": \"")));
 
826
                if (strchr(v, '\n'))
 
827
                        ereport(ERROR,
 
828
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
829
                                         errmsg("header key must not contain newlines")));
 
830
                keys[i] = v;
 
831
 
 
832
                /* And the same for the value */
 
833
                if (val_nulls[i])
 
834
                        ereport(ERROR,
 
835
                                        (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 
836
                                         errmsg("null value not allowed for header value")));
 
837
 
 
838
                v = TextDatumGetCString(val_datums[i]);
 
839
 
 
840
                if (!string_is_ascii(v))
 
841
                        ereport(ERROR,
 
842
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
843
                                         errmsg("header value must not contain non-ASCII characters")));
 
844
                if (strchr(v, '\n'))
 
845
                        ereport(ERROR,
 
846
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
847
                                         errmsg("header value must not contain newlines")));
 
848
 
 
849
                values[i] = v;
 
850
        }
 
851
 
 
852
        *p_keys = keys;
 
853
        *p_values = values;
 
854
        return key_count;
 
855
}
 
856
 
 
857
Datum
 
858
pg_armor(PG_FUNCTION_ARGS)
 
859
{
 
860
        bytea      *data;
 
861
        text       *res;
 
862
        int                     data_len;
 
863
        StringInfoData buf;
 
864
        int                     num_headers;
 
865
        char      **keys = NULL,
 
866
                          **values = NULL;
 
867
 
 
868
        data = PG_GETARG_BYTEA_PP(0);
 
869
        data_len = VARSIZE_ANY_EXHDR(data);
 
870
        if (PG_NARGS() == 3)
 
871
        {
 
872
                num_headers = parse_key_value_arrays(PG_GETARG_ARRAYTYPE_P(1),
 
873
                                                                                         PG_GETARG_ARRAYTYPE_P(2),
 
874
                                                                                         &keys, &values);
 
875
        }
 
876
        else if (PG_NARGS() == 1)
 
877
                num_headers = 0;
 
878
        else
 
879
                elog(ERROR, "unexpected number of arguments %d", PG_NARGS());
 
880
 
 
881
        initStringInfo(&buf);
 
882
 
 
883
        pgp_armor_encode((uint8 *) VARDATA_ANY(data), data_len, &buf,
 
884
                                         num_headers, keys, values);
 
885
 
 
886
        res = palloc(VARHDRSZ + buf.len);
 
887
        SET_VARSIZE(res, VARHDRSZ + buf.len);
 
888
        memcpy(VARDATA(res), buf.data, buf.len);
 
889
        pfree(buf.data);
 
890
 
 
891
        PG_FREE_IF_COPY(data, 0);
 
892
        PG_RETURN_TEXT_P(res);
 
893
}
 
894
 
 
895
Datum
 
896
pg_dearmor(PG_FUNCTION_ARGS)
 
897
{
 
898
        text       *data;
 
899
        bytea      *res;
 
900
        int                     data_len;
 
901
        int                     ret;
 
902
        StringInfoData buf;
 
903
 
 
904
        data = PG_GETARG_TEXT_PP(0);
 
905
        data_len = VARSIZE_ANY_EXHDR(data);
 
906
 
 
907
        initStringInfo(&buf);
 
908
 
 
909
        ret = pgp_armor_decode((uint8 *) VARDATA_ANY(data), data_len, &buf);
 
910
        if (ret < 0)
 
911
                px_THROW_ERROR(ret);
 
912
        res = palloc(VARHDRSZ + buf.len);
 
913
        SET_VARSIZE(res, VARHDRSZ + buf.len);
 
914
        memcpy(VARDATA(res), buf.data, buf.len);
 
915
        pfree(buf.data);
 
916
 
 
917
        PG_FREE_IF_COPY(data, 0);
 
918
        PG_RETURN_TEXT_P(res);
 
919
}
 
920
 
 
921
/* cross-call state for pgp_armor_headers */
 
922
typedef struct
 
923
{
 
924
        int                     nheaders;
 
925
        char      **keys;
 
926
        char      **values;
 
927
} pgp_armor_headers_state;
 
928
 
 
929
Datum
 
930
pgp_armor_headers(PG_FUNCTION_ARGS)
 
931
{
 
932
        FuncCallContext *funcctx;
 
933
        pgp_armor_headers_state *state;
 
934
        char       *utf8key;
 
935
        char       *utf8val;
 
936
        HeapTuple       tuple;
 
937
        TupleDesc       tupdesc;
 
938
        AttInMetadata *attinmeta;
 
939
 
 
940
        if (SRF_IS_FIRSTCALL())
 
941
        {
 
942
                text       *data = PG_GETARG_TEXT_PP(0);
 
943
                int                     res;
 
944
                MemoryContext oldcontext;
 
945
 
 
946
                funcctx = SRF_FIRSTCALL_INIT();
 
947
 
 
948
                /* we need the state allocated in the multi call context */
 
949
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
950
 
 
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");
 
954
 
 
955
                attinmeta = TupleDescGetAttInMetadata(tupdesc);
 
956
                funcctx->attinmeta = attinmeta;
 
957
 
 
958
                state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state));
 
959
 
 
960
                res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data),
 
961
                                                                                VARSIZE_ANY_EXHDR(data),
 
962
                                                                                &state->nheaders, &state->keys,
 
963
                                                                                &state->values);
 
964
                if (res < 0)
 
965
                        px_THROW_ERROR(res);
 
966
 
 
967
                MemoryContextSwitchTo(oldcontext);
 
968
                funcctx->user_fctx = state;
 
969
        }
 
970
 
 
971
        funcctx = SRF_PERCALL_SETUP();
 
972
        state = (pgp_armor_headers_state *) funcctx->user_fctx;
 
973
 
 
974
        if (funcctx->call_cntr >= state->nheaders)
 
975
                SRF_RETURN_DONE(funcctx);
 
976
        else
 
977
        {
 
978
                char       *values[2];
 
979
 
 
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];
 
983
 
 
984
                values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8);
 
985
                values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8);
 
986
 
 
987
                /* build a tuple */
 
988
                tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
 
989
                SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
 
990
        }
 
991
}
 
992
 
 
993
 
 
994
 
 
995
/*
 
996
 * Wrappers for PGP key id
 
997
 */
 
998
 
 
999
Datum
 
1000
pgp_key_id_w(PG_FUNCTION_ARGS)
 
1001
{
 
1002
        bytea      *data;
 
1003
        text       *res;
 
1004
        int                     res_len;
 
1005
        MBuf       *buf;
 
1006
 
 
1007
        data = PG_GETARG_BYTEA_PP(0);
 
1008
        buf = create_mbuf_from_vardata(data);
 
1009
        res = palloc(VARHDRSZ + 17);
 
1010
 
 
1011
        res_len = pgp_get_keyid(buf, VARDATA(res));
 
1012
        mbuf_free(buf);
 
1013
        if (res_len < 0)
 
1014
                px_THROW_ERROR(res_len);
 
1015
        SET_VARSIZE(res, VARHDRSZ + res_len);
 
1016
 
 
1017
        PG_FREE_IF_COPY(data, 0);
 
1018
        PG_RETURN_TEXT_P(res);
 
1019
}