~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/pgcrypto/openssl.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
 * openssl.c
 
3
 *              Wrapper for OpenSSL library.
 
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/openssl.c,v 1.13.4.1 2005-03-12 06:54:31 neilc Exp $
 
30
 */
 
31
 
 
32
#include <postgres.h>
 
33
 
 
34
#include "px.h"
 
35
 
 
36
#include <openssl/evp.h>
 
37
 
 
38
/*
 
39
 * Hashes
 
40
 */
 
41
static unsigned
 
42
digest_result_size(PX_MD * h)
 
43
{
 
44
        return EVP_MD_CTX_size((EVP_MD_CTX *) h->p.ptr);
 
45
}
 
46
 
 
47
static unsigned
 
48
digest_block_size(PX_MD * h)
 
49
{
 
50
        return EVP_MD_CTX_block_size((EVP_MD_CTX *) h->p.ptr);
 
51
}
 
52
 
 
53
static void
 
54
digest_reset(PX_MD * h)
 
55
{
 
56
        EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
 
57
        const EVP_MD *md;
 
58
 
 
59
        md = EVP_MD_CTX_md(ctx);
 
60
 
 
61
        EVP_DigestInit(ctx, md);
 
62
}
 
63
 
 
64
static void
 
65
digest_update(PX_MD * h, const uint8 *data, unsigned dlen)
 
66
{
 
67
        EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
 
68
 
 
69
        EVP_DigestUpdate(ctx, data, dlen);
 
70
}
 
71
 
 
72
static void
 
73
digest_finish(PX_MD * h, uint8 *dst)
 
74
{
 
75
        EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
 
76
        const EVP_MD *md = EVP_MD_CTX_md(ctx);
 
77
 
 
78
        EVP_DigestFinal(ctx, dst, NULL);
 
79
 
 
80
        /*
 
81
         * Some builds of 0.9.7x clear all of ctx in EVP_DigestFinal.
 
82
         * Fix it by reinitializing ctx.
 
83
         */
 
84
        EVP_DigestInit(ctx, md);
 
85
}
 
86
 
 
87
static void
 
88
digest_free(PX_MD * h)
 
89
{
 
90
        EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
 
91
 
 
92
        px_free(ctx);
 
93
        px_free(h);
 
94
}
 
95
 
 
96
static int      px_openssl_initialized = 0;
 
97
 
 
98
/* PUBLIC functions */
 
99
 
 
100
int
 
101
px_find_digest(const char *name, PX_MD ** res)
 
102
{
 
103
        const EVP_MD *md;
 
104
        EVP_MD_CTX *ctx;
 
105
        PX_MD      *h;
 
106
 
 
107
        if (!px_openssl_initialized)
 
108
        {
 
109
                px_openssl_initialized = 1;
 
110
                OpenSSL_add_all_algorithms();
 
111
        }
 
112
 
 
113
        md = EVP_get_digestbyname(name);
 
114
        if (md == NULL)
 
115
                return -1;
 
116
 
 
117
        ctx = px_alloc(sizeof(*ctx));
 
118
        EVP_DigestInit(ctx, md);
 
119
 
 
120
        h = px_alloc(sizeof(*h));
 
121
        h->result_size = digest_result_size;
 
122
        h->block_size = digest_block_size;
 
123
        h->reset = digest_reset;
 
124
        h->update = digest_update;
 
125
        h->finish = digest_finish;
 
126
        h->free = digest_free;
 
127
        h->p.ptr = (void *) ctx;
 
128
 
 
129
        *res = h;
 
130
        return 0;
 
131
}
 
132
 
 
133
/*
 
134
 * Ciphers
 
135
 *
 
136
 * The problem with OpenSSL is that the EVP* family
 
137
 * of functions does not allow enough flexibility
 
138
 * and forces some of the parameters (keylen,
 
139
 * padding) to SSL defaults.
 
140
 *
 
141
 * So need to manage ciphers ourselves.
 
142
 */
 
143
 
 
144
struct ossl_cipher
 
145
{
 
146
        int                     (*init) (PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv);
 
147
        int                     (*encrypt) (PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res);
 
148
        int                     (*decrypt) (PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res);
 
149
 
 
150
        int                     block_size;
 
151
        int                     max_key_size;
 
152
        int                     stream_cipher;
 
153
};
 
154
 
 
155
typedef struct
 
