~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/pgcrypto/internal.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * internal.c
 
3
 *              Wrapper for builtin functions
 
4
 *
 
5
 * Copyright (c) 2001 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
 * $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.14 2004-10-25 02:15:02 tgl Exp $
 
30
 */
 
31
 
 
32
 
 
33
#include <postgres.h>
 
34
 
 
35
#include "px.h"
 
36
 
 
37
#include "md5.h"
 
38
#include "sha1.h"
 
39
#include "blf.h"
 
40
#include "rijndael.h"
 
41
 
 
42
#ifndef MD5_DIGEST_LENGTH
 
43
#define MD5_DIGEST_LENGTH 16
 
44
#endif
 
45
 
 
46
#ifndef SHA1_DIGEST_LENGTH
 
47
#ifdef SHA1_RESULTLEN
 
48
#define SHA1_DIGEST_LENGTH SHA1_RESULTLEN
 
49
#else
 
50
#define SHA1_DIGEST_LENGTH 20
 
51
#endif
 
52
#endif
 
53
 
 
54
#define SHA1_BLOCK_SIZE 64
 
55
#define MD5_BLOCK_SIZE 64
 
56
 
 
57
static void init_md5(PX_MD * h);
 
58
static void init_sha1(PX_MD * h);
 
59
 
 
60
static struct int_digest
 
61
{
 
62
        char       *name;
 
63
        void            (*init) (PX_MD * h);
 
64
}       int_digest_list[] =
 
65
 
 
66
{
 
67
        {
 
68
                "md5", init_md5
 
69
        },
 
70
        {
 
71
                "sha1", init_sha1
 
72
        },
 
73
        {
 
74
                NULL, NULL
 
75
        }
 
76
};
 
77
 
 
78
/* MD5 */
 
79
 
 
80
static unsigned
 
81
int_md5_len(PX_MD * h)
 
82
{
 
83
        return MD5_DIGEST_LENGTH;
 
84
}
 
85
 
 
86
static unsigned
 
87
int_md5_block_len(PX_MD * h)
 
88
{
 
89
        return MD5_BLOCK_SIZE;
 
90
}
 
91
 
 
92
static void
 
93
int_md5_update(PX_MD * h, const uint8 *data, unsigned dlen)
 
94
{
 
95
        MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
 
96
 
 
97
        MD5Update(ctx, data, dlen);
 
98
}
 
99
 
 
100
static void
 
101
int_md5_reset(PX_MD * h)
 
102
{
 
103
        MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
 
104
 
 
105
        MD5Init(ctx);
 
106
}
 
107
 
 
108
static void
 
109
int_md5_finish(PX_MD * h, uint8 *dst)
 
110
{
 
111
        MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
 
112
 
 
113
        MD5Final(dst, ctx);
 
114
}
 
115
 
 
116
static void
 
117
int_md5_free(PX_MD * h)
 
118
{
 
119
        MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
 
120
 
 
121
        px_free(ctx);
 
122
        px_free(h);
 
123
}
 
124
 
 
125
/* SHA1 */
 
126
 
 
127
static unsigned
 
128
int_sha1_len(PX_MD * h)
 
129
{
 
130
        return SHA1_DIGEST_LENGTH;
 
131
}
 
132
 
 
133
static unsigned
 
134
int_sha1_block_len(PX_MD * h)
 
135
{
 
136
        return SHA1_BLOCK_SIZE;
 
137
}
 
138
 
 
139
static void
 
140
int_sha1_update(PX_MD * h, const uint8 *data, unsigned dlen)
 
141
{
 
142
        SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
 
143
 
 
144
        SHA1Update(ctx, data, dlen);
 
145
}
 
146
 
 
147
static void
 
148
int_sha1_reset(PX_MD * h)
 
149
{
 
150
        SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
 
151
 
 
152
        SHA1Init(ctx);
 
153
}
 
154
 
 
155
static void
 
156
int_sha1_finish(PX_MD * h, uint8 *dst)
 
157
{
 
158
        SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
 
159
 
 
160
        SHA1Final(dst, ctx);
 
161
}
 
162
 
 
163
static void
 
164
int_sha1_free(PX_MD * h)
 
165
{
 
166
        SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
 
167
 
 
168
        px_free(ctx);
 
169
        px_free(h);
 
170
}
 
171
 
 
172
/* init functions */
 
173
 
 
174
static void
 
175
init_md5(PX_MD * md)
 
