]> granicus.if.org Git - postgresql/blob - contrib/pgcrypto/openssl.c
Another pgindent run. Fixes enum indenting, and improves #endif
[postgresql] / contrib / pgcrypto / openssl.c
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  * $Id: openssl.c,v 1.7 2001/10/28 06:25:41 momjian Exp $
30  */
31
32 #include <postgres.h>
33
34 #include "px.h"
35
36 #include <openssl/evp.h>
37 #include <openssl/blowfish.h>
38
39 static uint
40 digest_result_size(PX_MD * h)
41 {
42         return EVP_MD_CTX_size((EVP_MD_CTX *) h->p.ptr);
43 }
44
45 static uint
46 digest_block_size(PX_MD * h)
47 {
48         return EVP_MD_CTX_block_size((EVP_MD_CTX *) h->p.ptr);
49 }
50
51 static void
52 digest_reset(PX_MD * h)
53 {
54         EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
55         const EVP_MD *md;
56
57         md = EVP_MD_CTX_md(ctx);
58
59         EVP_DigestInit(ctx, md);
60 }
61
62 static void
63 digest_update(PX_MD * h, const uint8 *data, uint dlen)
64 {
65         EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
66
67         EVP_DigestUpdate(ctx, data, dlen);
68 }
69
70 static void
71 digest_finish(PX_MD * h, uint8 *dst)
72 {
73         EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
74
75         EVP_DigestFinal(ctx, dst, NULL);
76 }
77
78 static void
79 digest_free(PX_MD * h)
80 {
81         EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
82
83         px_free(ctx);
84         px_free(h);
85 }
86
87 /* CIPHERS */
88
89 /*
90  * The problem with OpenSSL is that the EVP* family
91  * of functions does not allow enough flexibility
92  * and forces some of the parameters (keylen,
93  * padding) to SSL defaults.
94  */
95
96
97 typedef struct
98 {
99         union
100         {
101                 struct
102                 {
103                         BF_KEY          key;
104                         int                     num;
105                 }                       bf;
106                 EVP_CIPHER_CTX evp_ctx;
107         }                       u;
108         const EVP_CIPHER *evp_ciph;
109         uint8           key[EVP_MAX_KEY_LENGTH];
110         uint8           iv[EVP_MAX_IV_LENGTH];
111         uint            klen;
112         uint            init;
113 }                       ossldata;
114
115 /* generic EVP */
116
117 static uint
118 gen_evp_block_size(PX_Cipher * c)
119 {
120         ossldata   *od = (ossldata *) c->ptr;
121
122         return EVP_CIPHER_block_size(od->evp_ciph);
123 }
124
125 static uint
126 gen_evp_key_size(PX_Cipher * c)
127 {
128         ossldata   *od = (ossldata *) c->ptr;
129
130         return EVP_CIPHER_key_length(od->evp_ciph);
131 }
132
133 static uint
134 gen_evp_iv_size(PX_Cipher * c)
135 {
136         uint            ivlen;
137         ossldata   *od = (ossldata *) c->ptr;
138
139         ivlen = EVP_CIPHER_iv_length(od->evp_ciph);
140         return ivlen;
141 }
142
143 static void
144 gen_evp_free(PX_Cipher * c)
145 {
146         ossldata   *od = (ossldata *) c->ptr;
147
148         memset(od, 0, sizeof(*od));
149         pfree(od);
150         pfree(c);
151 }
152
153 /* fun */
154
155 static int
156 gen_evp_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
157 {
158         ossldata   *od = (ossldata *) c->ptr;
159         uint            bs = gen_evp_block_size(c);
160
161         if (iv)
162                 memcpy(od->iv, iv, bs);
163         else
164                 memset(od->iv, 0, bs);
165         memcpy(od->key, key, klen);
166         od->klen = klen;
167         od->init = 0;
168         return 0;
169 }
170
171 static void
172 _gen_init(PX_Cipher * c, int enc)
173 {
174         ossldata   *od = c->ptr;
175
176         od->evp_ciph->init(&od->u.evp_ctx, od->key, od->iv, enc);
177         od->init = 1;
178         od->u.evp_ctx.encrypt = enc;
179 }
180
181 static int
182 gen_evp_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
183 {
184         ossldata   *od = c->ptr;
185
186         if (!od->init)
187                 _gen_init(c, 1);
188         od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
189         return 0;
190 }
191
192 static int
193 gen_evp_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
194 {
195         ossldata   *od = c->ptr;
196
197         if (!od->init)
198                 _gen_init(c, 0);
199         od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
200         return 0;
201 }
202
203 /* Blowfish */
204
205 static int
206 bf_init(PX_Cipher * c, const uint8 *key, uint klen, const uint8 *iv)
207 {
208         ossldata   *od = c->ptr;
209
210         BF_set_key(&od->u.bf.key, klen, key);
211         if (iv)
212                 memcpy(od->iv, iv, BF_BLOCK);
213         else
214                 memset(od->iv, 0, BF_BLOCK);
215         od->u.bf.num = 0;
216         return 0;
217 }
218
219 static int
220 bf_ecb_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
221 {
222         uint            bs = gen_evp_block_size(c),
223                                 i;
224         ossldata   *od = c->ptr;
225
226         for (i = 0; i < dlen / bs; i++)
227                 BF_ecb_encrypt(data + i * bs, res + i * bs, &od->u.bf.key, BF_ENCRYPT);
228         return 0;
229 }
230
231 static int
232 bf_ecb_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
233 {
234         uint            bs = gen_evp_block_size(c),
235                                 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_DECRYPT);
240         return 0;
241 }
242
243 static int
244 bf_cbc_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
245 {
246         ossldata   *od = c->ptr;
247
248         BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT);
249         return 0;
250 }
251
252 static int
253 bf_cbc_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
254 {
255         ossldata   *od = c->ptr;
256
257         BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT);
258         return 0;
259 }
260
261 static int
262 bf_cfb64_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
263 {
264         ossldata   *od = c->ptr;
265
266         BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
267                                          &od->u.bf.num, BF_ENCRYPT);
268         return 0;
269 }
270
271 static int
272 bf_cfb64_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
273 {
274         ossldata   *od = c->ptr;
275
276         BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
277                                          &od->u.bf.num, BF_DECRYPT);
278         return 0;
279 }
280
281 static int
282 bf_ofb64_encrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
283 {
284         ossldata   *od = c->ptr;
285
286         BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
287         return 0;
288 }
289
290 static int
291 bf_ofb64_decrypt(PX_Cipher * c, const uint8 *data, uint dlen, uint8 *res)
292 {
293         ossldata   *od = c->ptr;
294
295         BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
296         return 0;
297 }
298
299 /*
300  * aliases
301  */
302
303 static PX_Alias ossl_aliases[] = {
304         {"bf", "bf-cbc"},
305         {"blowfish", "bf-cbc"},
306         {"blowfish-cbc", "bf-cbc"},
307         {"blowfish-ecb", "bf-ecb"},
308         {"blowfish-cfb", "bf-cfb"},
309         {"blowfish-ofb", "bf-ofb"},
310         {NULL}
311 };
312
313 /*
314 static PX_Alias ossl_mode_aliases [] = {
315         { "cfb64", "cfb" },
316         { "ofb64", "ofb" },
317         { NULL }
318 };*/
319
320 /*
321  * Special handlers
322  */
323 struct
324 {
325         char       *name;
326         PX_Cipher       cf;
327 }                       spec_types[] =
328
329 {
330         {
331                 "bf-cbc",
332                 {
333                         gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
334                                 bf_init, bf_cbc_encrypt, bf_cbc_decrypt, gen_evp_free
335                 }
336         },
337         {
338                 "bf-ecb",
339                 {
340                         gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
341                                 bf_init, bf_ecb_encrypt, bf_ecb_decrypt, gen_evp_free
342                 }
343         },
344         {
345                 "bf-cfb",
346                 {
347                         gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
348                                 bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt, gen_evp_free
349                 }
350         },
351         {
352                 "bf-ofb",
353                 {
354                         gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
355                                 bf_init, bf_ofb64_encrypt, bf_ofb64_decrypt, gen_evp_free
356                 }
357         },
358         {
359                 NULL
360         }
361 };
362
363 /*
364  * Generic EVP_* functions handler
365  */
366 static PX_Cipher gen_evp_handler = {
367         gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
368         gen_evp_init, gen_evp_encrypt, gen_evp_decrypt, gen_evp_free
369 };
370
371 static int      px_openssl_initialized = 0;
372
373 /* ATM not needed
374 static void *o_alloc(uint s) { return px_alloc(s); }
375 static void *o_realloc(void *p) { return px_realloc(p); }
376 static void o_free(void *p) { px_free(p); }
377 */
378
379 /* PUBLIC functions */
380
381 int
382 px_find_digest(const char *name, PX_MD ** res)
383 {
384         const EVP_MD *md;
385         EVP_MD_CTX *ctx;
386         PX_MD      *h;
387
388         if (!px_openssl_initialized)
389         {
390                 px_openssl_initialized = 1;
391                 /* CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free); */
392                 OpenSSL_add_all_algorithms();
393         }
394
395         md = EVP_get_digestbyname(name);
396         if (md == NULL)
397                 return -1;
398
399         ctx = px_alloc(sizeof(*ctx));
400         EVP_DigestInit(ctx, md);
401
402         h = px_alloc(sizeof(*h));
403         h->result_size = digest_result_size;
404         h->block_size = digest_block_size;
405         h->reset = digest_reset;
406         h->update = digest_update;
407         h->finish = digest_finish;
408         h->free = digest_free;
409         h->p.ptr = (void *) ctx;
410
411         *res = h;
412         return 0;
413 }
414
415
416 int
417 px_find_cipher(const char *name, PX_Cipher ** res)
418 {
419         uint            i;
420         PX_Cipher  *c = NULL,
421                            *csrc;
422         ossldata   *od;
423
424         const EVP_CIPHER *evp_c;
425
426         if (!px_openssl_initialized)
427         {
428                 px_openssl_initialized = 1;
429                 /* CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free); */
430                 OpenSSL_add_all_algorithms();
431         }
432
433         name = px_resolve_alias(ossl_aliases, name);
434         evp_c = EVP_get_cipherbyname(name);
435         if (evp_c == NULL)
436                 return -1;
437
438         od = px_alloc(sizeof(*od));
439         memset(od, 0, sizeof(*od));
440         od->evp_ciph = evp_c;
441
442         csrc = NULL;
443
444         for (i = 0; spec_types[i].name; i++)
445                 if (!strcmp(name, spec_types[i].name))
446                 {
447                         csrc = &spec_types[i].cf;
448                         break;
449                 }
450
451         if (csrc == NULL)
452                 csrc = &gen_evp_handler;
453
454         c = px_alloc(sizeof(*c));
455         memcpy(c, csrc, sizeof(*c));
456         c->ptr = od;
457
458         *res = c;
459         return 0;
460 }