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