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 * contrib/pgcrypto/openssl.c
30 */
31
32 #include "postgres.h"
33
34 #include <openssl/evp.h>
35 #include <openssl/err.h>
36 #include <openssl/rand.h>
37
38 #include "px.h"
39 #include "utils/memutils.h"
40 #include "utils/resowner.h"
41
42 /*
43 * Max lengths we might want to handle.
44 */
45 #define MAX_KEY (512/8)
46 #define MAX_IV (128/8)
47
48 /*
49 * Hashes
50 */
51
52 /*
53 * To make sure we don't leak OpenSSL handles on abort, we keep OSSLDigest
54 * objects in a linked list, allocated in TopMemoryContext. We use the
55 * ResourceOwner mechanism to free them on abort.
56 */
57 typedef struct OSSLDigest
58 {
59 const EVP_MD *algo;
60 EVP_MD_CTX *ctx;
61
62 ResourceOwner owner;
63 struct OSSLDigest *next;
64 struct OSSLDigest *prev;
65 } OSSLDigest;
66
67 static OSSLDigest *open_digests = NULL;
68 static bool digest_resowner_callback_registered = false;
69
70 static void
free_openssl_digest(OSSLDigest * digest)71 free_openssl_digest(OSSLDigest *digest)
72 {
73 EVP_MD_CTX_destroy(digest->ctx);
74 if (digest->prev)
75 digest->prev->next = digest->next;
76 else
77 open_digests = digest->next;
78 if (digest->next)
79 digest->next->prev = digest->prev;
80 pfree(digest);
81 }
82
83 /*
84 * Close any open OpenSSL handles on abort.
85 */
86 static void
digest_free_callback(ResourceReleasePhase phase,bool isCommit,bool isTopLevel,void * arg)87 digest_free_callback(ResourceReleasePhase phase,
88 bool isCommit,
89 bool isTopLevel,
90 void *arg)
91 {
92 OSSLDigest *curr;
93 OSSLDigest *next;
94
95 if (phase != RESOURCE_RELEASE_AFTER_LOCKS)
96 return;
97
98 next = open_digests;
99 while (next)
100 {
101 curr = next;
102 next = curr->next;
103
104 if (curr->owner == CurrentResourceOwner)
105 {
106 if (isCommit)
107 elog(WARNING, "pgcrypto digest reference leak: digest %p still referenced", curr);
108 free_openssl_digest(curr);
109 }
110 }
111 }
112
113 static unsigned
digest_result_size(PX_MD * h)114 digest_result_size(PX_MD *h)
115 {
116 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
117 int result = EVP_MD_CTX_size(digest->ctx);
118
119 if (result < 0)
120 elog(ERROR, "EVP_MD_CTX_size() failed");
121
122 return result;
123 }
124
125 static unsigned
digest_block_size(PX_MD * h)126 digest_block_size(PX_MD *h)
127 {
128 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
129 int result = EVP_MD_CTX_block_size(digest->ctx);
130
131 if (result < 0)
132 elog(ERROR, "EVP_MD_CTX_block_size() failed");
133
134 return result;
135 }
136
137 static void
digest_reset(PX_MD * h)138 digest_reset(PX_MD *h)
139 {
140 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
141
142 if (!EVP_DigestInit_ex(digest->ctx, digest->algo, NULL))
143 elog(ERROR, "EVP_DigestInit_ex() failed");
144 }
145
146 static void
digest_update(PX_MD * h,const uint8 * data,unsigned dlen)147 digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
148 {
149 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
150
151 if (!EVP_DigestUpdate(digest->ctx, data, dlen))
152 elog(ERROR, "EVP_DigestUpdate() failed");
153 }
154
155 static void
digest_finish(PX_MD * h,uint8 * dst)156 digest_finish(PX_MD *h, uint8 *dst)
157 {
158 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
159
160 if (!EVP_DigestFinal_ex(digest->ctx, dst, NULL))
161 elog(ERROR, "EVP_DigestFinal_ex() failed");
162 }
163
164 static void
digest_free(PX_MD * h)165 digest_free(PX_MD *h)
166 {
167 OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
168
169 free_openssl_digest(digest);
170 px_free(h);
171 }
172
173 static int px_openssl_initialized = 0;
174
175 /* PUBLIC functions */
176
177 int
px_find_digest(const char * name,PX_MD ** res)178 px_find_digest(const char *name, PX_MD **res)
179 {
180 const EVP_MD *md;
181 EVP_MD_CTX *ctx;
182 PX_MD *h;
183 OSSLDigest *digest;
184
185 if (!px_openssl_initialized)
186 {
187 px_openssl_initialized = 1;
188 OpenSSL_add_all_algorithms();
189 }
190
191 if (!digest_resowner_callback_registered)
192 {
193 RegisterResourceReleaseCallback(digest_free_callback, NULL);
194 digest_resowner_callback_registered = true;
195 }
196
197 md = EVP_get_digestbyname(name);
198 if (md == NULL)
199 return PXE_NO_HASH;
200
201 /*
202 * Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object.
203 * The order is crucial, to make sure we don't leak anything on
204 * out-of-memory or other error.
205 */
206 digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest));
207
208 ctx = EVP_MD_CTX_create();
209 if (!ctx)
210 {
211 pfree(digest);
212 return -1;
213 }
214 if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
215 {
216 EVP_MD_CTX_destroy(ctx);
217 pfree(digest);
218 return -1;
219 }
220
221 digest->algo = md;
222 digest->ctx = ctx;
223 digest->owner = CurrentResourceOwner;
224 digest->next = open_digests;
225 digest->prev = NULL;
226 open_digests = digest;
227
228 /* The PX_MD object is allocated in the current memory context. */
229 h = px_alloc(sizeof(*h));
230 h->result_size = digest_result_size;
231 h->block_size = digest_block_size;
232 h->reset = digest_reset;
233 h->update = digest_update;
234 h->finish = digest_finish;
235 h->free = digest_free;
236 h->p.ptr = (void *) digest;
237
238 *res = h;
239 return 0;
240 }
241
242 /*
243 * Ciphers
244 *
245 * We use OpenSSL's EVP* family of functions for these.
246 */
247
248 /*
249 * prototype for the EVP functions that return an algorithm, e.g.
250 * EVP_aes_128_cbc().
251 */
252 typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void);
253
254 /*
255 * ossl_cipher contains the static information about each cipher.
256 */
257 struct ossl_cipher
258 {
259 int (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv);
260 ossl_EVP_cipher_func cipher_func;
261 int block_size;
262 int max_key_size;
263 };
264
265 /*
266 * OSSLCipher contains the state for using a cipher. A separate OSSLCipher
267 * object is allocated in each px_find_cipher() call.
268 *
269 * To make sure we don't leak OpenSSL handles on abort, we keep OSSLCipher
270 * objects in a linked list, allocated in TopMemoryContext. We use the
271 * ResourceOwner mechanism to free them on abort.
272 */
273 typedef struct OSSLCipher
274 {
275 EVP_CIPHER_CTX *evp_ctx;
276 const EVP_CIPHER *evp_ciph;
277 uint8 key[MAX_KEY];
278 uint8 iv[MAX_IV];
279 unsigned klen;
280 unsigned init;
281 const struct ossl_cipher *ciph;
282
283 ResourceOwner owner;
284 struct OSSLCipher *next;
285 struct OSSLCipher *prev;
286 } OSSLCipher;
287
288 static OSSLCipher *open_ciphers = NULL;
289 static bool cipher_resowner_callback_registered = false;
290
291 static void
free_openssl_cipher(OSSLCipher * od)292 free_openssl_cipher(OSSLCipher *od)
293 {
294 EVP_CIPHER_CTX_free(od->evp_ctx);
295 if (od->prev)
296 od->prev->next = od->next;
297 else
298 open_ciphers = od->next;
299 if (od->next)
300 od->next->prev = od->prev;
301 pfree(od);
302 }
303
304 /*
305 * Close any open OpenSSL cipher handles on abort.
306 */
307 static void
cipher_free_callback(ResourceReleasePhase phase,bool isCommit,bool isTopLevel,void * arg)308 cipher_free_callback(ResourceReleasePhase phase,
309 bool isCommit,
310 bool isTopLevel,
311 void *arg)
312 {
313 OSSLCipher *curr;
314 OSSLCipher *next;
315
316 if (phase != RESOURCE_RELEASE_AFTER_LOCKS)
317 return;
318
319 next = open_ciphers;
320 while (next)
321 {
322 curr = next;
323 next = curr->next;
324
325 if (curr->owner == CurrentResourceOwner)
326 {
327 if (isCommit)
328 elog(WARNING, "pgcrypto cipher reference leak: cipher %p still referenced", curr);
329 free_openssl_cipher(curr);
330 }
331 }
332 }
333
334 /* Common routines for all algorithms */
335
336 static unsigned
gen_ossl_block_size(PX_Cipher * c)337 gen_ossl_block_size(PX_Cipher *c)
338 {
339 OSSLCipher *od = (OSSLCipher *) c->ptr;
340
341 return od->ciph->block_size;
342 }
343
344 static unsigned
gen_ossl_key_size(PX_Cipher * c)345 gen_ossl_key_size(PX_Cipher *c)
346 {
347 OSSLCipher *od = (OSSLCipher *) c->ptr;
348
349 return od->ciph->max_key_size;
350 }
351
352 static unsigned
gen_ossl_iv_size(PX_Cipher * c)353 gen_ossl_iv_size(PX_Cipher *c)
354 {
355 unsigned ivlen;
356 OSSLCipher *od = (OSSLCipher *) c->ptr;
357
358 ivlen = od->ciph->block_size;
359 return ivlen;
360 }
361
362 static void
gen_ossl_free(PX_Cipher * c)363 gen_ossl_free(PX_Cipher *c)
364 {
365 OSSLCipher *od = (OSSLCipher *) c->ptr;
366
367 free_openssl_cipher(od);
368 px_free(c);
369 }
370
371 static int
gen_ossl_decrypt(PX_Cipher * c,const uint8 * data,unsigned dlen,uint8 * res)372 gen_ossl_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
373 uint8 *res)
374 {
375 OSSLCipher *od = c->ptr;
376 int outlen;
377
378 if (!od->init)
379 {
380 if (!EVP_DecryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
381 return PXE_CIPHER_INIT;
382 if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, 0))
383 return PXE_CIPHER_INIT;
384 if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
385 return PXE_CIPHER_INIT;
386 if (!EVP_DecryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
387 return PXE_CIPHER_INIT;
388 od->init = true;
389 }
390
391 if (!EVP_DecryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
392 return PXE_DECRYPT_FAILED;
393
394 return 0;
395 }
396
397 static int
gen_ossl_encrypt(PX_Cipher * c,const uint8 * data,unsigned dlen,uint8 * res)398 gen_ossl_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen,
399 uint8 *res)
400 {
401 OSSLCipher *od = c->ptr;
402 int outlen;
403
404 if (!od->init)
405 {
406 if (!EVP_EncryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
407 return PXE_CIPHER_INIT;
408 if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, 0))
409 return PXE_CIPHER_INIT;
410 if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
411 return PXE_CIPHER_INIT;
412 if (!EVP_EncryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
413 return PXE_CIPHER_INIT;
414 od->init = true;
415 }
416
417 if (!EVP_EncryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
418 return PXE_ERR_GENERIC;
419
420 return 0;
421 }
422
423 /* Blowfish */
424
425 /*
426 * Check if strong crypto is supported. Some OpenSSL installations
427 * support only short keys and unfortunately BF_set_key does not return any
428 * error value. This function tests if is possible to use strong key.
429 */
430 static int
bf_check_supported_key_len(void)431 bf_check_supported_key_len(void)
432 {
433 static const uint8 key[56] = {
434 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69,
435 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, 0x00, 0x11, 0x22, 0x33,
436 0x44, 0x55, 0x66, 0x77, 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd,
437 0x3b, 0x2f, 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
438 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 0xff, 0xff,
439 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
440 };
441
442 static const uint8 data[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
443 static const uint8 res[8] = {0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53};
444 uint8 out[8];
445 EVP_CIPHER_CTX *evp_ctx;
446 int outlen;
447 int status = 0;
448
449 /* encrypt with 448bits key and verify output */
450 evp_ctx = EVP_CIPHER_CTX_new();
451 if (!evp_ctx)
452 return 0;
453 if (!EVP_EncryptInit_ex(evp_ctx, EVP_bf_ecb(), NULL, NULL, NULL))
454 goto leave;
455 if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, 56))
456 goto leave;
457 if (!EVP_EncryptInit_ex(evp_ctx, NULL, NULL, key, NULL))
458 goto leave;
459
460 if (!EVP_EncryptUpdate(evp_ctx, out, &outlen, data, 8))
461 goto leave;
462
463 if (memcmp(out, res, 8) != 0)
464 goto leave; /* Output does not match -> strong cipher is
465 * not supported */
466 status = 1;
467
468 leave:
469 EVP_CIPHER_CTX_free(evp_ctx);
470 return status;
471 }
472
473 static int
bf_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)474 bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
475 {
476 OSSLCipher *od = c->ptr;
477 unsigned bs = gen_ossl_block_size(c);
478 static int bf_is_strong = -1;
479
480 /*
481 * Test if key len is supported. BF_set_key silently cut large keys and it
482 * could be a problem when user transfer crypted data from one server to
483 * another.
484 */
485
486 if (bf_is_strong == -1)
487 bf_is_strong = bf_check_supported_key_len();
488
489 if (!bf_is_strong && klen > 16)
490 return PXE_KEY_TOO_BIG;
491
492 /* Key len is supported. We can use it. */
493 od->klen = klen;
494 memcpy(od->key, key, klen);
495
496 if (iv)
497 memcpy(od->iv, iv, bs);
498 else
499 memset(od->iv, 0, bs);
500 return 0;
501 }
502
503 /* DES */
504
505 static int
ossl_des_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)506 ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
507 {
508 OSSLCipher *od = c->ptr;
509 unsigned bs = gen_ossl_block_size(c);
510
511 od->klen = 8;
512 memset(od->key, 0, 8);
513 memcpy(od->key, key, klen > 8 ? 8 : klen);
514
515 if (iv)
516 memcpy(od->iv, iv, bs);
517 else
518 memset(od->iv, 0, bs);
519 return 0;
520 }
521
522 /* DES3 */
523
524 static int
ossl_des3_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)525 ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
526 {
527 OSSLCipher *od = c->ptr;
528 unsigned bs = gen_ossl_block_size(c);
529
530 od->klen = 24;
531 memset(od->key, 0, 24);
532 memcpy(od->key, key, klen > 24 ? 24 : klen);
533
534 if (iv)
535 memcpy(od->iv, iv, bs);
536 else
537 memset(od->iv, 0, bs);
538 return 0;
539 }
540
541 /* CAST5 */
542
543 static int
ossl_cast_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)544 ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
545 {
546 OSSLCipher *od = c->ptr;
547 unsigned bs = gen_ossl_block_size(c);
548
549 od->klen = klen;
550 memcpy(od->key, key, klen);
551
552 if (iv)
553 memcpy(od->iv, iv, bs);
554 else
555 memset(od->iv, 0, bs);
556 return 0;
557 }
558
559 /* AES */
560
561 static int
ossl_aes_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)562 ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
563 {
564 OSSLCipher *od = c->ptr;
565 unsigned bs = gen_ossl_block_size(c);
566
567 if (klen <= 128 / 8)
568 od->klen = 128 / 8;
569 else if (klen <= 192 / 8)
570 od->klen = 192 / 8;
571 else if (klen <= 256 / 8)
572 od->klen = 256 / 8;
573 else
574 return PXE_KEY_TOO_BIG;
575
576 memcpy(od->key, key, klen);
577
578 if (iv)
579 memcpy(od->iv, iv, bs);
580 else
581 memset(od->iv, 0, bs);
582
583 return 0;
584 }
585
586 static int
ossl_aes_ecb_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)587 ossl_aes_ecb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
588 {
589 OSSLCipher *od = c->ptr;
590 int err;
591
592 err = ossl_aes_init(c, key, klen, iv);
593 if (err)
594 return err;
595
596 switch (od->klen)
597 {
598 case 128 / 8:
599 od->evp_ciph = EVP_aes_128_ecb();
600 break;
601 case 192 / 8:
602 od->evp_ciph = EVP_aes_192_ecb();
603 break;
604 case 256 / 8:
605 od->evp_ciph = EVP_aes_256_ecb();
606 break;
607 default:
608 /* shouldn't happen */
609 err = PXE_CIPHER_INIT;
610 break;
611 }
612
613 return err;
614 }
615
616 static int
ossl_aes_cbc_init(PX_Cipher * c,const uint8 * key,unsigned klen,const uint8 * iv)617 ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
618 {
619 OSSLCipher *od = c->ptr;
620 int err;
621
622 err = ossl_aes_init(c, key, klen, iv);
623 if (err)
624 return err;
625
626 switch (od->klen)
627 {
628 case 128 / 8:
629 od->evp_ciph = EVP_aes_128_cbc();
630 break;
631 case 192 / 8:
632 od->evp_ciph = EVP_aes_192_cbc();
633 break;
634 case 256 / 8:
635 od->evp_ciph = EVP_aes_256_cbc();
636 break;
637 default:
638 /* shouldn't happen */
639 err = PXE_CIPHER_INIT;
640 break;
641 }
642
643 return err;
644 }
645
646 /*
647 * aliases
648 */
649
650 static PX_Alias ossl_aliases[] = {
651 {"bf", "bf-cbc"},
652 {"blowfish", "bf-cbc"},
653 {"blowfish-cbc", "bf-cbc"},
654 {"blowfish-ecb", "bf-ecb"},
655 {"blowfish-cfb", "bf-cfb"},
656 {"des", "des-cbc"},
657 {"3des", "des3-cbc"},
658 {"3des-ecb", "des3-ecb"},
659 {"3des-cbc", "des3-cbc"},
660 {"cast5", "cast5-cbc"},
661 {"aes", "aes-cbc"},
662 {"rijndael", "aes-cbc"},
663 {"rijndael-cbc", "aes-cbc"},
664 {"rijndael-ecb", "aes-ecb"},
665 {NULL}
666 };
667
668 static const struct ossl_cipher ossl_bf_cbc = {
669 bf_init,
670 EVP_bf_cbc,
671 64 / 8, 448 / 8
672 };
673
674 static const struct ossl_cipher ossl_bf_ecb = {
675 bf_init,
676 EVP_bf_ecb,
677 64 / 8, 448 / 8
678 };
679
680 static const struct ossl_cipher ossl_bf_cfb = {
681 bf_init,
682 EVP_bf_cfb,
683 64 / 8, 448 / 8
684 };
685
686 static const struct ossl_cipher ossl_des_ecb = {
687 ossl_des_init,
688 EVP_des_ecb,
689 64 / 8, 64 / 8
690 };
691
692 static const struct ossl_cipher ossl_des_cbc = {
693 ossl_des_init,
694 EVP_des_cbc,
695 64 / 8, 64 / 8
696 };
697
698 static const struct ossl_cipher ossl_des3_ecb = {
699 ossl_des3_init,
700 EVP_des_ede3_ecb,
701 64 / 8, 192 / 8
702 };
703
704 static const struct ossl_cipher ossl_des3_cbc = {
705 ossl_des3_init,
706 EVP_des_ede3_cbc,
707 64 / 8, 192 / 8
708 };
709
710 static const struct ossl_cipher ossl_cast_ecb = {
711 ossl_cast_init,
712 EVP_cast5_ecb,
713 64 / 8, 128 / 8
714 };
715
716 static const struct ossl_cipher ossl_cast_cbc = {
717 ossl_cast_init,
718 EVP_cast5_cbc,
719 64 / 8, 128 / 8
720 };
721
722 static const struct ossl_cipher ossl_aes_ecb = {
723 ossl_aes_ecb_init,
724 NULL, /* EVP_aes_XXX_ecb(), determined in init
725 * function */
726 128 / 8, 256 / 8
727 };
728
729 static const struct ossl_cipher ossl_aes_cbc = {
730 ossl_aes_cbc_init,
731 NULL, /* EVP_aes_XXX_cbc(), determined in init
732 * function */
733 128 / 8, 256 / 8
734 };
735
736 /*
737 * Special handlers
738 */
739 struct ossl_cipher_lookup
740 {
741 const char *name;
742 const struct ossl_cipher *ciph;
743 };
744
745 static const struct ossl_cipher_lookup ossl_cipher_types[] = {
746 {"bf-cbc", &ossl_bf_cbc},
747 {"bf-ecb", &ossl_bf_ecb},
748 {"bf-cfb", &ossl_bf_cfb},
749 {"des-ecb", &ossl_des_ecb},
750 {"des-cbc", &ossl_des_cbc},
751 {"des3-ecb", &ossl_des3_ecb},
752 {"des3-cbc", &ossl_des3_cbc},
753 {"cast5-ecb", &ossl_cast_ecb},
754 {"cast5-cbc", &ossl_cast_cbc},
755 {"aes-ecb", &ossl_aes_ecb},
756 {"aes-cbc", &ossl_aes_cbc},
757 {NULL}
758 };
759
760 /* PUBLIC functions */
761
762 int
px_find_cipher(const char * name,PX_Cipher ** res)763 px_find_cipher(const char *name, PX_Cipher **res)
764 {
765 const struct ossl_cipher_lookup *i;
766 PX_Cipher *c = NULL;
767 EVP_CIPHER_CTX *ctx;
768 OSSLCipher *od;
769
770 name = px_resolve_alias(ossl_aliases, name);
771 for (i = ossl_cipher_types; i->name; i++)
772 if (strcmp(i->name, name) == 0)
773 break;
774 if (i->name == NULL)
775 return PXE_NO_CIPHER;
776
777 if (!cipher_resowner_callback_registered)
778 {
779 RegisterResourceReleaseCallback(cipher_free_callback, NULL);
780 cipher_resowner_callback_registered = true;
781 }
782
783 /*
784 * Create an OSSLCipher object, an EVP_CIPHER_CTX object and a PX_Cipher.
785 * The order is crucial, to make sure we don't leak anything on
786 * out-of-memory or other error.
787 */
788 od = MemoryContextAllocZero(TopMemoryContext, sizeof(*od));
789 od->ciph = i->ciph;
790
791 /* Allocate an EVP_CIPHER_CTX object. */
792 ctx = EVP_CIPHER_CTX_new();
793 if (!ctx)
794 {
795 pfree(od);
796 return PXE_CIPHER_INIT;
797 }
798
799 od->evp_ctx = ctx;
800 od->owner = CurrentResourceOwner;
801 od->next = open_ciphers;
802 od->prev = NULL;
803 open_ciphers = od;
804
805 if (i->ciph->cipher_func)
806 od->evp_ciph = i->ciph->cipher_func();
807
808 /* The PX_Cipher is allocated in current memory context */
809 c = px_alloc(sizeof(*c));
810 c->block_size = gen_ossl_block_size;
811 c->key_size = gen_ossl_key_size;
812 c->iv_size = gen_ossl_iv_size;
813 c->free = gen_ossl_free;
814 c->init = od->ciph->init;
815 c->encrypt = gen_ossl_encrypt;
816 c->decrypt = gen_ossl_decrypt;
817 c->ptr = od;
818
819 *res = c;
820 return 0;
821 }
822