156
{
 
157
        union
 
158
        {
 
159
                struct
 
160
                {
 
161
                        BF_KEY          key;
 
162
                        int                     num;
 
163
                }                       bf;
 
164
                struct
 
165
                {
 
166
                        des_key_schedule key_schedule;
 
167
                }                       des;
 
168
                CAST_KEY        cast_key;
 
169
        }                       u;
 
170
        uint8           key[EVP_MAX_KEY_LENGTH];
 
171
        uint8           iv[EVP_MAX_IV_LENGTH];
 
172
        unsigned        klen;
 
173
        unsigned        init;
 
174
        const struct ossl_cipher *ciph;
 
175
}       ossldata;
 
176
 
 
177
/* generic */
 
178
 
 
179
static unsigned
 
180
gen_ossl_block_size(PX_Cipher * c)
 
181
{
 
182
        ossldata   *od = (ossldata *) c->ptr;
 
183
 
 
184
        return od->ciph->block_size;
 
185
}
 
186
 
 
187
static unsigned
 
188
gen_ossl_key_size(PX_Cipher * c)
 
189
{
 
190
        ossldata   *od = (ossldata *) c->ptr;
 
191
 
 
192
        return od->ciph->max_key_size;
 
193
}
 
194
 
 
195
static unsigned
 
196
gen_ossl_iv_size(PX_Cipher * c)
 
197
{
 
198
        unsigned        ivlen;
 
199
        ossldata   *od = (ossldata *) c->ptr;
 
200
 
 
201
        ivlen = od->ciph->block_size;
 
202
        return ivlen;
 
203
}
 
204
 
 
205
static void
 
206
gen_ossl_free(PX_Cipher * c)
 
207
{
 
208
        ossldata   *od = (ossldata *) c->ptr;
 
209
 
 
210
        memset(od, 0, sizeof(*od));
 
211
        pfree(od);
 
212
        pfree(c);
 
213
}
 
214
 
 
215
/* Blowfish */
 
216
 
 
217
static int
 
218
bf_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
 
219
{
 
220
        ossldata   *od = c->ptr;
 
221
 
 
222
        BF_set_key(&od->u.bf.key, klen, key);
 
223
        if (iv)
 
224
                memcpy(od->iv, iv, BF_BLOCK);
 
225
        else
 
226
                memset(od->iv, 0, BF_BLOCK);
 
227
        od->u.bf.num = 0;
 
228
        return 0;
 
229
}
 
230
 
 
231
static int
 
232
bf_ecb_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
233
{
 
234
        unsigned        bs = gen_ossl_block_size(c);
 
235
        unsigned        i;
 
236
        ossldata   *od = c->ptr;
 
237
 
 
238
        for (i = 0; i < dlen / bs; i++)
 
239
                BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_ENCRYPT);
 
240
        return 0;
 
241
}
 
242
 
 
243
static int
 
244
bf_ecb_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
245
{
 
246
        unsigned        bs = gen_ossl_block_size(c),
 
247
                                i;
 
248
        ossldata   *od = c->ptr;
 
249
 
 
250
        for (i = 0; i < dlen / bs; i++)
 
251
                BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_DECRYPT);
 
252
        return 0;
 
253
}
 
254
 
 
255
static int
 
256
bf_cbc_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
257
{
 
258
        ossldata   *od = c->ptr;
 
259
 
 
260
        BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT);
 
261
        return 0;
 
262
}
 
263
 
 
264
static int
 
265
bf_cbc_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
266
{
 
267
        ossldata   *od = c->ptr;
 
268
 
 
269
        BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT);
 
270
        return 0;
 
271
}
 
272
 
 
273
static int
 
274
bf_cfb64_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
275
{
 
276
        ossldata   *od = c->ptr;
 
277
 
 
278
        BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
 
279
                                         &od->u.bf.num, BF_ENCRYPT);
 
280
        return 0;
 
281
}
 
282
 
 
283
static int
 
284
bf_cfb64_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
285
{
 
286
        ossldata   *od = c->ptr;
 
287
 
 
288
        BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
 
289
                                         &od->u.bf.num, BF_DECRYPT);
 
290
        return 0;
 
291
}
 
292
 
 
293
/* DES */
 
294
 
 
295
static int
 
296
ossl_des_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
 
297
{
 
298
        ossldata   *od = c->ptr;
 
299
        des_cblock      xkey;
 
300
 
 
301
        memset(&xkey, 0, sizeof(xkey));
 
302
        memcpy(&xkey, key, klen > 8 ? 8 : klen);
 
303
        des_set_key(&xkey, od->u.des.key_schedule);
 
304
        memset(&xkey, 0, sizeof(xkey));
 
305
 
 
306
        if (iv)
 
307
                memcpy(od->iv, iv, 8);
 
308
        else
 
309
                memset(od->iv, 0, 8);
 
310
        return 0;
 
311
}
 
