Apache HTTPD
apr_crypto_openssl.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_lib.h"
18#include "apu.h"
19#include "apu_errno.h"
20
21#include <ctype.h>
22#include <assert.h>
23#include <stdlib.h>
24
25#include "apr_strings.h"
26#include "apr_time.h"
27#include "apr_buckets.h"
28
29#include "apr_crypto_internal.h"
30
31#if APU_HAVE_CRYPTO
32
33#include <openssl/evp.h>
34#include <openssl/rand.h>
35#include <openssl/engine.h>
36
37#define LOG_PREFIX "apr_crypto_openssl: "
38
39#ifndef APR_USE_OPENSSL_PRE_1_1_API
40#if defined(LIBRESSL_VERSION_NUMBER)
41/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most
42 * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so
43 * we have to work around this...
44 */
45#define APR_USE_OPENSSL_PRE_1_1_API (1)
46#else
47#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
48#endif
49#endif
50
51struct apr_crypto_t {
53 const apr_crypto_driver_t *provider;
55 apr_crypto_config_t *config;
58};
59
62};
63
64struct apr_crypto_key_t {
66 const apr_crypto_driver_t *provider;
67 const apr_crypto_t *f;
68 const EVP_CIPHER * cipher;
69 unsigned char *key;
70 int keyLen;
71 int doPad;
72 int ivSize;
73};
74
75struct apr_crypto_block_t {
77 const apr_crypto_driver_t *provider;
78 const apr_crypto_t *f;
80 int initialised;
81 int ivSize;
82 int blockSize;
83 int doPad;
84};
85
87{
88{ APR_KEY_3DES_192, 24, 8, 8 },
89{ APR_KEY_AES_128, 16, 16, 16 },
90{ APR_KEY_AES_192, 24, 16, 16 },
91{ APR_KEY_AES_256, 32, 16, 16 } };
92
94{
95{ APR_MODE_ECB },
96{ APR_MODE_CBC } };
97
98/* sufficient space to wrap a key */
99#define BUFFER_SIZE 128
100
105 const apr_crypto_t *f)
106{
107 *result = f->result;
108 return APR_SUCCESS;
109}
110
114static apr_status_t crypto_shutdown(void)
115{
117 EVP_cleanup();
119 return APR_SUCCESS;
120}
121
123{
124 return crypto_shutdown();
125}
126
130static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
131 const apu_err_t **result)
132{
133#if APR_USE_OPENSSL_PRE_1_1_API
134 (void)CRYPTO_malloc_init();
135#else
137#endif
139 /* SSL_load_error_strings(); */
143
146
147 return APR_SUCCESS;
148}
149
150#if OPENSSL_VERSION_NUMBER < 0x0090802fL
151
152/* Code taken from OpenSSL 0.9.8b, see
153 * https://github.com/openssl/openssl/commit/cf6bc84148cb15af09b292394aaf2b45f0d5af0d
154 */
155
157{
159 if (ctx)
161 return ctx;
162}
163
165{
166 if (ctx) {
169 }
170}
171
172#endif
173
181{
182
183 if (ctx->initialised) {
184 EVP_CIPHER_CTX_free(ctx->cipherCtx);
185 ctx->initialised = 0;
186 }
187
188 return APR_SUCCESS;
189
190}
191
193{
196}
197
205{
206
207 if (f->config->engine) {
208 ENGINE_finish(f->config->engine);
209 ENGINE_free(f->config->engine);
210 f->config->engine = NULL;
211 }
212 return APR_SUCCESS;
213
214}
215
217{
219 return crypto_cleanup(f);
220}
221
235 const apr_crypto_driver_t *provider, const char *params,
237{
238 apr_crypto_config_t *config = NULL;
240
241 const char *engine = NULL;
242
243 struct {
244 const char *field;
245 const char *value;
246 int set;
247 } fields[] = {
248 { "engine", NULL, 0 },
249 { NULL, NULL, 0 }
250 };
251 const char *ptr;
252 size_t klen;
253 char **elts = NULL;
254 char *elt;
255 int i = 0, j;
257
258 if (params) {
259 if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
260 return status;
261 }
262 while ((elt = elts[i])) {
263 ptr = strchr(elt, '=');
264 if (ptr) {
265 for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
266 ;
267 ptr++;
268 }
269 else {
270 for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
271 ;
272 }
273 elt[klen] = 0;
274
275 for (j = 0; fields[j].field != NULL; ++j) {
276 if (!strcasecmp(fields[j].field, elt)) {
277 fields[j].set = 1;
278 if (ptr) {
279 fields[j].value = ptr;
280 }
281 break;
282 }
283 }
284
285 i++;
286 }
287 engine = fields[0].value;
288 }
289
290 if (!f) {
291 return APR_ENOMEM;
292 }
293 *ff = f;
294 f->pool = pool;
295 f->provider = provider;
296 config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
297 if (!config) {
298 return APR_ENOMEM;
299 }
300
301 f->result = apr_pcalloc(pool, sizeof(apu_err_t));
302 if (!f->result) {
303 return APR_ENOMEM;
304 }
305
306 f->types = apr_hash_make(pool);
307 if (!f->types) {
308 return APR_ENOMEM;
309 }
310 apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
311 apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
312 apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
313 apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
314
315 f->modes = apr_hash_make(pool);
316 if (!f->modes) {
317 return APR_ENOMEM;
318 }
319 apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
320 apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
321
324
325 if (engine) {
326 config->engine = ENGINE_by_id(engine);
327 if (!config->engine) {
328 return APR_ENOENGINE;
329 }
330 if (!ENGINE_init(config->engine)) {
331 ENGINE_free(config->engine);
332 config->engine = NULL;
333 return APR_EINITENGINE;
334 }
335 }
336
337 return APR_SUCCESS;
338
339}
340
350 const apr_crypto_t *f)
351{
352 *types = f->types;
353 return APR_SUCCESS;
354}
355
365 const apr_crypto_t *f)
366{
367 *modes = f->modes;
368 return APR_SUCCESS;
369}
370
371/*
372 * Work out which mechanism to use.
373 */
377{
378 /* determine the cipher to be used */
379 switch (type) {
380
381 case (APR_KEY_3DES_192):
382
383 /* A 3DES key */
384 if (mode == APR_MODE_CBC) {
385 key->cipher = EVP_des_ede3_cbc();
386 }
387 else {
388 key->cipher = EVP_des_ede3_ecb();
389 }
390 break;
391
392 case (APR_KEY_AES_128):
393
394 if (mode == APR_MODE_CBC) {
395 key->cipher = EVP_aes_128_cbc();
396 }
397 else {
398 key->cipher = EVP_aes_128_ecb();
399 }
400 break;
401
402 case (APR_KEY_AES_192):
403
404 if (mode == APR_MODE_CBC) {
405 key->cipher = EVP_aes_192_cbc();
406 }
407 else {
408 key->cipher = EVP_aes_192_ecb();
409 }
410 break;
411
412 case (APR_KEY_AES_256):
413
414 if (mode == APR_MODE_CBC) {
415 key->cipher = EVP_aes_256_cbc();
416 }
417 else {
418 key->cipher = EVP_aes_256_ecb();
419 }
420 break;
421
422 default:
423
424 /* unknown key type, give up */
425 return APR_EKEYTYPE;
426
427 }
428
429 /* find the length of the key we need */
430 key->keyLen = EVP_CIPHER_key_length(key->cipher);
431
432 /* make space for the key */
433 key->key = apr_pcalloc(p, key->keyLen);
434 if (!key->key) {
435 return APR_ENOMEM;
436 }
437 apr_crypto_clear(p, key->key, key->keyLen);
438
439 return APR_SUCCESS;
440}
441
460{
461 apr_crypto_key_t *key = *k;
462 apr_status_t rv;
463
464 if (!key) {
465 *k = key = apr_pcalloc(p, sizeof *key);
466 if (!key) {
467 return APR_ENOMEM;
468 }
469 }
470
471 key->f = f;
472 key->provider = f->provider;
473
474 /* decide on what cipher mechanism we will be using */
475 rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
476 if (APR_SUCCESS != rv) {
477 return rv;
478 }
479
480 switch (rec->ktype) {
481
483
484 /* generate the key */
485 if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
486 rec->k.passphrase.passLen,
487 (unsigned char *) rec->k.passphrase.salt,
488 rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
489 key->keyLen, key->key) == 0) {
490 return APR_ENOKEY;
491 }
492
493 break;
494 }
495
497
498 /* sanity check - key correct size? */
499 if (rec->k.secret.secretLen != key->keyLen) {
500 return APR_EKEYLENGTH;
501 }
502
503 /* copy the key */
504 memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
505
506 break;
507 }
508
509 default: {
510
511 return APR_ENOKEY;
512
513 }
514 }
515
516 key->doPad = rec->pad;
517
518 /* note: openssl incorrectly returns non zero IV size values for ECB
519 * algorithms, so work around this by ignoring the IV size.
520 */
521 if (APR_MODE_ECB != rec->mode) {
522 key->ivSize = EVP_CIPHER_iv_length(key->cipher);
523 }
524
525 return APR_SUCCESS;
526}
527
557 const char *pass, apr_size_t passLen, const unsigned char * salt,
559 const apr_crypto_block_key_mode_e mode, const int doPad,
560 const int iterations, const apr_crypto_t *f, apr_pool_t *p)
561{
562 apr_crypto_key_t *key = *k;
563 apr_status_t rv;
564
565 if (!key) {
566 *k = key = apr_pcalloc(p, sizeof *key);
567 if (!key) {
568 return APR_ENOMEM;
569 }
570 }
571
572 key->f = f;
573 key->provider = f->provider;
574
575 /* decide on what cipher mechanism we will be using */
577 if (APR_SUCCESS != rv) {
578 return rv;
579 }
580
581 /* generate the key */
582 if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
583 iterations, key->keyLen, key->key) == 0) {
584 return APR_ENOKEY;
585 }
586
587 key->doPad = doPad;
588
589 /* note: openssl incorrectly returns non zero IV size values for ECB
590 * algorithms, so work around this by ignoring the IV size.
591 */
592 if (APR_MODE_ECB != mode) {
593 key->ivSize = EVP_CIPHER_iv_length(key->cipher);
594 }
595 if (ivSize) {
596 *ivSize = key->ivSize;
597 }
598
599 return APR_SUCCESS;
600}
601
619 const unsigned char **iv, const apr_crypto_key_t *key,
621{
622 unsigned char *usedIv;
623 apr_crypto_config_t *config = key->f->config;
625 if (!block) {
627 }
628 if (!block) {
629 return APR_ENOMEM;
630 }
631 block->f = key->f;
632 block->pool = p;
633 block->provider = key->provider;
634
637
638 /* create a new context for encryption */
639 if (!block->initialised) {
640 block->cipherCtx = EVP_CIPHER_CTX_new();
641 block->initialised = 1;
642 }
643
644 /* generate an IV, if necessary */
645 usedIv = NULL;
646 if (key->ivSize) {
647 if (iv == NULL) {
648 return APR_ENOIV;
649 }
650 if (*iv == NULL) {
651 usedIv = apr_pcalloc(p, key->ivSize);
652 if (!usedIv) {
653 return APR_ENOMEM;
654 }
655 apr_crypto_clear(p, usedIv, key->ivSize);
656 if (!((RAND_status() == 1)
657 && (RAND_bytes(usedIv, key->ivSize) == 1))) {
658 return APR_ENOIV;
659 }
660 *iv = usedIv;
661 }
662 else {
663 usedIv = (unsigned char *) *iv;
664 }
665 }
666
667 /* set up our encryption context */
668#if CRYPTO_OPENSSL_CONST_BUFFERS
669 if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
670 key->key, usedIv)) {
671#else
672 if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
673#endif
674 return APR_EINIT;
675 }
676
677 /* Clear up any read padding */
678 if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
679 return APR_EPADDING;
680 }
681
682 if (blockSize) {
684 }
685
686 return APR_SUCCESS;
687
688}
689
708static apr_status_t crypto_block_encrypt(unsigned char **out,
709 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
711{
712 int outl = *outlen;
713 unsigned char *buffer;
714
715 /* are we after the maximum size of the out buffer? */
716 if (!out) {
718 return APR_SUCCESS;
719 }
720
721 /* must we allocate the output buffer from a pool? */
722 if (!*out) {
724 if (!buffer) {
725 return APR_ENOMEM;
726 }
728 *out = buffer;
729 }
730
731#if CRYPT_OPENSSL_CONST_BUFFERS
732 if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl, in, inlen)) {
733#else
734 if (!EVP_EncryptUpdate(ctx->cipherCtx, (*out), &outl,
735 (unsigned char *) in, inlen)) {
736#endif
737#if APR_USE_OPENSSL_PRE_1_1_API
738 EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
739#else
740 EVP_CIPHER_CTX_reset(ctx->cipherCtx);
741#endif
742 return APR_ECRYPT;
743 }
744 *outlen = outl;
745
746 return APR_SUCCESS;
747
748}
749
768static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
770{
772 int len = *outlen;
773
774 if (EVP_EncryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
776 }
777 else {
778 *outlen = len;
779 }
780#if APR_USE_OPENSSL_PRE_1_1_API
781 EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
782#else
783 EVP_CIPHER_CTX_reset(ctx->cipherCtx);
784#endif
785
786 return rc;
787
788}
789
806 apr_size_t *blockSize, const unsigned char *iv,
808{
809 apr_crypto_config_t *config = key->f->config;
811 if (!block) {
813 }
814 if (!block) {
815 return APR_ENOMEM;
816 }
817 block->f = key->f;
818 block->pool = p;
819 block->provider = key->provider;
820
823
824 /* create a new context for encryption */
825 if (!block->initialised) {
826 block->cipherCtx = EVP_CIPHER_CTX_new();
827 block->initialised = 1;
828 }
829
830 /* generate an IV, if necessary */
831 if (key->ivSize) {
832 if (iv == NULL) {
833 return APR_ENOIV;
834 }
835 }
836
837 /* set up our encryption context */
838#if CRYPTO_OPENSSL_CONST_BUFFERS
839 if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
840 key->key, iv)) {
841#else
842 if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
843#endif
844 return APR_EINIT;
845 }
846
847 /* Clear up any read padding */
848 if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) {
849 return APR_EPADDING;
850 }
851
852 if (blockSize) {
854 }
855
856 return APR_SUCCESS;
857
858}
859
878static apr_status_t crypto_block_decrypt(unsigned char **out,
879 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
881{
882 int outl = *outlen;
883 unsigned char *buffer;
884
885 /* are we after the maximum size of the out buffer? */
886 if (!out) {
888 return APR_SUCCESS;
889 }
890
891 /* must we allocate the output buffer from a pool? */
892 if (!(*out)) {
894 if (!buffer) {
895 return APR_ENOMEM;
896 }
898 *out = buffer;
899 }
900
901#if CRYPT_OPENSSL_CONST_BUFFERS
902 if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, in, inlen)) {
903#else
904 if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, (unsigned char *) in,
905 inlen)) {
906#endif
907#if APR_USE_OPENSSL_PRE_1_1_API
908 EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
909#else
910 EVP_CIPHER_CTX_reset(ctx->cipherCtx);
911#endif
912 return APR_ECRYPT;
913 }
914 *outlen = outl;
915
916 return APR_SUCCESS;
917
918}
919
938static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
940{
942 int len = *outlen;
943
944 if (EVP_DecryptFinal_ex(ctx->cipherCtx, out, &len) == 0) {
946 }
947 else {
948 *outlen = len;
949 }
950#if APR_USE_OPENSSL_PRE_1_1_API
951 EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
952#else
953 EVP_CIPHER_CTX_reset(ctx->cipherCtx);
954#endif
955
956 return rc;
957
958}
959
971};
972
973#endif
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
static apr_uint32_t initialised
Definition apr_dbd.c:37
APR general purpose library routines.
APR Strings library.
APR Time Library.
APR-Util Error Codes.
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_EINIT
Definition apr_errno.h:474
const char * salt
Definition apr_md5.h:139
apr_file_t * f
apr_brigade_flush void * ctx
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
apr_pool_t const char * params
Definition apr_dbd.h:141
#define APR_ENOIV
Definition apu_errno.h:65
#define APR_ECRYPT
Definition apu_errno.h:71
#define APR_EKEYTYPE
Definition apu_errno.h:67
#define APR_EINITENGINE
Definition apu_errno.h:83
#define APR_EKEYLENGTH
Definition apu_errno.h:75
#define APR_ENOKEY
Definition apu_errno.h:63
#define APR_ENOENGINE
Definition apu_errno.h:81
#define APR_EPADDING
Definition apu_errno.h:73
apr_redis_t * rc
Definition apr_redis.h:173
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isspace(c)
Definition apr_lib.h:225
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
void * data
int type
char * buffer
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
apr_ssize_t * klen
Definition apr_hash.h:71
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
void * rec
Definition apr_hash.h:270
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_int32_t in
int int status
apr_pool_t * p
Definition md_event.c:32
static apr_file_t * out
Definition mod_info.c:85
static const char *const types[]
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static const char * key_types[]
apr_pool_t * pool