/ lib / sslAesGcmCipher.c
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  };