176
{
 
177
        MD5_CTX    *ctx;
 
178
 
 
179
        ctx = px_alloc(sizeof(*ctx));
 
180
 
 
181
        md->p.ptr = ctx;
 
182
 
 
183
        md->result_size = int_md5_len;
 
184
        md->block_size = int_md5_block_len;
 
185
        md->reset = int_md5_reset;
 
186
        md->update = int_md5_update;
 
187
        md->finish = int_md5_finish;
 
188
        md->free = int_md5_free;
 
189
 
 
190
        md->reset(md);
 
191
}
 
192
 
 
193
static void
 
194
init_sha1(PX_MD * md)
 
195
{
 
196
        SHA1_CTX   *ctx;
 
197
 
 
198
        ctx = px_alloc(sizeof(*ctx));
 
199
 
 
200
        md->p.ptr = ctx;
 
201
 
 
202
        md->result_size = int_sha1_len;
 
203
        md->block_size = int_sha1_block_len;
 
204
        md->reset = int_sha1_reset;
 
205
        md->update = int_sha1_update;
 
206
        md->finish = int_sha1_finish;
 
207
        md->free = int_sha1_free;
 
208
 
 
209
        md->reset(md);
 
210
}
 
211
 
 
212
/*
 
213
 * ciphers generally
 
214
 */
 
215
 
 
216
#define INT_MAX_KEY             (512/8)
 
217
#define INT_MAX_IV              (128/8)
 
218
 
 
219
struct int_ctx
 
220
{
 
221
        uint8           keybuf[INT_MAX_KEY];
 
222
        uint8           iv[INT_MAX_IV];
 
223
        union
 
224
        {
 
225
                blf_ctx         bf;
 
226
                rijndael_ctx rj;
 
227
        }                       ctx;
 
228
        unsigned        keylen;
 
229
        int                     is_init;
 
230
        int                     mode;
 
231
};
 
232
 
 
233
static void
 
234
intctx_free(PX_Cipher * c)
 
235
{
 
236
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
237
 
 
238
        if (cx)
 
239
        {
 
240
                memset(cx, 0, sizeof *cx);
 
241
                px_free(cx);
 
242
        }
 
243
        px_free(c);
 
244
}
 
245
 
 
246
/*
 
247
 * AES/rijndael
 
248
 */
 
249
 
 
250
#define MODE_ECB 0
 
251
#define MODE_CBC 1
 
252
 
 
253
static unsigned
 
254
rj_block_size(PX_Cipher * c)
 
255
{
 
256
        return 128 / 8;
 
257
}
 
258
 
 
259
static unsigned
 
260
rj_key_size(PX_Cipher * c)
 
261
{
 
262
        return 256 / 8;
 
263
}
 
264
 
 
265
static unsigned
 
266
rj_iv_size(PX_Cipher * c)
 
267
{
 
268
        return 128 / 8;
 
269
}
 
270
 
 
271
static int
 
272
rj_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
 
273
{
 
274
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
275
 
 
276
        if (klen <= 128 / 8)
 
277
                cx->keylen = 128 / 8;
 
278
        else if (klen <= 192 / 8)
 
279
                cx->keylen = 192 / 8;
 
280
        else if (klen <= 256 / 8)
 
281
                cx->keylen = 256 / 8;
 
282
        else
 
283
                return -1;
 
284
 
 
285
        memcpy(&cx->keybuf, key, klen);
 
286
 
 
287
        if (iv)
 
288
                memcpy(cx->iv, iv, 128 / 8);
 
289
 
 
290
        return 0;
 
291
}
 
292
 
 
293
static int
 
294
rj_real_init(struct int_ctx * cx, int dir)
 
295
{
 
296
        aes_set_key(&cx->ctx.rj, cx->keybuf, cx->keylen * 8, dir);
 
297
        return 0;
 
298
}
 
299
 
 
300
static int
 
301
rj_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
302
{
 
303
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
304
 
 
305
        if (!cx->is_init)
 
306
        {
 
307
                if (rj_real_init(cx, 1))
 
308
                        return -1;
 
309
        }
 
310
 
 
311
        if (dlen == 0)
 
312
                return 0;
 
313
 
 
314
        if (dlen & 15)
 
315
                return -1;
 
316
 
 
317
        memcpy(res, data, dlen);
 
318
 
 
319
        if (cx->mode == MODE_CBC)
 
320
        {
 
321
                aes_cbc_encrypt(&cx->ctx.rj, cx->iv, res, dlen);
 
322
                memcpy(cx->iv, res + dlen - 16, 16);
 
323
        }
 
324
        else
 
325
                aes_ecb_encrypt(&cx->ctx.rj, res, dlen);
 
326
 
 
327
        return 0;
 
328
}
 
