1/*
2 * Copyright (c) 2012 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// #define COMMON_GCM_FUNCTIONS
25#include "ccMemory.h"
26#include "ccdebug.h"
27#include "CommonCryptor.h"
28#include "CommonCryptorSPI.h"
29#include "CommonCryptorPriv.h"
30#include <corecrypto/ccmode_factory.h>
31
32
33CCCryptorStatus
34CCCryptorGCMAddIV(CCCryptorRef cryptorRef,
35                	const void 		*iv,
36                    size_t ivLen)
37{
38    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
39    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
40    if(!cryptor) return kCCParamError;
41    ccmode_gcm_set_iv(cryptor->ctx[cryptor->op].gcm, ivLen, iv);
42 	return kCCSuccess;
43}
44
45
46CCCryptorStatus
47CCCryptorGCMAddAAD(CCCryptorRef cryptorRef,
48                	const void 		*aData,
49                    size_t aDataLen)
50{
51    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
52    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
53    if(!cryptor) return kCCParamError;
54    ccmode_gcm_gmac(cryptor->ctx[cryptor->op].gcm, aDataLen, aData);
55 	return kCCSuccess;
56}
57
58// This is for old iOS5 clients
59CCCryptorStatus
60CCCryptorGCMAddADD(CCCryptorRef cryptorRef,
61                   const void 		*aData,
62                   size_t aDataLen)
63{
64    return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
65}
66
67// This was a temp mistake in MacOSX8
68CCCryptorStatus
69CCCryptorGCMaddAAD(CCCryptorRef cryptorRef,
70                   const void 		*aData,
71                   size_t aDataLen)
72{
73    return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
74}
75
76
77
78CCCryptorStatus CCCryptorGCMEncrypt(
79	CCCryptorRef cryptorRef,
80	const void *dataIn,
81	size_t dataInLength,
82	void *dataOut)
83{
84    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
85    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
86    if(!cryptor) return kCCParamError;
87    if(dataIn == NULL || dataOut == NULL) return kCCParamError;
88    ccmode_gcm_encrypt(cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut);
89 	return kCCSuccess;
90}
91
92
93
94CCCryptorStatus CCCryptorGCMDecrypt(
95	CCCryptorRef cryptorRef,
96	const void *dataIn,
97	size_t dataInLength,
98	void *dataOut)
99{
100    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
101    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
102    if(!cryptor) return kCCParamError;
103    if(dataIn == NULL || dataOut == NULL) return kCCParamError;
104    ccmode_gcm_decrypt(cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut);
105 	return kCCSuccess;
106}
107
108
109
110CCCryptorStatus CCCryptorGCMFinal(
111	CCCryptorRef cryptorRef,
112	const void *tag,
113	size_t *tagLength)
114{
115    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
116    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
117    if(!cryptor) return kCCParamError;
118	if(tag == NULL || tagLength == NULL)  return kCCParamError;
119    ccmode_gcm_finalize(cryptor->ctx[cryptor->op].gcm, *tagLength, (void *)tag);
120 	return kCCSuccess;
121}
122
123
124
125CCCryptorStatus CCCryptorGCMReset(
126	CCCryptorRef cryptorRef)
127{
128    CCCryptor   *cryptor = getRealCryptor(cryptorRef, 0);
129    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
130    if(!cryptor) return kCCParamError;
131    ccmode_gcm_reset(cryptor->ctx[cryptor->op].gcm);
132 	return kCCSuccess;
133}
134
135
136
137CCCryptorStatus CCCryptorGCM(
138	CCOperation 	op,				/* kCCEncrypt, kCCDecrypt */
139	CCAlgorithm		alg,
140	const void 		*key,			/* raw key material */
141	size_t 			keyLength,
142	const void 		*iv,
143	size_t 			ivLen,
144	const void 		*aData,
145	size_t 			aDataLen,
146	const void 		*dataIn,
147	size_t 			dataInLength,
148  	void 			*dataOut,
149	const void 		*tag,
150	size_t 			*tagLength)
151{
152    CCCryptorRef cryptorRef;
153    CCCryptorStatus retval;
154
155    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Op: %d Cipher: %d\n", op, alg);
156
157    retval = CCCryptorCreateWithMode(op, kCCModeGCM, alg, 0, NULL, key, keyLength,
158                                         NULL, 0, 0, 0, &cryptorRef);
159    if(retval) return retval;
160
161    // IV is optional
162    if(ivLen) {
163        retval = CCCryptorGCMAddIV(cryptorRef, iv, ivLen);
164        if(retval) return retval;
165    }
166
167    // This must always be called - even with no aData.
168    retval = CCCryptorGCMaddAAD(cryptorRef, aData, aDataLen);
169    if(retval) return retval;
170
171    if(op == kCCEncrypt)
172        retval = CCCryptorGCMEncrypt(cryptorRef, dataIn, dataInLength, dataOut);
173    else if(op == kCCDecrypt)
174        retval = CCCryptorGCMDecrypt(cryptorRef, dataIn, dataInLength, dataOut);
175    else return kCCParamError;
176    if(retval) return retval;
177
178    retval = CCCryptorGCMFinal(cryptorRef, tag, tagLength);
179    CCCryptorRelease(cryptorRef);
180
181    return retval;
182}
183
184
185