Apache HTTPD
apr_crypto_commoncrypto.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.h"
18#include "apr_lib.h"
19#include "apu.h"
20#include "apu_errno.h"
21
22#include <ctype.h>
23#include <assert.h>
24#include <stdlib.h>
25
26#include "apr_strings.h"
27#include "apr_time.h"
28#include "apr_buckets.h"
29#include "apr_random.h"
30
31#include "apr_crypto_internal.h"
32
33#if APU_HAVE_CRYPTO
34
35#include <CommonCrypto/CommonCrypto.h>
36
37#define LOG_PREFIX "apr_crypto_commoncrypto: "
38
39struct apr_crypto_t
40{
42 const apr_crypto_driver_t *provider;
47};
48
50{
52 const apr_crypto_driver_t *provider;
53 const apr_crypto_t *f;
54 CCAlgorithm algorithm;
55 CCOptions options;
56 unsigned char *key;
57 int keyLen;
58 int ivSize;
60};
61
63{
65 const apr_crypto_driver_t *provider;
66 const apr_crypto_t *f;
67 const apr_crypto_key_t *key;
68 CCCryptorRef ref;
69};
70
72{
73{ APR_KEY_3DES_192, 24, 8, 8 },
74{ APR_KEY_AES_128, 16, 16, 16 },
75{ APR_KEY_AES_192, 24, 16, 16 },
76{ APR_KEY_AES_256, 32, 16, 16 } };
77
79{
80{ APR_MODE_ECB },
81{ APR_MODE_CBC } };
82
87 const apr_crypto_t *f)
88{
89 *result = f->result;
90 return APR_SUCCESS;
91}
92
97{
98 return APR_SUCCESS;
99}
100
102{
103 return crypto_shutdown();
104}
105
109static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
110 const apu_err_t **result)
111{
112
115
116 return APR_SUCCESS;
117}
118
126{
127
128 if (ctx->ref) {
129 CCCryptorRelease(ctx->ref);
130 ctx->ref = NULL;
131 }
132
133 return APR_SUCCESS;
134
135}
136
138{
141}
142
150{
151
152 return APR_SUCCESS;
153
154}
155
157{
159 return crypto_cleanup(f);
160}
161
175 const apr_crypto_driver_t *provider, const char *params,
177{
179 apr_status_t rv;
180
181 if (!f) {
182 return APR_ENOMEM;
183 }
184 *ff = f;
185 f->pool = pool;
186 f->provider = provider;
187
188 /* seed the secure random number generator */
190 if (!f->rng) {
191 return APR_ENOMEM;
192 }
193 do {
194 unsigned char seed[8];
195 rv = apr_generate_random_bytes(seed, sizeof(seed));
196 if (rv != APR_SUCCESS) {
197 return rv;
198 }
199 apr_random_add_entropy(f->rng, seed, sizeof(seed));
200 rv = apr_random_secure_ready(f->rng);
201 } while (rv == APR_ENOTENOUGHENTROPY);
202
203 f->result = apr_pcalloc(pool, sizeof(apu_err_t));
204 if (!f->result) {
205 return APR_ENOMEM;
206 }
207
208 f->types = apr_hash_make(pool);
209 if (!f->types) {
210 return APR_ENOMEM;
211 }
212 apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
213 apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
214 apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
215 apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
216
217 f->modes = apr_hash_make(pool);
218 if (!f->modes) {
219 return APR_ENOMEM;
220 }
221 apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
222 apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
223
226
227 return APR_SUCCESS;
228
229}
230
240 const apr_crypto_t *f)
241{
242 *types = f->types;
243 return APR_SUCCESS;
244}
245
255 const apr_crypto_t *f)
256{
257 *modes = f->modes;
258 return APR_SUCCESS;
259}
260
261/*
262 * Work out which mechanism to use.
263 */
267{
268 /* handle padding */
269 key->options = doPad ? kCCOptionPKCS7Padding : 0;
270
271 /* determine the algorithm to be used */
272 switch (type) {
273
274 case (APR_KEY_3DES_192):
275
276 /* A 3DES key */
277 if (mode == APR_MODE_CBC) {
278 key->algorithm = kCCAlgorithm3DES;
279 key->keyLen = kCCKeySize3DES;
280 key->ivSize = kCCBlockSize3DES;
281 key->blockSize = kCCBlockSize3DES;
282 }
283 else {
284 key->algorithm = kCCAlgorithm3DES;
285 key->options += kCCOptionECBMode;
286 key->keyLen = kCCKeySize3DES;
287 key->ivSize = 0;
288 key->blockSize = kCCBlockSize3DES;
289 }
290 break;
291
292 case (APR_KEY_AES_128):
293
294 if (mode == APR_MODE_CBC) {
295 key->algorithm = kCCAlgorithmAES128;
296 key->keyLen = kCCKeySizeAES128;
297 key->ivSize = kCCBlockSizeAES128;
298 key->blockSize = kCCBlockSizeAES128;
299 }
300 else {
301 key->algorithm = kCCAlgorithmAES128;
302 key->options += kCCOptionECBMode;
303 key->keyLen = kCCKeySizeAES128;
304 key->ivSize = 0;
305 key->blockSize = kCCBlockSizeAES128;
306 }
307 break;
308
309 case (APR_KEY_AES_192):
310
311 if (mode == APR_MODE_CBC) {
312 key->algorithm = kCCAlgorithmAES128;
313 key->keyLen = kCCKeySizeAES192;
314 key->ivSize = kCCBlockSizeAES128;
315 key->blockSize = kCCBlockSizeAES128;
316 }
317 else {
318 key->algorithm = kCCAlgorithmAES128;
319 key->options += kCCOptionECBMode;
320 key->keyLen = kCCKeySizeAES192;
321 key->ivSize = 0;
322 key->blockSize = kCCBlockSizeAES128;
323 }
324 break;
325
326 case (APR_KEY_AES_256):
327
328 if (mode == APR_MODE_CBC) {
329 key->algorithm = kCCAlgorithmAES128;
330 key->keyLen = kCCKeySizeAES256;
331 key->ivSize = kCCBlockSizeAES128;
332 key->blockSize = kCCBlockSizeAES128;
333 }
334 else {
335 key->algorithm = kCCAlgorithmAES128;
336 key->options += kCCOptionECBMode;
337 key->keyLen = kCCKeySizeAES256;
338 key->ivSize = 0;
339 key->blockSize = kCCBlockSizeAES128;
340 }
341 break;
342
343 default:
344
345 /* TODO: Support CAST, Blowfish */
346
347 /* unknown key type, give up */
348 return APR_EKEYTYPE;
349
350 }
351
352 /* make space for the key */
353 key->key = apr_palloc(p, key->keyLen);
354 if (!key->key) {
355 return APR_ENOMEM;
356 }
357 apr_crypto_clear(p, key->key, key->keyLen);
358
359 return APR_SUCCESS;
360}
361
380{
381 apr_status_t rv;
382 apr_crypto_key_t *key = *k;
383
384 if (!key) {
385 *k = key = apr_pcalloc(p, sizeof *key);
386 }
387 if (!key) {
388 return APR_ENOMEM;
389 }
390
391 key->f = f;
392 key->provider = f->provider;
393
394 /* decide on what cipher mechanism we will be using */
395 rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
396 if (APR_SUCCESS != rv) {
397 return rv;
398 }
399
400 switch (rec->ktype) {
401
403
404 /* generate the key */
405 if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2,
406 rec->k.passphrase.pass, rec->k.passphrase.passLen,
407 rec->k.passphrase.salt, rec->k.passphrase.saltLen,
408 kCCPRFHmacAlgSHA1, rec->k.passphrase.iterations, key->key,
409 key->keyLen)) == kCCParamError) {
410 return APR_ENOKEY;
411 }
412
413 break;
414 }
415
417
418 /* sanity check - key correct size? */
419 if (rec->k.secret.secretLen != key->keyLen) {
420 return APR_EKEYLENGTH;
421 }
422
423 /* copy the key */
424 memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
425
426 break;
427 }
428
429 default: {
430
431 return APR_ENOKEY;
432
433 }
434 }
435
436 return APR_SUCCESS;
437}
438
468 const char *pass, apr_size_t passLen, const unsigned char * salt,
470 const apr_crypto_block_key_mode_e mode, const int doPad,
471 const int iterations, const apr_crypto_t *f, apr_pool_t *p)
472{
473 apr_status_t rv;
474 apr_crypto_key_t *key = *k;
475
476 if (!key) {
477 *k = key = apr_pcalloc(p, sizeof *key);
478 if (!key) {
479 return APR_ENOMEM;
480 }
481 }
482
483 key->f = f;
484 key->provider = f->provider;
485
486 /* decide on what cipher mechanism we will be using */
488 if (APR_SUCCESS != rv) {
489 return rv;
490 }
491
492 /* generate the key */
493 if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2, pass, passLen, salt,
494 saltLen, kCCPRFHmacAlgSHA1, iterations, key->key, key->keyLen))
495 == kCCParamError) {
496 return APR_ENOKEY;
497 }
498
499 if (ivSize) {
500 *ivSize = key->ivSize;
501 }
502
503 return APR_SUCCESS;
504}
505
523 const unsigned char **iv, const apr_crypto_key_t *key,
525{
526 unsigned char *usedIv;
528 if (!block) {
530 }
531 if (!block) {
532 return APR_ENOMEM;
533 }
534 block->f = key->f;
535 block->pool = p;
536 block->provider = key->provider;
537 block->key = key;
538
541
542 /* generate an IV, if necessary */
543 usedIv = NULL;
544 if (key->ivSize) {
545 if (iv == NULL) {
546 return APR_ENOIV;
547 }
548 if (*iv == NULL) {
550 usedIv = apr_pcalloc(p, key->ivSize);
551 if (!usedIv) {
552 return APR_ENOMEM;
553 }
554 apr_crypto_clear(p, usedIv, key->ivSize);
556 key->ivSize);
557 if (APR_SUCCESS != status) {
558 return status;
559 }
560 *iv = usedIv;
561 }
562 else {
563 usedIv = (unsigned char *) *iv;
564 }
565 }
566
567 /* create a new context for encryption */
568 switch ((block->f->result->rc = CCCryptorCreate(kCCEncrypt, key->algorithm,
569 key->options, key->key, key->keyLen, usedIv, &block->ref))) {
570 case kCCSuccess: {
571 break;
572 }
573 case kCCParamError: {
574 return APR_EINIT;
575 }
576 case kCCMemoryFailure: {
577 return APR_ENOMEM;
578 }
579 case kCCAlignmentError: {
580 return APR_EPADDING;
581 }
582 case kCCUnimplemented: {
583 return APR_ENOTIMPL;
584 }
585 default: {
586 return APR_EINIT;
587 }
588 }
589
590 if (blockSize) {
591 *blockSize = key->blockSize;
592 }
593
594 return APR_SUCCESS;
595
596}
597
616static apr_status_t crypto_block_encrypt(unsigned char **out,
617 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
619{
621 unsigned char *buffer;
622
623 /* are we after the maximum size of the out buffer? */
624 if (!out) {
626 return APR_SUCCESS;
627 }
628
629 /* must we allocate the output buffer from a pool? */
630 if (!*out) {
632 buffer = apr_palloc(ctx->pool, outl);
633 if (!buffer) {
634 return APR_ENOMEM;
635 }
637 *out = buffer;
638 }
639
640 switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
641 outl, &outl))) {
642 case kCCSuccess: {
643 break;
644 }
645 case kCCBufferTooSmall: {
646 return APR_ENOSPACE;
647 }
648 default: {
649 return APR_ECRYPT;
650 }
651 }
652 *outlen = outl;
653
654 return APR_SUCCESS;
655
656}
657
676static apr_status_t crypto_block_encrypt_finish(unsigned char *out,
678{
680
681 ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
682 CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
683
684 /* always clean up */
686
687 switch (ctx->f->result->rc) {
688 case kCCSuccess: {
689 break;
690 }
691 case kCCBufferTooSmall: {
692 return APR_ENOSPACE;
693 }
694 case kCCAlignmentError: {
695 return APR_EPADDING;
696 }
697 case kCCDecodeError: {
698 return APR_ECRYPT;
699 }
700 default: {
701 return APR_ECRYPT;
702 }
703 }
704 *outlen = len;
705
706 return APR_SUCCESS;
707
708}
709
726 apr_size_t *blockSize, const unsigned char *iv,
728{
730 if (!block) {
732 }
733 if (!block) {
734 return APR_ENOMEM;
735 }
736 block->f = key->f;
737 block->pool = p;
738 block->provider = key->provider;
739
742
743 /* generate an IV, if necessary */
744 if (key->ivSize) {
745 if (iv == NULL) {
746 return APR_ENOIV;
747 }
748 }
749
750 /* create a new context for decryption */
751 switch ((block->f->result->rc = CCCryptorCreate(kCCDecrypt, key->algorithm,
752 key->options, key->key, key->keyLen, iv, &block->ref))) {
753 case kCCSuccess: {
754 break;
755 }
756 case kCCParamError: {
757 return APR_EINIT;
758 }
759 case kCCMemoryFailure: {
760 return APR_ENOMEM;
761 }
762 case kCCAlignmentError: {
763 return APR_EPADDING;
764 }
765 case kCCUnimplemented: {
766 return APR_ENOTIMPL;
767 }
768 default: {
769 return APR_EINIT;
770 }
771 }
772
773 if (blockSize) {
774 *blockSize = key->blockSize;
775 }
776
777 return APR_SUCCESS;
778
779}
780
799static apr_status_t crypto_block_decrypt(unsigned char **out,
800 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
802{
804 unsigned char *buffer;
805
806 /* are we after the maximum size of the out buffer? */
807 if (!out) {
809 return APR_SUCCESS;
810 }
811
812 /* must we allocate the output buffer from a pool? */
813 if (!*out) {
815 buffer = apr_palloc(ctx->pool, outl);
816 if (!buffer) {
817 return APR_ENOMEM;
818 }
820 *out = buffer;
821 }
822
823 switch ((ctx->f->result->rc = CCCryptorUpdate(ctx->ref, in, inlen, (*out),
824 outl, &outl))) {
825 case kCCSuccess: {
826 break;
827 }
828 case kCCBufferTooSmall: {
829 return APR_ENOSPACE;
830 }
831 default: {
832 return APR_ECRYPT;
833 }
834 }
835 *outlen = outl;
836
837 return APR_SUCCESS;
838
839}
840
859static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
861{
863
864 ctx->f->result->rc = CCCryptorFinal(ctx->ref, out,
865 CCCryptorGetOutputLength(ctx->ref, 0, 1), &len);
866
867 /* always clean up */
869
870 switch (ctx->f->result->rc) {
871 case kCCSuccess: {
872 break;
873 }
874 case kCCBufferTooSmall: {
875 return APR_ENOSPACE;
876 }
877 case kCCAlignmentError: {
878 return APR_EPADDING;
879 }
880 case kCCDecodeError: {
881 return APR_ECRYPT;
882 }
883 default: {
884 return APR_ECRYPT;
885 }
886 }
887 *outlen = len;
888
889 return APR_SUCCESS;
890
891}
892
897{
904};
905
906#endif
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
APR general purpose library routines.
APR PRNG routines.
APR Strings library.
APR Time Library.
APR-Util Error Codes.
static apr_random_t * rng
Definition core.c:5392
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EINIT
Definition apr_errno.h:474
#define APR_ENOTENOUGHENTROPY
Definition apr_errno.h:340
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_EKEYLENGTH
Definition apu_errno.h:75
#define APR_ENOKEY
Definition apu_errno.h:63
#define APR_EPADDING
Definition apu_errno.h:73
#define APR_ENOSPACE
Definition apu_errno.h:69
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#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
#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
static const char * key_types[]
apr_pool_t * pool