329
 
 
330
static int
 
331
rj_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
332
{
 
333
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
334
 
 
335
        if (!cx->is_init)
 
336
                if (rj_real_init(cx, 0))
 
337
                        return -1;
 
338
 
 
339
        if (dlen == 0)
 
340
                return 0;
 
341
 
 
342
        if (dlen & 15)
 
343
                return -1;
 
344
 
 
345
        memcpy(res, data, dlen);
 
346
 
 
347
        if (cx->mode == MODE_CBC)
 
348
        {
 
349
                aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen);
 
350
                memcpy(cx->iv, data + dlen - 16, 16);
 
351
        }
 
352
        else
 
353
                aes_ecb_decrypt(&cx->ctx.rj, res, dlen);
 
354
 
 
355
        return 0;
 
356
}
 
357
 
 
358
/*
 
359
 * initializers
 
360
 */
 
361
 
 
362
static PX_Cipher *
 
363
rj_load(int mode)
 
364
{
 
365
        PX_Cipher  *c;
 
366
        struct int_ctx *cx;
 
367
 
 
368
        c = px_alloc(sizeof *c);
 
369
        memset(c, 0, sizeof *c);
 
370
 
 
371
        c->block_size = rj_block_size;
 
372
        c->key_size = rj_key_size;
 
373
        c->iv_size = rj_iv_size;
 
374
        c->init = rj_init;
 
375
        c->encrypt = rj_encrypt;
 
376
        c->decrypt = rj_decrypt;
 
377
        c->free = intctx_free;
 
378
 
 
379
        cx = px_alloc(sizeof *cx);
 
380
        memset(cx, 0, sizeof *cx);
 
381
        cx->mode = mode;
 
382
 
 
383
        c->ptr = cx;
 
384
        return c;
 
385
}
 
386
 
 
387
/*
 
388
 * blowfish
 
389
 */
 
390
 
 
391
static unsigned
 
392
bf_block_size(PX_Cipher * c)
 
393
{
 
394
        return 8;
 
395
}
 
396
 
 
397
static unsigned
 
398
bf_key_size(PX_Cipher * c)
 
399
{
 
400
        return BLF_MAXKEYLEN;
 
401
}
 
402
 
 
403
static unsigned
 
404
bf_iv_size(PX_Cipher * c)
 
405
{
 
406
        return 8;
 
407
}
 
408
 
 
409
static int
 
410
bf_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
 
411
{
 
412
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
413
 
 
414
        blf_key(&cx->ctx.bf, key, klen);
 
415
        if (iv)
 
416
                memcpy(cx->iv, iv, 8);
 
417
 
 
418
        return 0;
 
419
}
 
420
 
 
421
static int
 
422
bf_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
423
{
 
424
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
425
 
 
426
        if (dlen == 0)
 
427
                return 0;
 
428
 
 
429
        if (dlen & 7)
 
430
                return -1;
 
431
 
 
432
        memcpy(res, data, dlen);
 
433
        switch (cx->mode)
 
434
        {
 
435
                case MODE_ECB:
 
436
                        blf_ecb_encrypt(&cx->ctx.bf, res, dlen);
 
437
                        break;
 
438
                case MODE_CBC:
 
439
                        blf_cbc_encrypt(&cx->ctx.bf, cx->iv, res, dlen);
 
440
                        memcpy(cx->iv, res + dlen - 8, 8);
 
441
        }
 
442
        return 0;
 
443
}
 
444
 
 
445
static int
 
446
bf_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
447
{
 
448
        struct int_ctx *cx = (struct int_ctx *) c->ptr;
 
449
 
 
450
        if (dlen == 0)
 
451
                return 0;
 
452
 
 
453
        if (dlen & 7)
 
454
                return -1;
 
455
 
 
456
        memcpy(res, data, dlen);
 
457
        switch (cx->mode)
 
458
        {
 
459
                case MODE_ECB:
 
460
                        blf_ecb_decrypt(&cx->ctx.bf, res, dlen);
 
461
                        break;
 
462
                case MODE_CBC:
 
463
                        blf_cbc_decrypt(&cx->ctx.bf, cx->iv, res, dlen);
 
464
                        memcpy(cx->iv, data + dlen - 8, 8);
 
465
        }
 
466
        return 0;
 
467
}
 
