Header And Logo

PostgreSQL
| The world's most advanced open source database.

internal.c

Go to the documentation of this file.
00001 /*
00002  * internal.c
00003  *      Wrapper for builtin functions
00004  *
00005  * Copyright (c) 2001 Marko Kreen
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * contrib/pgcrypto/internal.c
00030  */
00031 
00032 #include "postgres.h"
00033 
00034 #include <time.h>
00035 
00036 #include "px.h"
00037 #include "md5.h"
00038 #include "sha1.h"
00039 #include "blf.h"
00040 #include "rijndael.h"
00041 #include "fortuna.h"
00042 
00043 /*
00044  * System reseeds should be separated at least this much.
00045  */
00046 #define SYSTEM_RESEED_MIN           (20*60)     /* 20 min */
00047 /*
00048  * How often to roll dice.
00049  */
00050 #define SYSTEM_RESEED_CHECK_TIME    (10*60)     /* 10 min */
00051 /*
00052  * The chance is x/256 that the reseed happens.
00053  */
00054 #define SYSTEM_RESEED_CHANCE        (4) /* 256/4 * 10min ~ 10h */
00055 
00056 /*
00057  * If this much time has passed, force reseed.
00058  */
00059 #define SYSTEM_RESEED_MAX           (12*60*60)  /* 12h */
00060 
00061 
00062 #ifndef MD5_DIGEST_LENGTH
00063 #define MD5_DIGEST_LENGTH 16
00064 #endif
00065 
00066 #ifndef SHA1_DIGEST_LENGTH
00067 #ifdef SHA1_RESULTLEN
00068 #define SHA1_DIGEST_LENGTH SHA1_RESULTLEN
00069 #else
00070 #define SHA1_DIGEST_LENGTH 20
00071 #endif
00072 #endif
00073 
00074 #define SHA1_BLOCK_SIZE 64
00075 #define MD5_BLOCK_SIZE 64
00076 
00077 static void init_md5(PX_MD *h);
00078 static void init_sha1(PX_MD *h);
00079 
00080 void        init_sha224(PX_MD *h);
00081 void        init_sha256(PX_MD *h);
00082 void        init_sha384(PX_MD *h);
00083 void        init_sha512(PX_MD *h);
00084 
00085 struct int_digest
00086 {
00087     char       *name;
00088     void        (*init) (PX_MD *h);
00089 };
00090 
00091 static const struct int_digest
00092             int_digest_list[] = {
00093     {"md5", init_md5},
00094     {"sha1", init_sha1},
00095     {"sha224", init_sha224},
00096     {"sha256", init_sha256},
00097     {"sha384", init_sha384},
00098     {"sha512", init_sha512},
00099     {NULL, NULL}
00100 };
00101 
00102 /* MD5 */
00103 
00104 static unsigned
00105 int_md5_len(PX_MD *h)
00106 {
00107     return MD5_DIGEST_LENGTH;
00108 }
00109 
00110 static unsigned
00111 int_md5_block_len(PX_MD *h)
00112 {
00113     return MD5_BLOCK_SIZE;
00114 }
00115 
00116 static void
00117 int_md5_update(PX_MD *h, const uint8 *data, unsigned dlen)
00118 {
00119     MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
00120 
00121     MD5Update(ctx, data, dlen);
00122 }
00123 
00124 static void
00125 int_md5_reset(PX_MD *h)
00126 {
00127     MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
00128 
00129     MD5Init(ctx);
00130 }
00131 
00132 static void
00133 int_md5_finish(PX_MD *h, uint8 *dst)
00134 {
00135     MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
00136 
00137     MD5Final(dst, ctx);
00138 }
00139 
00140 static void
00141 int_md5_free(PX_MD *h)
00142 {
00143     MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
00144 
00145     memset(ctx, 0, sizeof(*ctx));
00146     px_free(ctx);
00147     px_free(h);
00148 }
00149 
00150 /* SHA1 */
00151 
00152 static unsigned
00153 int_sha1_len(PX_MD *h)
00154 {
00155     return SHA1_DIGEST_LENGTH;
00156 }
00157 
00158 static unsigned
00159 int_sha1_block_len(PX_MD *h)
00160 {
00161     return SHA1_BLOCK_SIZE;
00162 }
00163 
00164 static void
00165 int_sha1_update(PX_MD *h, const uint8 *data, unsigned dlen)
00166 {
00167     SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
00168 
00169     SHA1Update(ctx, data, dlen);
00170 }
00171 
00172 static void
00173 int_sha1_reset(PX_MD *h)
00174 {
00175     SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
00176 
00177     SHA1Init(ctx);
00178 }
00179 
00180 static void
00181 int_sha1_finish(PX_MD *h, uint8 *dst)
00182 {
00183     SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
00184 
00185     SHA1Final(dst, ctx);
00186 }
00187 
00188 static void
00189 int_sha1_free(PX_MD *h)
00190 {
00191     SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
00192 
00193     memset(ctx, 0, sizeof(*ctx));
00194     px_free(ctx);
00195     px_free(h);
00196 }
00197 
00198 /* init functions */
00199 
00200 static void
00201 init_md5(PX_MD *md)
00202 {
00203     MD5_CTX    *ctx;
00204 
00205     ctx = px_alloc(sizeof(*ctx));
00206     memset(ctx, 0, sizeof(*ctx));
00207 
00208     md->p.ptr = ctx;
00209 
00210     md->result_size = int_md5_len;
00211     md->block_size = int_md5_block_len;
00212     md->reset = int_md5_reset;
00213     md->update = int_md5_update;
00214     md->finish = int_md5_finish;
00215     md->free = int_md5_free;
00216 
00217     md->reset(md);
00218 }
00219 
00220 static void
00221 init_sha1(PX_MD *md)
00222 {
00223     SHA1_CTX   *ctx;
00224 
00225     ctx = px_alloc(sizeof(*ctx));
00226     memset(ctx, 0, sizeof(*ctx));
00227 
00228     md->p.ptr = ctx;
00229 
00230     md->result_size = int_sha1_len;
00231     md->block_size = int_sha1_block_len;
00232     md->reset = int_sha1_reset;
00233     md->update = int_sha1_update;
00234     md->finish = int_sha1_finish;
00235     md->free = int_sha1_free;
00236 
00237     md->reset(md);
00238 }
00239 
00240 /*
00241  * ciphers generally
00242  */
00243 
00244 #define INT_MAX_KEY     (512/8)
00245 #define INT_MAX_IV      (128/8)
00246 
00247 struct int_ctx
00248 {
00249     uint8       keybuf[INT_MAX_KEY];
00250     uint8       iv[INT_MAX_IV];
00251     union
00252     {
00253         BlowfishContext bf;
00254         rijndael_ctx rj;
00255     }           ctx;
00256     unsigned    keylen;
00257     int         is_init;
00258     int         mode;
00259 };
00260 
00261 static void
00262 intctx_free(PX_Cipher *c)
00263 {
00264     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00265 
00266     if (cx)
00267     {
00268         memset(cx, 0, sizeof *cx);
00269         px_free(cx);
00270     }
00271     px_free(c);
00272 }
00273 
00274 /*
00275  * AES/rijndael
00276  */
00277 
00278 #define MODE_ECB 0
00279 #define MODE_CBC 1
00280 
00281 static unsigned
00282 rj_block_size(PX_Cipher *c)
00283 {
00284     return 128 / 8;
00285 }
00286 
00287 static unsigned
00288 rj_key_size(PX_Cipher *c)
00289 {
00290     return 256 / 8;
00291 }
00292 
00293 static unsigned
00294 rj_iv_size(PX_Cipher *c)
00295 {
00296     return 128 / 8;
00297 }
00298 
00299 static int
00300 rj_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00301 {
00302     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00303 
00304     if (klen <= 128 / 8)
00305         cx->keylen = 128 / 8;
00306     else if (klen <= 192 / 8)
00307         cx->keylen = 192 / 8;
00308     else if (klen <= 256 / 8)
00309         cx->keylen = 256 / 8;
00310     else
00311         return PXE_KEY_TOO_BIG;
00312 
00313     memcpy(&cx->keybuf, key, klen);
00314 
00315     if (iv)
00316         memcpy(cx->iv, iv, 128 / 8);
00317 
00318     return 0;
00319 }
00320 
00321 static int
00322 rj_real_init(struct int_ctx * cx, int dir)
00323 {
00324     aes_set_key(&cx->ctx.rj, cx->keybuf, cx->keylen * 8, dir);
00325     return 0;
00326 }
00327 
00328 static int
00329 rj_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00330 {
00331     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00332 
00333     if (!cx->is_init)
00334     {
00335         if (rj_real_init(cx, 1))
00336             return PXE_CIPHER_INIT;
00337     }
00338 
00339     if (dlen == 0)
00340         return 0;
00341 
00342     if (dlen & 15)
00343         return PXE_NOTBLOCKSIZE;
00344 
00345     memcpy(res, data, dlen);
00346 
00347     if (cx->mode == MODE_CBC)
00348     {
00349         aes_cbc_encrypt(&cx->ctx.rj, cx->iv, res, dlen);
00350         memcpy(cx->iv, res + dlen - 16, 16);
00351     }
00352     else
00353         aes_ecb_encrypt(&cx->ctx.rj, res, dlen);
00354 
00355     return 0;
00356 }
00357 
00358 static int
00359 rj_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00360 {
00361     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00362 
00363     if (!cx->is_init)
00364         if (rj_real_init(cx, 0))
00365             return PXE_CIPHER_INIT;
00366 
00367     if (dlen == 0)
00368         return 0;
00369 
00370     if (dlen & 15)
00371         return PXE_NOTBLOCKSIZE;
00372 
00373     memcpy(res, data, dlen);
00374 
00375     if (cx->mode == MODE_CBC)
00376     {
00377         aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen);
00378         memcpy(cx->iv, data + dlen - 16, 16);
00379     }
00380     else
00381         aes_ecb_decrypt(&cx->ctx.rj, res, dlen);
00382 
00383     return 0;
00384 }
00385 
00386 /*
00387  * initializers
00388  */
00389 
00390 static PX_Cipher *
00391 rj_load(int mode)
00392 {
00393     PX_Cipher  *c;
00394     struct int_ctx *cx;
00395 
00396     c = px_alloc(sizeof *c);
00397     memset(c, 0, sizeof *c);
00398 
00399     c->block_size = rj_block_size;
00400     c->key_size = rj_key_size;
00401     c->iv_size = rj_iv_size;
00402     c->init = rj_init;
00403     c->encrypt = rj_encrypt;
00404     c->decrypt = rj_decrypt;
00405     c->free = intctx_free;
00406 
00407     cx = px_alloc(sizeof *cx);
00408     memset(cx, 0, sizeof *cx);
00409     cx->mode = mode;
00410 
00411     c->ptr = cx;
00412     return c;
00413 }
00414 
00415 /*
00416  * blowfish
00417  */
00418 
00419 static unsigned
00420 bf_block_size(PX_Cipher *c)
00421 {
00422     return 8;
00423 }
00424 
00425 static unsigned
00426 bf_key_size(PX_Cipher *c)
00427 {
00428     return 448 / 8;
00429 }
00430 
00431 static unsigned
00432 bf_iv_size(PX_Cipher *c)
00433 {
00434     return 8;
00435 }
00436 
00437 static int
00438 bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00439 {
00440     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00441 
00442     blowfish_setkey(&cx->ctx.bf, key, klen);
00443     if (iv)
00444         blowfish_setiv(&cx->ctx.bf, iv);
00445 
00446     return 0;
00447 }
00448 
00449 static int
00450 bf_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00451 {
00452     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00453     BlowfishContext *bfctx = &cx->ctx.bf;
00454 
00455     if (dlen == 0)
00456         return 0;
00457 
00458     if (dlen & 7)
00459         return PXE_NOTBLOCKSIZE;
00460 
00461     memcpy(res, data, dlen);
00462     switch (cx->mode)
00463     {
00464         case MODE_ECB:
00465             blowfish_encrypt_ecb(res, dlen, bfctx);
00466             break;
00467         case MODE_CBC:
00468             blowfish_encrypt_cbc(res, dlen, bfctx);
00469             break;
00470     }
00471     return 0;
00472 }
00473 
00474 static int
00475 bf_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00476 {
00477     struct int_ctx *cx = (struct int_ctx *) c->ptr;
00478     BlowfishContext *bfctx = &cx->ctx.bf;
00479 
00480     if (dlen == 0)
00481         return 0;
00482 
00483     if (dlen & 7)
00484         return PXE_NOTBLOCKSIZE;
00485 
00486     memcpy(res, data, dlen);
00487     switch (cx->mode)
00488     {
00489         case MODE_ECB:
00490             blowfish_decrypt_ecb(res, dlen, bfctx);
00491             break;
00492         case MODE_CBC:
00493             blowfish_decrypt_cbc(res, dlen, bfctx);
00494             break;
00495     }
00496     return 0;
00497 }
00498 
00499 static PX_Cipher *
00500 bf_load(int mode)
00501 {
00502     PX_Cipher  *c;
00503     struct int_ctx *cx;
00504 
00505     c = px_alloc(sizeof *c);
00506     memset(c, 0, sizeof *c);
00507 
00508     c->block_size = bf_block_size;
00509     c->key_size = bf_key_size;
00510     c->iv_size = bf_iv_size;
00511     c->init = bf_init;
00512     c->encrypt = bf_encrypt;
00513     c->decrypt = bf_decrypt;
00514     c->free = intctx_free;
00515 
00516     cx = px_alloc(sizeof *cx);
00517     memset(cx, 0, sizeof *cx);
00518     cx->mode = mode;
00519     c->ptr = cx;
00520     return c;
00521 }
00522 
00523 /* ciphers */
00524 
00525 static PX_Cipher *
00526 rj_128_ecb(void)
00527 {
00528     return rj_load(MODE_ECB);
00529 }
00530 
00531 static PX_Cipher *
00532 rj_128_cbc(void)
00533 {
00534     return rj_load(MODE_CBC);
00535 }
00536 
00537 static PX_Cipher *
00538 bf_ecb_load(void)
00539 {
00540     return bf_load(MODE_ECB);
00541 }
00542 
00543 static PX_Cipher *
00544 bf_cbc_load(void)
00545 {
00546     return bf_load(MODE_CBC);
00547 }
00548 
00549 struct int_cipher
00550 {
00551     char       *name;
00552     PX_Cipher  *(*load) (void);
00553 };
00554 
00555 static const struct int_cipher
00556             int_ciphers[] = {
00557     {"bf-cbc", bf_cbc_load},
00558     {"bf-ecb", bf_ecb_load},
00559     {"aes-128-cbc", rj_128_cbc},
00560     {"aes-128-ecb", rj_128_ecb},
00561     {NULL, NULL}
00562 };
00563 
00564 static const PX_Alias int_aliases[] = {
00565     {"bf", "bf-cbc"},
00566     {"blowfish", "bf-cbc"},
00567     {"aes", "aes-128-cbc"},
00568     {"aes-ecb", "aes-128-ecb"},
00569     {"aes-cbc", "aes-128-cbc"},
00570     {"aes-128", "aes-128-cbc"},
00571     {"rijndael", "aes-128-cbc"},
00572     {"rijndael-128", "aes-128-cbc"},
00573     {NULL, NULL}
00574 };
00575 
00576 /* PUBLIC FUNCTIONS */
00577 
00578 int
00579 px_find_digest(const char *name, PX_MD **res)
00580 {
00581     const struct int_digest *p;
00582     PX_MD      *h;
00583 
00584     for (p = int_digest_list; p->name; p++)
00585         if (pg_strcasecmp(p->name, name) == 0)
00586         {
00587             h = px_alloc(sizeof(*h));
00588             p->init(h);
00589 
00590             *res = h;
00591 
00592             return 0;
00593         }
00594     return PXE_NO_HASH;
00595 }
00596 
00597 int
00598 px_find_cipher(const char *name, PX_Cipher **res)
00599 {
00600     int         i;
00601     PX_Cipher  *c = NULL;
00602 
00603     name = px_resolve_alias(int_aliases, name);
00604 
00605     for (i = 0; int_ciphers[i].name; i++)
00606         if (strcmp(int_ciphers[i].name, name) == 0)
00607         {
00608             c = int_ciphers[i].load();
00609             break;
00610         }
00611 
00612     if (c == NULL)
00613         return PXE_NO_CIPHER;
00614 
00615     *res = c;
00616     return 0;
00617 }
00618 
00619 /*
00620  * Randomness provider
00621  */
00622 
00623 /*
00624  * Use always strong randomness.
00625  */
00626 int
00627 px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
00628 {
00629     return px_get_random_bytes(dst, count);
00630 }
00631 
00632 static time_t seed_time = 0;
00633 static time_t check_time = 0;
00634 
00635 static void
00636 system_reseed(void)
00637 {
00638     uint8       buf[1024];
00639     int         n;
00640     time_t      t;
00641     int         skip = 1;
00642 
00643     t = time(NULL);
00644 
00645     if (seed_time == 0)
00646         skip = 0;
00647     else if ((t - seed_time) < SYSTEM_RESEED_MIN)
00648         skip = 1;
00649     else if ((t - seed_time) > SYSTEM_RESEED_MAX)
00650         skip = 0;
00651     else if (check_time == 0 ||
00652              (t - check_time) > SYSTEM_RESEED_CHECK_TIME)
00653     {
00654         check_time = t;
00655 
00656         /* roll dice */
00657         px_get_random_bytes(buf, 1);
00658         skip = buf[0] >= SYSTEM_RESEED_CHANCE;
00659     }
00660     /* clear 1 byte */
00661     memset(buf, 0, sizeof(buf));
00662 
00663     if (skip)
00664         return;
00665 
00666     n = px_acquire_system_randomness(buf);
00667     if (n > 0)
00668         fortuna_add_entropy(buf, n);
00669 
00670     seed_time = t;
00671     memset(buf, 0, sizeof(buf));
00672 }
00673 
00674 int
00675 px_get_random_bytes(uint8 *dst, unsigned count)
00676 {
00677     system_reseed();
00678     fortuna_get_bytes(count, dst);
00679     return 0;
00680 }
00681 
00682 int
00683 px_add_entropy(const uint8 *data, unsigned count)
00684 {
00685     system_reseed();
00686     fortuna_add_entropy(data, count);
00687     return 0;
00688 }