312
 
 
313
static int
 
314
ossl_des_ecb_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
 
315
                                         uint8 *res)
 
316
{
 
317
        unsigned        bs = gen_ossl_block_size(c);
 
318
        unsigned        i;
 
319
        ossldata   *od = c->ptr;
 
320
 
 
321
        for (i = 0; i < dlen / bs; i++)
 
322
                des_ecb_encrypt((des_cblock *) (data + i * bs),
 
323
                                                (des_cblock *) (res + i * bs),
 
324
                                                od->u.des.key_schedule, 1);
 
325
        return 0;
 
326
}
 
327
 
 
328
static int
 
329
ossl_des_ecb_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
 
330
                                         uint8 *res)
 
331
{
 
332
        unsigned        bs = gen_ossl_block_size(c);
 
333
        unsigned        i;
 
334
        ossldata   *od = c->ptr;
 
335
 
 
336
        for (i = 0; i < dlen / bs; i++)
 
337
                des_ecb_encrypt((des_cblock *) (data + i * bs),
 
338
                                                (des_cblock *) (res + i * bs),
 
339
                                                od->u.des.key_schedule, 0);
 
340
        return 0;
 
341
}
 
342
 
 
343
static int
 
344
ossl_des_cbc_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
 
345
                                         uint8 *res)
 
346
{
 
347
        ossldata   *od = c->ptr;
 
348
 
 
349
        des_ncbc_encrypt(data, res, dlen, od->u.des.key_schedule,
 
350
                                         (des_cblock *) od->iv, 1);
 
351
        return 0;
 
352
}
 
353
 
 
354
static int
 
355
ossl_des_cbc_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
 
356
                                         uint8 *res)
 
357
{
 
358
        ossldata   *od = c->ptr;
 
359
 
 
360
        des_ncbc_encrypt(data, res, dlen, od->u.des.key_schedule,
 
361
                                         (des_cblock *) od->iv, 0);
 
362
        return 0;
 
363
}
 
364
 
 
365
/* CAST5 */
 
366
 
 
367
static int
 
368
ossl_cast_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
 
369
{
 
370
        ossldata   *od = c->ptr;
 
371
        unsigned        bs = gen_ossl_block_size(c);
 
372
 
 
373
        CAST_set_key(&od->u.cast_key, klen, key);
 
374
        if (iv)
 
375
                memcpy(od->iv, iv, bs);
 
376
        else
 
377
                memset(od->iv, 0, bs);
 
378
        return 0;
 
379
}
 
380
 
 
381
static int
 
382
ossl_cast_ecb_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
383
{
 
384
        unsigned        bs = gen_ossl_block_size(c);
 
385
        ossldata   *od = c->ptr;
 
386
        const uint8 *end = data + dlen - bs;
 
387
 
 
388
        for (; data <= end; data += bs, res += bs)
 
389
                CAST_ecb_encrypt(data, res, &od->u.cast_key, CAST_ENCRYPT);
 
390
        return 0;
 
391
}
 
392
 
 
393
static int
 
394
ossl_cast_ecb_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
395
{
 
396
        unsigned        bs = gen_ossl_block_size(c);
 
397
        ossldata   *od = c->ptr;
 
398
        const uint8 *end = data + dlen - bs;
 
399
 
 
400
        for (; data <= end; data += bs, res += bs)
 
401
                CAST_ecb_encrypt(data, res, &od->u.cast_key, CAST_DECRYPT);
 
402
        return 0;
 
403
}
 
404
 
 
405
static int
 
406
ossl_cast_cbc_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
407
{
 
408
        ossldata   *od = c->ptr;
 
409
 
 
410
        CAST_cbc_encrypt(data, res, dlen, &od->u.cast_key, od->iv, CAST_ENCRYPT);
 
411
        return 0;
 
412
}
 
413
 
 
414
static int
 
415
ossl_cast_cbc_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen, uint8 *res)
 
416
{
 
417
        ossldata   *od = c->ptr;
 
418
 
 
419
        CAST_cbc_encrypt(data, res, dlen, &od->u.cast_key, od->iv, CAST_DECRYPT);
 
420
        return 0;
 
421
}
 
422
 
 
423
/*
 
424
 * aliases
 
425
 */
 
426
 
 
427
static PX_Alias ossl_aliases[] = {
 
428
        {"bf", "bf-cbc"},
 
429
        {"blowfish", "bf-cbc"},
 
430
        {"blowfish-cbc", "bf-cbc"},
 
431
        {"blowfish-ecb", "bf-ecb"},
 
432
        {"blowfish-cfb", "bf-cfb"},
 
433
        {"des", "des-cbc"},
 
434
        {"cast5", "cast5-cbc"},
 
435
        {NULL}
 
436
};
 
