sslAesGcmCipher.c
1 /* 2 * Copyright (c) 2014 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 /* THIS FILE CONTAINS KERNEL CODE */ 25 #include <tls_ciphersuites.h> 26 27 #include "sslBuildFlags.h" 28 #include "sslDebug.h" 29 #include "sslMemory.h" 30 #include "symCipher.h" 31 #include "tls_types_private.h" 32 33 #include <string.h> 34 #include <AssertMacros.h> 35 #include <stddef.h> 36 37 #include <corecrypto/ccaes.h> 38 #include <corecrypto/ccmode.h> 39 #include <corecrypto/ccrng.h> 40 41 struct SymCipherContext { 42 const struct ccmode_gcm *gcm; 43 ccgcm_ctx *gcmCtx; 44 uint8_t gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE+TLS_AES_GCM_EXPLICIT_IV_SIZE]; 45 uint8_t *key; 46 size_t keySize; 47 }; 48 49 static 50 int CCGCMSymmInit(const SSLSymmetricCipherParams *params, 51 int encrypting, 52 uint8_t *key, 53 uint8_t* iv, 54 struct ccrng_state *rng, 55 SymCipherContext *cipherCtx) 56 { 57 SymCipherContext ctx = *cipherCtx; 58 59 /* FIXME: this should not be needed as long as CCSymFinish is called */ 60 if (ctx) { 61 sslFree(ctx); 62 ctx = NULL; 63 } 64 65 const struct ccmode_gcm *gcm = encrypting ? ccaes_gcm_encrypt_mode() : ccaes_gcm_decrypt_mode(); 66 ctx = sslMalloc(sizeof(struct SymCipherContext)); 67 68 if (ctx == NULL) { 69 sslErrorLog("CCSymmInit: Can't allocate context\n"); 70 return errSSLRecordInternal; 71 } 72 73 ctx->gcm = gcm; 74 ctx->gcmCtx = sslMalloc(gcm->size); 75 76 // Generate the initial value for the implicit and explicit nonces. 77 // The initial nonce is the 4 byte packet counter and the explicit nonce 78 // is a 8 byte random value. 79 memcpy(ctx->gcmIV, iv, TLS_AES_GCM_IMPLICIT_IV_SIZE); 80 ccrng_generate(rng, TLS_AES_GCM_EXPLICIT_IV_SIZE, &ctx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE]); 81 82 // We may need to re-initialize the cipher later on (if the explicit IV changes). So, for now, we 83 // have to save the key and defer initialization until later on. 84 ctx->keySize = params->keySize; 85 ctx->key = sslMalloc(ctx->keySize); 86 memcpy(ctx->key, key, ctx->keySize); 87 88 *cipherCtx = ctx; 89 return 0; 90 } 91 92 static 93 int CCSymmAEADSetIV(const uint8_t *srcIV, 94 SymCipherContext cipherCtx) 95 { 96 int err = 0; 97 98 if (cipherCtx == NULL || cipherCtx->gcm == NULL) { 99 sslErrorLog("CCSymmAEADSetIV: NULL cipherCtx\n"); 100 return errSSLRecordInternal; 101 } 102 103 /* Save the explicit IV in our local buffer and then finish initializing the cipher, if needed. */ 104 memcpy(&cipherCtx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE], srcIV, TLS_AES_GCM_EXPLICIT_IV_SIZE); 105 err = ccgcm_init_with_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->keySize, cipherCtx->key, cipherCtx->gcmIV); 106 107 return err; 108 } 109 110 static 111 int CCSymmAEADGetIV(uint8_t *destIV, 112 SymCipherContext cipherCtx) 113 { 114 if (cipherCtx == NULL || cipherCtx->gcm == NULL) { 115 sslErrorLog("CCSymmAEADSetIV: NULL cipherCtx\n"); 116 return errSSLRecordInternal; 117 } 118 119 /* copy the explicit IV */ 120 memcpy(destIV, &cipherCtx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE], TLS_AES_GCM_EXPLICIT_IV_SIZE); 121 122 return 0; 123 } 124 125 static 126 int CCSymmAEADEncrypt(const uint8_t *src, 127 uint8_t *dest, 128 size_t len, 129 SymCipherContext cipherCtx) 130 { 131 int err = 0; 132 133 if (cipherCtx == NULL || cipherCtx->gcm == NULL) { 134 sslErrorLog("CCSymmAEADEncrypt: NULL cipherCtx\n"); 135 return errSSLRecordInternal; 136 } 137 138 err = ccgcm_update(cipherCtx->gcm, cipherCtx->gcmCtx, len-(TLS_AES_GCM_EXPLICIT_IV_SIZE+TLS_AES_GCM_TAG_SIZE), 139 src+TLS_AES_GCM_EXPLICIT_IV_SIZE, dest+TLS_AES_GCM_EXPLICIT_IV_SIZE); 140 err |= ccgcm_finalize(cipherCtx->gcm, cipherCtx->gcmCtx, TLS_AES_GCM_TAG_SIZE, &dest[len-TLS_AES_GCM_TAG_SIZE]); 141 142 /* Reset the GCM for another operation and then bump up the IV */ 143 err |= ccgcm_reset(cipherCtx->gcm, cipherCtx->gcmCtx); 144 err |= ccgcm_inc_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->gcmIV); 145 146 return err; 147 } 148 149 static 150 int CCSymmAEADDecrypt(const uint8_t *src, 151 uint8_t *dest, 152 size_t len, 153 SymCipherContext cipherCtx) 154 { 155 int err = 0; 156 157 if (cipherCtx == NULL || cipherCtx->gcm == NULL) { 158 printf("CCSymmAEADDecrypt: NULL cipherCtx\n"); 159 return -1; 160 } 161 162 /* Make a temporary copy of the tag to avoid breaking the const signature */ 163 uint8_t tagCopy[TLS_AES_GCM_TAG_SIZE]; 164 memcpy(tagCopy, &src[len-TLS_AES_GCM_TAG_SIZE], TLS_AES_GCM_TAG_SIZE); 165 166 err = ccgcm_update(cipherCtx->gcm, cipherCtx->gcmCtx, len-TLS_AES_GCM_TAG_SIZE, src, dest); 167 err |= ccgcm_finalize(cipherCtx->gcm, cipherCtx->gcmCtx, TLS_AES_GCM_TAG_SIZE, tagCopy); 168 169 /* Reset the GCM for another operation and then bump up the IV */ 170 err |= ccgcm_reset(cipherCtx->gcm, cipherCtx->gcmCtx); 171 err |= ccgcm_inc_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->gcmIV); 172 173 /* If an error occurred then scrub the plaintext destination */ 174 if (err != 0) { 175 cc_clear(len-TLS_AES_GCM_TAG_SIZE, dest); 176 } 177 178 return err; 179 } 180 181 static 182 int CCSymmAddADD(const uint8_t *src, 183 size_t len, 184 SymCipherContext cipherCtx) 185 { 186 if (cipherCtx == NULL || cipherCtx->gcm == NULL) { 187 sslErrorLog("CCSymmAddADD: NULL cipherCtx\n"); 188 return errSSLRecordInternal; 189 } 190 191 return ccgcm_gmac(cipherCtx->gcm, cipherCtx->gcmCtx, len, src); 192 } 193 194 static 195 int CCSymmFinish(SymCipherContext cipherCtx) 196 { 197 if (cipherCtx) { 198 ccgcm_ctx_clear(cipherCtx->gcm->size, cipherCtx->gcmCtx); 199 sslFree(cipherCtx->gcmCtx); 200 201 // Scrub the key from memory 202 cc_clear(cipherCtx->keySize, cipherCtx->key); 203 sslFree(cipherCtx->key); 204 205 sslFree(cipherCtx); 206 } 207 return 0; 208 } 209 210 const SSLSymmetricCipher SSLCipherAES_128_GCM = { 211 .params = &SSLCipherAES_128_GCMParams, 212 .c.aead = { 213 .initialize = CCGCMSymmInit, 214 .setIV = CCSymmAEADSetIV, 215 .getIV = CCSymmAEADGetIV, 216 .update = CCSymmAddADD, 217 .encrypt = CCSymmAEADEncrypt, 218 .decrypt = CCSymmAEADDecrypt, 219 }, 220 .finish = CCSymmFinish 221 }; 222 223 const SSLSymmetricCipher SSLCipherAES_256_GCM = { 224 .params = &SSLCipherAES_256_GCMParams, 225 .c.aead = { 226 .initialize = CCGCMSymmInit, 227 .setIV = CCSymmAEADSetIV, 228 .getIV = CCSymmAEADGetIV, 229 .update = CCSymmAddADD, 230 .encrypt = CCSymmAEADEncrypt, 231 .decrypt = CCSymmAEADDecrypt, 232 }, 233 .finish = CCSymmFinish 234 };