OSDN Git Service

ba1d17efd98bd2441ebe028312eab51c1a3ecb39
[pg-rex/syncrep.git] / contrib / pgcrypto / internal.c
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  * $Id: internal.c,v 1.7 2001/10/28 06:25:41 momjian 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 uint
81 int_md5_len(PX_MD * h)
82 {
83         return MD5_DIGEST_LENGTH;
84 }
85
86 static uint
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, uint 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 uint
128 int_sha1_len(PX_MD * h)
129 {
130         return SHA1_DIGEST_LENGTH;
131 }
132
133 static uint
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, uint 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         uint            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 uint
254 rj_block_size(PX_Cipher * c)
255 {
256         return 128 / 8;
257 }
258
259 static uint
260 rj_key_size(PX_Cipher * c)
261 {
262         return 256 / 8;
263 }
264
265 static uint
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, uint 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, uint 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) || (((unsigned) res) & 3))
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, uint 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) || (((unsigned) res) & 3))
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 uint
392 bf_block_size(PX_Cipher * c)
393 {
394         return 8;
395 }
396
397 static uint
398 bf_key_size(PX_Cipher * c)
399 {
400         return BLF_MAXKEYLEN;
401 }
402
403 static uint
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, uint 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, uint 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) || (((unsigned) res) & 3))
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, uint 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) || (((unsigned) res) & 3))
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()
497 {
498         return rj_load(MODE_ECB);
499 }
500
501 static PX_Cipher *
502 rj_128_cbc()
503 {
504         return rj_load(MODE_CBC);
505 }
506
507 static PX_Cipher *
508 bf_ecb_load()
509 {
510         return bf_load(MODE_ECB);
511 }
512
513 static PX_Cipher *
514 bf_cbc_load()
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 (!strcasecmp(p->name, name))
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 }