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