468
 
 
469
static PX_Cipher *
 
470
bf_load(int mode)
 
471
{
 
472
        PX_Cipher  *c;
 
473
        struct int_ctx *cx;
 
474
 
 
475
        c = px_alloc(sizeof *c);
 
476
        memset(c, 0, sizeof *c);
 
477
 
 
478
        c->block_size = bf_block_size;
 
479
        c->key_size = bf_key_size;
 
480
        c->iv_size = bf_iv_size;
 
481
        c->init = bf_init;
 
482
        c->encrypt = bf_encrypt;
 
483
        c->decrypt = bf_decrypt;
 
484
        c->free = intctx_free;
 
485
 
 
486
        cx = px_alloc(sizeof *cx);
 
487
        memset(cx, 0, sizeof *cx);
 
488
        cx->mode = mode;
 
489
        c->ptr = cx;
 
490
        return c;
 
491
}
 
492
 
 
493
/* ciphers */
 
494
 
 
495
static PX_Cipher *
 
496
rj_128_ecb(void)
 
497
{
 
498
        return rj_load(MODE_ECB);
 
499
}
 
500
 
 
501
static PX_Cipher *
 
502
rj_128_cbc(void)
 
503
{
 
504
        return rj_load(MODE_CBC);
 
505
}
 
506
 
 
507
static PX_Cipher *
 
508
bf_ecb_load(void)
 
509
{
 
510
        return bf_load(MODE_ECB);
 
511
}
 
512
 
 
513
static PX_Cipher *
 
514
bf_cbc_load(void)
 
515
{
 
516
        return bf_load(MODE_CBC);
 
517
}
 
518
 
 
519
static struct
 
520
{
 
521
        char       *name;
 
522
        PX_Cipher  *(*load) (void);
 
523
}       int_ciphers[] =
 
524
 
 
525
{
 
526
        {
 
527
                "bf-cbc", bf_cbc_load
 
528
        },
 
529
        {
 
530
                "bf-ecb", bf_ecb_load
 
531
        },
 
532
        {
 
533
                "aes-128-cbc", rj_128_cbc
 
534
        },
 
535
        {
 
536
                "aes-128-ecb", rj_128_ecb
 
537
        },
 
538
        {
 
539
                NULL, NULL
 
540
        }
 
541
};
 
542
 
 
543
static PX_Alias int_aliases[] = {
 
544
        {"bf", "bf-cbc"},
 
545
        {"blowfish", "bf-cbc"},
 
546
        {"aes", "aes-128-cbc"},
 
547
        {"aes-ecb", "aes-128-ecb"},
 
548
        {"aes-cbc", "aes-128-cbc"},
 
549
        {"aes-128", "aes-128-cbc"},
 
550
        {"rijndael", "aes-128-cbc"},
 
551
        {"rijndael-128", "aes-128-cbc"},
 
552
        {NULL, NULL}
 
553
};
 
554
 
 
555
/* PUBLIC FUNCTIONS */
 
556
 
 
557
int
 
558
px_find_digest(const char *name, PX_MD ** res)
 
559
{
 
560
        struct int_digest *p;
 
561
        PX_MD      *h;
 
562
 
 
563
        for (p = int_digest_list; p->name; p++)
 
564
                if (pg_strcasecmp(p->name, name) == 0)
 
565
                {
 
566
                        h = px_alloc(sizeof(*h));
 
567
                        p->init(h);
 
568
 
 
569
                        *res = h;
 
570
 
 
571
                        return 0;
 
572
                }
 
573
        return -1;
 
574
}
 
575
 
 
576
int
 
577
px_find_cipher(const char *name, PX_Cipher ** res)
 
578
{
 
579
        int                     i;
 
580
        PX_Cipher  *c = NULL;
 
581
 
 
582
        name = px_resolve_alias(int_aliases, name);
 
583
 
 
584
        for (i = 0; int_ciphers[i].name; i++)
 
585
                if (!strcmp(int_ciphers[i].name, name))
 
586
                {
 
587
                        c = int_ciphers[i].load();
 
588
                        break;
 
589
                }
 
590
 
 
591
        if (c == NULL)
 
592
                return -1;
 
593
 
 
594
        *res = c;
 
595
        return 0;
 
596
}