1/*
2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include "ossl-config.h"
25
26#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
27
28#include <sys/types.h>
29
30#include <assert.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <CommonCrypto/CommonCryptor.h>
36
37#include "ossl-aes.h"
38
39/*
40 * CommonCrypto shims for OSSL AES lowlevel API
41 */
42static int
43_AES_set_key(int enc, const unsigned char *userKey, const int bits,
44    AES_KEY *key)
45{
46	CCCryptorStatus status;
47	size_t keysize = (size_t)(bits / 8);
48
49	if (!userKey || !key) {
50		return (-1);
51	}
52
53	if ((keysize < kCCKeySizeAES128) || (keysize > kCCKeySizeAES256)) {
54		return (-2);
55	}
56
57	/*
58	 * XXX The headerdoc for CCCryptorCreateFromData() claims to "Create
59	 * a cryptographic context using caller-supplied memory" and that
60	 * calling CCCryptorRelease() "is not strictly necessary".  Unfortunately,
61	 * this is incorrect.  CCCryptorCreateFromData() allocates 4K of memory
62	 * that will never be release unless CCCryptorRelease() is called.
63	 * See <rdr://problem/10867937>.
64	 */
65	status = CCCryptorCreateFromData(enc, kCCAlgorithmAES128,
66		kCCOptionECBMode, (const void *)userKey, keysize, NULL,
67		key->data, AES_KEYST_SIZE, &key->cref, NULL);
68	if (status != kCCSuccess) {
69		return (-3);
70	}
71
72	return (0);
73}
74
75/*
76 * XXX Unfortunately CCCryptorCreateFromData() still allocates memory even passing
77 * it a buffer to use.  Therefore, we need to explicitly free that memory by calling
78 * CCCryptorRelease().  Also see the comment above and <rdr://problem/10867937>.
79 */
80void
81AES_destroy_ctx(AES_KEY *key)
82{
83	if (key && key->cref) {
84		CCCryptorRelease(key->cref);
85		key->cref = NULL;
86	}
87}
88
89int
90AES_set_encrypt_key(const unsigned char *userKey, const int bits,
91    AES_KEY *key)
92{
93	return (_AES_set_key(kCCEncrypt, userKey, bits, key));
94}
95
96int
97AES_set_decrypt_key(const unsigned char *userKey, const int bits,
98    AES_KEY *key)
99{
100	return (_AES_set_key(kCCDecrypt, userKey, bits, key));
101}
102
103
104void
105AES_encrypt(const unsigned char *in, unsigned char *out,
106    const AES_KEY *key)
107{
108	(void)CCCryptorUpdate(key->cref, (const void *)in, kCCBlockSizeAES128,
109	    (void *)out, kCCBlockSizeAES128, NULL);
110}
111
112
113void
114AES_decrypt(const unsigned char *in, unsigned char *out,
115    const AES_KEY *key)
116{
117	(void)CCCryptorUpdate(key->cref, (const void *)in, kCCBlockSizeAES128,
118	    (void *)out, kCCBlockSizeAES128, NULL);
119}
120
121#endif  /* HAVE_COMMONCRYPTO_COMMONCRYPTOR_H */
122