Header And Logo

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

openssl.c

Go to the documentation of this file.
00001 /*
00002  * openssl.c
00003  *      Wrapper for OpenSSL library.
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/openssl.c
00030  */
00031 
00032 #include "postgres.h"
00033 
00034 #include "px.h"
00035 
00036 #include <openssl/evp.h>
00037 #include <openssl/blowfish.h>
00038 #include <openssl/cast.h>
00039 #include <openssl/des.h>
00040 #include <openssl/rand.h>
00041 #include <openssl/err.h>
00042 
00043 /*
00044  * Max lengths we might want to handle.
00045  */
00046 #define MAX_KEY     (512/8)
00047 #define MAX_IV      (128/8)
00048 
00049 /*
00050  * Compatibility with OpenSSL 0.9.6
00051  *
00052  * It needs AES and newer DES and digest API.
00053  */
00054 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
00055 
00056 /*
00057  * Nothing needed for OpenSSL 0.9.7+
00058  */
00059 
00060 #include <openssl/aes.h>
00061 #else                           /* old OPENSSL */
00062 
00063 /*
00064  * Emulate OpenSSL AES.
00065  */
00066 
00067 #include "rijndael.c"
00068 
00069 #define AES_ENCRYPT 1
00070 #define AES_DECRYPT 0
00071 #define AES_KEY     rijndael_ctx
00072 
00073 static int
00074 AES_set_encrypt_key(const uint8 *key, int kbits, AES_KEY *ctx)
00075 {
00076     aes_set_key(ctx, key, kbits, 1);
00077     return 0;
00078 }
00079 
00080 static int
00081 AES_set_decrypt_key(const uint8 *key, int kbits, AES_KEY *ctx)
00082 {
00083     aes_set_key(ctx, key, kbits, 0);
00084     return 0;
00085 }
00086 
00087 static void
00088 AES_ecb_encrypt(const uint8 *src, uint8 *dst, AES_KEY *ctx, int enc)
00089 {
00090     memcpy(dst, src, 16);
00091     if (enc)
00092         aes_ecb_encrypt(ctx, dst, 16);
00093     else
00094         aes_ecb_decrypt(ctx, dst, 16);
00095 }
00096 
00097 static void
00098 AES_cbc_encrypt(const uint8 *src, uint8 *dst, int len, AES_KEY *ctx, uint8 *iv, int enc)
00099 {
00100     memcpy(dst, src, len);
00101     if (enc)
00102     {
00103         aes_cbc_encrypt(ctx, iv, dst, len);
00104         memcpy(iv, dst + len - 16, 16);
00105     }
00106     else
00107     {
00108         aes_cbc_decrypt(ctx, iv, dst, len);
00109         memcpy(iv, src + len - 16, 16);
00110     }
00111 }
00112 
00113 /*
00114  * Emulate DES_* API
00115  */
00116 
00117 #define DES_key_schedule des_key_schedule
00118 #define DES_cblock des_cblock
00119 #define DES_set_key(k, ks) \
00120         des_set_key((k), *(ks))
00121 #define DES_ecb_encrypt(i, o, k, e) \
00122         des_ecb_encrypt((i), (o), *(k), (e))
00123 #define DES_ncbc_encrypt(i, o, l, k, iv, e) \
00124         des_ncbc_encrypt((i), (o), (l), *(k), (iv), (e))
00125 #define DES_ecb3_encrypt(i, o, k1, k2, k3, e) \
00126         des_ecb3_encrypt((des_cblock *)(i), (des_cblock *)(o), \
00127                 *(k1), *(k2), *(k3), (e))
00128 #define DES_ede3_cbc_encrypt(i, o, l, k1, k2, k3, iv, e) \
00129         des_ede3_cbc_encrypt((i), (o), \
00130                 (l), *(k1), *(k2), *(k3), (iv), (e))
00131 
00132 /*
00133  * Emulate newer digest API.
00134  */
00135 
00136 static void
00137 EVP_MD_CTX_init(EVP_MD_CTX *ctx)
00138 {
00139     memset(ctx, 0, sizeof(*ctx));
00140 }
00141 
00142 static int
00143 EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
00144 {
00145     memset(ctx, 0, sizeof(*ctx));
00146     return 1;
00147 }
00148 
00149 static int
00150 EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine)
00151 {
00152     EVP_DigestInit(ctx, md);
00153     return 1;
00154 }
00155 
00156 static int
00157 EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *res, unsigned int *len)
00158 {
00159     EVP_DigestFinal(ctx, res, len);
00160     return 1;
00161 }
00162 #endif   /* old OpenSSL */
00163 
00164 /*
00165  * Provide SHA2 for older OpenSSL < 0.9.8
00166  */
00167 #if OPENSSL_VERSION_NUMBER < 0x00908000L
00168 
00169 #include "sha2.c"
00170 #include "internal-sha2.c"
00171 
00172 typedef void (*init_f) (PX_MD *md);
00173 
00174 static int
00175 compat_find_digest(const char *name, PX_MD **res)
00176 {
00177     init_f      init = NULL;
00178 
00179     if (pg_strcasecmp(name, "sha224") == 0)
00180         init = init_sha224;
00181     else if (pg_strcasecmp(name, "sha256") == 0)
00182         init = init_sha256;
00183     else if (pg_strcasecmp(name, "sha384") == 0)
00184         init = init_sha384;
00185     else if (pg_strcasecmp(name, "sha512") == 0)
00186         init = init_sha512;
00187     else
00188         return PXE_NO_HASH;
00189 
00190     *res = px_alloc(sizeof(PX_MD));
00191     init(*res);
00192     return 0;
00193 }
00194 #else
00195 #define compat_find_digest(name, res)  (PXE_NO_HASH)
00196 #endif
00197 
00198 /*
00199  * Hashes
00200  */
00201 
00202 typedef struct OSSLDigest
00203 {
00204     const EVP_MD *algo;
00205     EVP_MD_CTX  ctx;
00206 } OSSLDigest;
00207 
00208 static unsigned
00209 digest_result_size(PX_MD *h)
00210 {
00211     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00212 
00213     return EVP_MD_CTX_size(&digest->ctx);
00214 }
00215 
00216 static unsigned
00217 digest_block_size(PX_MD *h)
00218 {
00219     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00220 
00221     return EVP_MD_CTX_block_size(&digest->ctx);
00222 }
00223 
00224 static void
00225 digest_reset(PX_MD *h)
00226 {
00227     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00228 
00229     EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL);
00230 }
00231 
00232 static void
00233 digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
00234 {
00235     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00236 
00237     EVP_DigestUpdate(&digest->ctx, data, dlen);
00238 }
00239 
00240 static void
00241 digest_finish(PX_MD *h, uint8 *dst)
00242 {
00243     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00244 
00245     EVP_DigestFinal_ex(&digest->ctx, dst, NULL);
00246 }
00247 
00248 static void
00249 digest_free(PX_MD *h)
00250 {
00251     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
00252 
00253     EVP_MD_CTX_cleanup(&digest->ctx);
00254 
00255     px_free(digest);
00256     px_free(h);
00257 }
00258 
00259 static int  px_openssl_initialized = 0;
00260 
00261 /* PUBLIC functions */
00262 
00263 int
00264 px_find_digest(const char *name, PX_MD **res)
00265 {
00266     const EVP_MD *md;
00267     PX_MD      *h;
00268     OSSLDigest *digest;
00269 
00270     if (!px_openssl_initialized)
00271     {
00272         px_openssl_initialized = 1;
00273         OpenSSL_add_all_algorithms();
00274     }
00275 
00276     md = EVP_get_digestbyname(name);
00277     if (md == NULL)
00278         return compat_find_digest(name, res);
00279 
00280     digest = px_alloc(sizeof(*digest));
00281     digest->algo = md;
00282 
00283     EVP_MD_CTX_init(&digest->ctx);
00284     if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0)
00285         return -1;
00286 
00287     h = px_alloc(sizeof(*h));
00288     h->result_size = digest_result_size;
00289     h->block_size = digest_block_size;
00290     h->reset = digest_reset;
00291     h->update = digest_update;
00292     h->finish = digest_finish;
00293     h->free = digest_free;
00294     h->p.ptr = (void *) digest;
00295 
00296     *res = h;
00297     return 0;
00298 }
00299 
00300 /*
00301  * Ciphers
00302  *
00303  * The problem with OpenSSL is that the EVP* family
00304  * of functions does not allow enough flexibility
00305  * and forces some of the parameters (keylen,
00306  * padding) to SSL defaults.
00307  *
00308  * So need to manage ciphers ourselves.
00309  */
00310 
00311 struct ossl_cipher
00312 {
00313     int         (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv);
00314     int         (*encrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res);
00315     int         (*decrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res);
00316 
00317     int         block_size;
00318     int         max_key_size;
00319     int         stream_cipher;
00320 };
00321 
00322 typedef struct
00323 {
00324     union
00325     {
00326         struct
00327         {
00328             BF_KEY      key;
00329             int         num;
00330         }           bf;
00331         struct
00332         {
00333             DES_key_schedule key_schedule;
00334         }           des;
00335         struct
00336         {
00337             DES_key_schedule k1,
00338                         k2,
00339                         k3;
00340         }           des3;
00341         CAST_KEY    cast_key;
00342         AES_KEY     aes_key;
00343     }           u;
00344     uint8       key[MAX_KEY];
00345     uint8       iv[MAX_IV];
00346     unsigned    klen;
00347     unsigned    init;
00348     const struct ossl_cipher *ciph;
00349 } ossldata;
00350 
00351 /* generic */
00352 
00353 static unsigned
00354 gen_ossl_block_size(PX_Cipher *c)
00355 {
00356     ossldata   *od = (ossldata *) c->ptr;
00357 
00358     return od->ciph->block_size;
00359 }
00360 
00361 static unsigned
00362 gen_ossl_key_size(PX_Cipher *c)
00363 {
00364     ossldata   *od = (ossldata *) c->ptr;
00365 
00366     return od->ciph->max_key_size;
00367 }
00368 
00369 static unsigned
00370 gen_ossl_iv_size(PX_Cipher *c)
00371 {
00372     unsigned    ivlen;
00373     ossldata   *od = (ossldata *) c->ptr;
00374 
00375     ivlen = od->ciph->block_size;
00376     return ivlen;
00377 }
00378 
00379 static void
00380 gen_ossl_free(PX_Cipher *c)
00381 {
00382     ossldata   *od = (ossldata *) c->ptr;
00383 
00384     memset(od, 0, sizeof(*od));
00385     px_free(od);
00386     px_free(c);
00387 }
00388 
00389 /* Blowfish */
00390 
00391 /*
00392  * Check if strong crypto is supported. Some openssl installations
00393  * support only short keys and unfortunately BF_set_key does not return any
00394  * error value. This function tests if is possible to use strong key.
00395  */
00396 static int
00397 bf_check_supported_key_len(void)
00398 {
00399     static const uint8 key[56] = {
00400         0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69,
00401         0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, 0x00, 0x11, 0x22, 0x33,
00402         0x44, 0x55, 0x66, 0x77, 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd,
00403         0x3b, 0x2f, 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
00404         0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 0xff, 0xff,
00405         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
00406     };
00407 
00408     static const uint8 data[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
00409     static const uint8 res[8] = {0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53};
00410     static uint8 out[8];
00411 
00412     BF_KEY      bf_key;
00413 
00414     /* encrypt with 448bits key and verify output */
00415     BF_set_key(&bf_key, 56, key);
00416     BF_ecb_encrypt(data, out, &bf_key, BF_ENCRYPT);
00417 
00418     if (memcmp(out, res, 8) != 0)
00419         return 0;               /* Output does not match -> strong cipher is
00420                                  * not supported */
00421     return 1;
00422 }
00423 
00424 static int
00425 bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00426 {
00427     ossldata   *od = c->ptr;
00428     static int  bf_is_strong = -1;
00429 
00430     /*
00431      * Test if key len is supported. BF_set_key silently cut large keys and it
00432      * could be be a problem when user transfer crypted data from one server
00433      * to another.
00434      */
00435 
00436     if (bf_is_strong == -1)
00437         bf_is_strong = bf_check_supported_key_len();
00438 
00439     if (!bf_is_strong && klen > 16)
00440         return PXE_KEY_TOO_BIG;
00441 
00442     /* Key len is supported. We can use it. */
00443     BF_set_key(&od->u.bf.key, klen, key);
00444     if (iv)
00445         memcpy(od->iv, iv, BF_BLOCK);
00446     else
00447         memset(od->iv, 0, BF_BLOCK);
00448     od->u.bf.num = 0;
00449     return 0;
00450 }
00451 
00452 static int
00453 bf_ecb_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00454 {
00455     unsigned    bs = gen_ossl_block_size(c);
00456     unsigned    i;
00457     ossldata   *od = c->ptr;
00458 
00459     for (i = 0; i < dlen / bs; i++)
00460         BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_ENCRYPT);
00461     return 0;
00462 }
00463 
00464 static int
00465 bf_ecb_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00466 {
00467     unsigned    bs = gen_ossl_block_size(c),
00468                 i;
00469     ossldata   *od = c->ptr;
00470 
00471     for (i = 0; i < dlen / bs; i++)
00472         BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_DECRYPT);
00473     return 0;
00474 }
00475 
00476 static int
00477 bf_cbc_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00478 {
00479     ossldata   *od = c->ptr;
00480 
00481     BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT);
00482     return 0;
00483 }
00484 
00485 static int
00486 bf_cbc_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00487 {
00488     ossldata   *od = c->ptr;
00489 
00490     BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT);
00491     return 0;
00492 }
00493 
00494 static int
00495 bf_cfb64_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00496 {
00497     ossldata   *od = c->ptr;
00498 
00499     BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
00500                      &od->u.bf.num, BF_ENCRYPT);
00501     return 0;
00502 }
00503 
00504 static int
00505 bf_cfb64_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00506 {
00507     ossldata   *od = c->ptr;
00508 
00509     BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
00510                      &od->u.bf.num, BF_DECRYPT);
00511     return 0;
00512 }
00513 
00514 /* DES */
00515 
00516 static int
00517 ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00518 {
00519     ossldata   *od = c->ptr;
00520     DES_cblock  xkey;
00521 
00522     memset(&xkey, 0, sizeof(xkey));
00523     memcpy(&xkey, key, klen > 8 ? 8 : klen);
00524     DES_set_key(&xkey, &od->u.des.key_schedule);
00525     memset(&xkey, 0, sizeof(xkey));
00526 
00527     if (iv)
00528         memcpy(od->iv, iv, 8);
00529     else
00530         memset(od->iv, 0, 8);
00531     return 0;
00532 }
00533 
00534 static int
00535 ossl_des_ecb_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00536                      uint8 *res)
00537 {
00538     unsigned    bs = gen_ossl_block_size(c);
00539     unsigned    i;
00540     ossldata   *od = c->ptr;
00541 
00542     for (i = 0; i < dlen / bs; i++)
00543         DES_ecb_encrypt((DES_cblock *) (data + i * bs),
00544                         (DES_cblock *) (res + i * bs),
00545                         &od->u.des.key_schedule, 1);
00546     return 0;
00547 }
00548 
00549 static int
00550 ossl_des_ecb_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00551                      uint8 *res)
00552 {
00553     unsigned    bs = gen_ossl_block_size(c);
00554     unsigned    i;
00555     ossldata   *od = c->ptr;
00556 
00557     for (i = 0; i < dlen / bs; i++)
00558         DES_ecb_encrypt((DES_cblock *) (data + i * bs),
00559                         (DES_cblock *) (res + i * bs),
00560                         &od->u.des.key_schedule, 0);
00561     return 0;
00562 }
00563 
00564 static int
00565 ossl_des_cbc_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00566                      uint8 *res)
00567 {
00568     ossldata   *od = c->ptr;
00569 
00570     DES_ncbc_encrypt(data, res, dlen, &od->u.des.key_schedule,
00571                      (DES_cblock *) od->iv, 1);
00572     return 0;
00573 }
00574 
00575 static int
00576 ossl_des_cbc_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00577                      uint8 *res)
00578 {
00579     ossldata   *od = c->ptr;
00580 
00581     DES_ncbc_encrypt(data, res, dlen, &od->u.des.key_schedule,
00582                      (DES_cblock *) od->iv, 0);
00583     return 0;
00584 }
00585 
00586 /* DES3 */
00587 
00588 static int
00589 ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00590 {
00591     ossldata   *od = c->ptr;
00592     DES_cblock  xkey1,
00593                 xkey2,
00594                 xkey3;
00595 
00596     memset(&xkey1, 0, sizeof(xkey1));
00597     memset(&xkey2, 0, sizeof(xkey2));
00598     memset(&xkey3, 0, sizeof(xkey3));
00599     memcpy(&xkey1, key, klen > 8 ? 8 : klen);
00600     if (klen > 8)
00601         memcpy(&xkey2, key + 8, (klen - 8) > 8 ? 8 : (klen - 8));
00602     if (klen > 16)
00603         memcpy(&xkey3, key + 16, (klen - 16) > 8 ? 8 : (klen - 16));
00604 
00605     DES_set_key(&xkey1, &od->u.des3.k1);
00606     DES_set_key(&xkey2, &od->u.des3.k2);
00607     DES_set_key(&xkey3, &od->u.des3.k3);
00608     memset(&xkey1, 0, sizeof(xkey1));
00609     memset(&xkey2, 0, sizeof(xkey2));
00610     memset(&xkey3, 0, sizeof(xkey3));
00611 
00612     if (iv)
00613         memcpy(od->iv, iv, 8);
00614     else
00615         memset(od->iv, 0, 8);
00616     return 0;
00617 }
00618 
00619 static int
00620 ossl_des3_ecb_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00621                       uint8 *res)
00622 {
00623     unsigned    bs = gen_ossl_block_size(c);
00624     unsigned    i;
00625     ossldata   *od = c->ptr;
00626 
00627     for (i = 0; i < dlen / bs; i++)
00628         DES_ecb3_encrypt((void *) (data + i * bs), (void *) (res + i * bs),
00629                          &od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3, 1);
00630     return 0;
00631 }
00632 
00633 static int
00634 ossl_des3_ecb_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00635                       uint8 *res)
00636 {
00637     unsigned    bs = gen_ossl_block_size(c);
00638     unsigned    i;
00639     ossldata   *od = c->ptr;
00640 
00641     for (i = 0; i < dlen / bs; i++)
00642         DES_ecb3_encrypt((void *) (data + i * bs), (void *) (res + i * bs),
00643                          &od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3, 0);
00644     return 0;
00645 }
00646 
00647 static int
00648 ossl_des3_cbc_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00649                       uint8 *res)
00650 {
00651     ossldata   *od = c->ptr;
00652 
00653     DES_ede3_cbc_encrypt(data, res, dlen,
00654                          &od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3,
00655                          (DES_cblock *) od->iv, 1);
00656     return 0;
00657 }
00658 
00659 static int
00660 ossl_des3_cbc_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00661                       uint8 *res)
00662 {
00663     ossldata   *od = c->ptr;
00664 
00665     DES_ede3_cbc_encrypt(data, res, dlen,
00666                          &od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3,
00667                          (DES_cblock *) od->iv, 0);
00668     return 0;
00669 }
00670 
00671 /* CAST5 */
00672 
00673 static int
00674 ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00675 {
00676     ossldata   *od = c->ptr;
00677     unsigned    bs = gen_ossl_block_size(c);
00678 
00679     CAST_set_key(&od->u.cast_key, klen, key);
00680     if (iv)
00681         memcpy(od->iv, iv, bs);
00682     else
00683         memset(od->iv, 0, bs);
00684     return 0;
00685 }
00686 
00687 static int
00688 ossl_cast_ecb_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00689 {
00690     unsigned    bs = gen_ossl_block_size(c);
00691     ossldata   *od = c->ptr;
00692     const uint8 *end = data + dlen - bs;
00693 
00694     for (; data <= end; data += bs, res += bs)
00695         CAST_ecb_encrypt(data, res, &od->u.cast_key, CAST_ENCRYPT);
00696     return 0;
00697 }
00698 
00699 static int
00700 ossl_cast_ecb_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00701 {
00702     unsigned    bs = gen_ossl_block_size(c);
00703     ossldata   *od = c->ptr;
00704     const uint8 *end = data + dlen - bs;
00705 
00706     for (; data <= end; data += bs, res += bs)
00707         CAST_ecb_encrypt(data, res, &od->u.cast_key, CAST_DECRYPT);
00708     return 0;
00709 }
00710 
00711 static int
00712 ossl_cast_cbc_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00713 {
00714     ossldata   *od = c->ptr;
00715 
00716     CAST_cbc_encrypt(data, res, dlen, &od->u.cast_key, od->iv, CAST_ENCRYPT);
00717     return 0;
00718 }
00719 
00720 static int
00721 ossl_cast_cbc_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res)
00722 {
00723     ossldata   *od = c->ptr;
00724 
00725     CAST_cbc_encrypt(data, res, dlen, &od->u.cast_key, od->iv, CAST_DECRYPT);
00726     return 0;
00727 }
00728 
00729 /* AES */
00730 
00731 static int
00732 ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
00733 {
00734     ossldata   *od = c->ptr;
00735     unsigned    bs = gen_ossl_block_size(c);
00736 
00737     if (klen <= 128 / 8)
00738         od->klen = 128 / 8;
00739     else if (klen <= 192 / 8)
00740         od->klen = 192 / 8;
00741     else if (klen <= 256 / 8)
00742         od->klen = 256 / 8;
00743     else
00744         return PXE_KEY_TOO_BIG;
00745 
00746     memcpy(od->key, key, klen);
00747 
00748     if (iv)
00749         memcpy(od->iv, iv, bs);
00750     else
00751         memset(od->iv, 0, bs);
00752     return 0;
00753 }
00754 
00755 static int
00756 ossl_aes_key_init(ossldata *od, int type)
00757 {
00758     int         err;
00759 
00760     /*
00761      * Strong key support could be missing on some openssl installations. We
00762      * must check return value from set key function.
00763      */
00764     if (type == AES_ENCRYPT)
00765         err = AES_set_encrypt_key(od->key, od->klen * 8, &od->u.aes_key);
00766     else
00767         err = AES_set_decrypt_key(od->key, od->klen * 8, &od->u.aes_key);
00768 
00769     if (err == 0)
00770     {
00771         od->init = 1;
00772         return 0;
00773     }
00774     od->init = 0;
00775     return PXE_KEY_TOO_BIG;
00776 }
00777 
00778 static int
00779 ossl_aes_ecb_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00780                      uint8 *res)
00781 {
00782     unsigned    bs = gen_ossl_block_size(c);
00783     ossldata   *od = c->ptr;
00784     const uint8 *end = data + dlen - bs;
00785     int         err;
00786 
00787     if (!od->init)
00788         if ((err = ossl_aes_key_init(od, AES_ENCRYPT)) != 0)
00789             return err;
00790 
00791     for (; data <= end; data += bs, res += bs)
00792         AES_ecb_encrypt(data, res, &od->u.aes_key, AES_ENCRYPT);
00793     return 0;
00794 }
00795 
00796 static int
00797 ossl_aes_ecb_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00798                      uint8 *res)
00799 {
00800     unsigned    bs = gen_ossl_block_size(c);
00801     ossldata   *od = c->ptr;
00802     const uint8 *end = data + dlen - bs;
00803     int         err;
00804 
00805     if (!od->init)
00806         if ((err = ossl_aes_key_init(od, AES_DECRYPT)) != 0)
00807             return err;
00808 
00809     for (; data <= end; data += bs, res += bs)
00810         AES_ecb_encrypt(data, res, &od->u.aes_key, AES_DECRYPT);
00811     return 0;
00812 }
00813 
00814 static int
00815 ossl_aes_cbc_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00816                      uint8 *res)
00817 {
00818     ossldata   *od = c->ptr;
00819     int         err;
00820 
00821     if (!od->init)
00822         if ((err = ossl_aes_key_init(od, AES_ENCRYPT)) != 0)
00823             return err;
00824 
00825     AES_cbc_encrypt(data, res, dlen, &od->u.aes_key, od->iv, AES_ENCRYPT);
00826     return 0;
00827 }
00828 
00829 static int
00830 ossl_aes_cbc_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
00831                      uint8 *res)
00832 {
00833     ossldata   *od = c->ptr;
00834     int         err;
00835 
00836     if (!od->init)
00837         if ((err = ossl_aes_key_init(od, AES_DECRYPT)) != 0)
00838             return err;
00839 
00840     AES_cbc_encrypt(data, res, dlen, &od->u.aes_key, od->iv, AES_DECRYPT);
00841     return 0;
00842 }
00843 
00844 /*
00845  * aliases
00846  */
00847 
00848 static PX_Alias ossl_aliases[] = {
00849     {"bf", "bf-cbc"},
00850     {"blowfish", "bf-cbc"},
00851     {"blowfish-cbc", "bf-cbc"},
00852     {"blowfish-ecb", "bf-ecb"},
00853     {"blowfish-cfb", "bf-cfb"},
00854     {"des", "des-cbc"},
00855     {"3des", "des3-cbc"},
00856     {"3des-ecb", "des3-ecb"},
00857     {"3des-cbc", "des3-cbc"},
00858     {"cast5", "cast5-cbc"},
00859     {"aes", "aes-cbc"},
00860     {"rijndael", "aes-cbc"},
00861     {"rijndael-cbc", "aes-cbc"},
00862     {"rijndael-ecb", "aes-ecb"},
00863     {NULL}
00864 };
00865 
00866 static const struct ossl_cipher ossl_bf_cbc = {
00867     bf_init, bf_cbc_encrypt, bf_cbc_decrypt,
00868     64 / 8, 448 / 8, 0
00869 };
00870 
00871 static const struct ossl_cipher ossl_bf_ecb = {
00872     bf_init, bf_ecb_encrypt, bf_ecb_decrypt,
00873     64 / 8, 448 / 8, 0
00874 };
00875 
00876 static const struct ossl_cipher ossl_bf_cfb = {
00877     bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt,
00878     64 / 8, 448 / 8, 1
00879 };
00880 
00881 static const struct ossl_cipher ossl_des_ecb = {
00882     ossl_des_init, ossl_des_ecb_encrypt, ossl_des_ecb_decrypt,
00883     64 / 8, 64 / 8, 0
00884 };
00885 
00886 static const struct ossl_cipher ossl_des_cbc = {
00887     ossl_des_init, ossl_des_cbc_encrypt, ossl_des_cbc_decrypt,
00888     64 / 8, 64 / 8, 0
00889 };
00890 
00891 static const struct ossl_cipher ossl_des3_ecb = {
00892     ossl_des3_init, ossl_des3_ecb_encrypt, ossl_des3_ecb_decrypt,
00893     64 / 8, 192 / 8, 0
00894 };
00895 
00896 static const struct ossl_cipher ossl_des3_cbc = {
00897     ossl_des3_init, ossl_des3_cbc_encrypt, ossl_des3_cbc_decrypt,
00898     64 / 8, 192 / 8, 0
00899 };
00900 
00901 static const struct ossl_cipher ossl_cast_ecb = {
00902     ossl_cast_init, ossl_cast_ecb_encrypt, ossl_cast_ecb_decrypt,
00903     64 / 8, 128 / 8, 0
00904 };
00905 
00906 static const struct ossl_cipher ossl_cast_cbc = {
00907     ossl_cast_init, ossl_cast_cbc_encrypt, ossl_cast_cbc_decrypt,
00908     64 / 8, 128 / 8, 0
00909 };
00910 
00911 static const struct ossl_cipher ossl_aes_ecb = {
00912     ossl_aes_init, ossl_aes_ecb_encrypt, ossl_aes_ecb_decrypt,
00913     128 / 8, 256 / 8, 0
00914 };
00915 
00916 static const struct ossl_cipher ossl_aes_cbc = {
00917     ossl_aes_init, ossl_aes_cbc_encrypt, ossl_aes_cbc_decrypt,
00918     128 / 8, 256 / 8, 0
00919 };
00920 
00921 /*
00922  * Special handlers
00923  */
00924 struct ossl_cipher_lookup
00925 {
00926     const char *name;
00927     const struct ossl_cipher *ciph;
00928 };
00929 
00930 static const struct ossl_cipher_lookup ossl_cipher_types[] = {
00931     {"bf-cbc", &ossl_bf_cbc},
00932     {"bf-ecb", &ossl_bf_ecb},
00933     {"bf-cfb", &ossl_bf_cfb},
00934     {"des-ecb", &ossl_des_ecb},
00935     {"des-cbc", &ossl_des_cbc},
00936     {"des3-ecb", &ossl_des3_ecb},
00937     {"des3-cbc", &ossl_des3_cbc},
00938     {"cast5-ecb", &ossl_cast_ecb},
00939     {"cast5-cbc", &ossl_cast_cbc},
00940     {"aes-ecb", &ossl_aes_ecb},
00941     {"aes-cbc", &ossl_aes_cbc},
00942     {NULL}
00943 };
00944 
00945 /* PUBLIC functions */
00946 
00947 int
00948 px_find_cipher(const char *name, PX_Cipher **res)
00949 {
00950     const struct ossl_cipher_lookup *i;
00951     PX_Cipher  *c = NULL;
00952     ossldata   *od;
00953 
00954     name = px_resolve_alias(ossl_aliases, name);
00955     for (i = ossl_cipher_types; i->name; i++)
00956         if (strcmp(i->name, name) == 0)
00957             break;
00958     if (i->name == NULL)
00959         return PXE_NO_CIPHER;
00960 
00961     od = px_alloc(sizeof(*od));
00962     memset(od, 0, sizeof(*od));
00963     od->ciph = i->ciph;
00964 
00965     c = px_alloc(sizeof(*c));
00966     c->block_size = gen_ossl_block_size;
00967     c->key_size = gen_ossl_key_size;
00968     c->iv_size = gen_ossl_iv_size;
00969     c->free = gen_ossl_free;
00970     c->init = od->ciph->init;
00971     c->encrypt = od->ciph->encrypt;
00972     c->decrypt = od->ciph->decrypt;
00973     c->ptr = od;
00974 
00975     *res = c;
00976     return 0;
00977 }
00978 
00979 
00980 static int  openssl_random_init = 0;
00981 
00982 /*
00983  * OpenSSL random should re-feeded occasionally. From /dev/urandom
00984  * preferably.
00985  */
00986 static void
00987 init_openssl_rand(void)
00988 {
00989     if (RAND_get_rand_method() == NULL)
00990         RAND_set_rand_method(RAND_SSLeay());
00991     openssl_random_init = 1;
00992 }
00993 
00994 int
00995 px_get_random_bytes(uint8 *dst, unsigned count)
00996 {
00997     int         res;
00998 
00999     if (!openssl_random_init)
01000         init_openssl_rand();
01001 
01002     res = RAND_bytes(dst, count);
01003     if (res == 1)
01004         return count;
01005 
01006     return PXE_OSSL_RAND_ERROR;
01007 }
01008 
01009 int
01010 px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
01011 {
01012     int         res;
01013 
01014     if (!openssl_random_init)
01015         init_openssl_rand();
01016 
01017     res = RAND_pseudo_bytes(dst, count);
01018     if (res == 0 || res == 1)
01019         return count;
01020 
01021     return PXE_OSSL_RAND_ERROR;
01022 }
01023 
01024 int
01025 px_add_entropy(const uint8 *data, unsigned count)
01026 {
01027     /*
01028      * estimate 0 bits
01029      */
01030     RAND_add(data, count, 0);
01031     return 0;
01032 }