437
 
 
438
static const struct ossl_cipher ossl_bf_cbc = {
 
439
        bf_init, bf_cbc_encrypt, bf_cbc_decrypt,
 
440
        64 / 8, 448 / 8, 0
 
441
};
 
442
 
 
443
static const struct ossl_cipher ossl_bf_ecb = {
 
444
        bf_init, bf_ecb_encrypt, bf_ecb_decrypt,
 
445
        64 / 8, 448 / 8, 0
 
446
};
 
447
 
 
448
static const struct ossl_cipher ossl_bf_cfb = {
 
449
        bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt,
 
450
        64 / 8, 448 / 8, 1
 
451
};
 
452
 
 
453
static const struct ossl_cipher ossl_des_ecb = {
 
454
        ossl_des_init, ossl_des_ecb_encrypt, ossl_des_ecb_decrypt,
 
455
        64 / 8, 64 / 8, 0
 
456
};
 
457
 
 
458
static const struct ossl_cipher ossl_des_cbc = {
 
459
        ossl_des_init, ossl_des_cbc_encrypt, ossl_des_cbc_decrypt,
 
460
        64 / 8, 64 / 8, 0
 
461
};
 
462
 
 
463
static const struct ossl_cipher ossl_cast_ecb = {
 
464
        ossl_cast_init, ossl_cast_ecb_encrypt, ossl_cast_ecb_decrypt,
 
465
        64 / 8, 128 / 8, 0
 
466
};
 
467
 
 
468
static const struct ossl_cipher ossl_cast_cbc = {
 
469
        ossl_cast_init, ossl_cast_cbc_encrypt, ossl_cast_cbc_decrypt,
 
470
        64 / 8, 128 / 8, 0
 
471
};
 
472
 
 
473
/*
 
474
 * Special handlers
 
475
 */
 
476
static const struct
 
477
{
 
478
        const char *name;
 
479
        const struct ossl_cipher *ciph;
 
480
}       ossl_cipher_types[] =
 
481
 
 
482
{
 
483
        {
 
484
                "bf-cbc", &ossl_bf_cbc
 
485
        },
 
486
        {
 
487
                "bf-ecb", &ossl_bf_ecb
 
488
        },
 
489
        {
 
490
                "bf-cfb", &ossl_bf_cfb
 
491
        },
 
492
        {
 
493
                "des-ecb", &ossl_des_ecb
 
494
        },
 
495
        {
 
496
                "des-cbc", &ossl_des_cbc
 
497
        },
 
498
        {
 
499
                "cast5-ecb", &ossl_cast_ecb
 
500
        },
 
501
        {
 
502
                "cast5-cbc", &ossl_cast_cbc
 
503
        },
 
504
        {
 
505
                NULL
 
506
        }
 
507
};
 
508
 
 
509
/* PUBLIC functions */
 
510
 
 
511
int
 
512
px_find_cipher(const char *name, PX_Cipher ** res)
 
513
{
 
514
        unsigned        i;
 
515
        PX_Cipher  *c = NULL,
 
516
                           *csrc;
 
517
        ossldata   *od;
 
518
        const struct ossl_cipher *ossl_ciph = NULL;
 
519
 
 
520
        name = px_resolve_alias(ossl_aliases, name);
 
521
        for (i = 0; ossl_cipher_types[i].name; i++)
 
522
        {
 
523
                if (!strcmp(ossl_cipher_types[i].name, name))
 
524
                {
 
525
                        ossl_ciph = ossl_cipher_types[i].ciph;
 
526
                        break;
 
527
                }
 
528
        }
 
529
        if (ossl_ciph == NULL)
 
530
                return -1;
 
531
 
 
532
        od = px_alloc(sizeof(*od));
 
533
        memset(od, 0, sizeof(*od));
 
534
        od->ciph = ossl_ciph;
 
535
 
 
536
        csrc = NULL;
 
537
 
 
538
        c = px_alloc(sizeof(*c));
 
539
        c->block_size = gen_ossl_block_size;
 
540
        c->key_size = gen_ossl_key_size;
 
541
        c->iv_size = gen_ossl_iv_size;
 
542
        c->free = gen_ossl_free;
 
543
        c->init = ossl_ciph->init;
 
544
        c->encrypt = ossl_ciph->encrypt;
 
545
        c->decrypt = ossl_ciph->decrypt;
 
546
        c->ptr = od;
 
547
 
 
548
        *res = c;
 
549
        return 0;
 
550
}