]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_apple_csp/lib/aescsp.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_apple_csp / lib / aescsp.cpp
diff --git a/libsecurity_apple_csp/lib/aescsp.cpp b/libsecurity_apple_csp/lib/aescsp.cpp
new file mode 100644 (file)
index 0000000..9f068b3
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+
+/*
+ * aescsp.cpp - glue between BlockCryptor and AES implementation
+ * Written by Doug Mitchell 10/3/2000
+ */
+#include "aescspi.h"
+#include "rijndaelApi.h"
+#include "rijndael-alg-ref.h"
+#include "cspdebugging.h"
+
+#define DEFAULT_BLOCK_SIZE             (MIN_AES_BLOCK_BITS / 8)
+
+/*
+ * AES symmetric key generation.
+ * This algorithm has key size restrictions which don't fit with the 
+ * standard AppleSymmKeyGenContext model so we have to do some addditional
+ * checking.
+ */
+void AESKeyGenContext::generate(
+       const Context   &context, 
+       CssmKey                 &symKey, 
+       CssmKey                 &dummyKey)
+{
+       uint32 reqKeySize = context.getInt(
+               CSSM_ATTRIBUTE_KEY_LENGTH, 
+               CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
+       switch(reqKeySize) {
+               case MIN_AES_KEY_BITS:
+               case MID_AES_KEY_BITS:
+               case MAX_AES_KEY_BITS:
+                       break;
+               default:
+                       CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
+       }
+       AppleSymmKeyGenContext::generateSymKey(
+               context, 
+               session(),
+               symKey);                
+}
+
+/*
+ * AES encrypt/decrypt.
+ */
+AESContext::~AESContext()
+{
+       deleteKey();
+       memset(mRawKey, 0, MAX_AES_KEY_BITS / 8);
+       mInitFlag = false;
+}
+       
+void AESContext::aesError(
+       int artn, 
+       const char *errStr)
+{
+       CSSM_RETURN crtn;
+       errorLog2("AESContext: %s : %d\n", errStr, artn);
+       switch(artn) {
+               case BAD_KEY_INSTANCE:
+               default:
+                       crtn = CSSMERR_CSP_INTERNAL_ERROR;
+                       break;
+               case BAD_KEY_MAT:
+                       crtn = CSSMERR_CSP_INVALID_KEY;
+                       break;
+       }
+       CssmError::throwMe(crtn);
+}
+
+void AESContext::deleteKey()
+{
+       if(mAesKey) {
+               memset(mAesKey, 0, sizeof(keyInstance));
+               session().free(mAesKey);
+               mAesKey = NULL;
+       }
+}
+
+/* 
+ * Standard CSPContext init, called from CSPFullPluginSession::init().
+ * Reusable, e.g., query followed by en/decrypt. Even reusable after context
+ * changed (i.e., new IV in Encrypted File System). 
+ */
+void AESContext::init( 
+       const Context &context, 
+       bool encrypting)
+{
+       if(mInitFlag && !opStarted()) {
+               return;
+       }
+       
+       CSSM_SIZE       keyLen;
+       uint8           *keyData = NULL;
+       unsigned        lastBlockSize = mBlockSize;             // may be 0 (first time thru)
+       bool            sameKeyAndBlockSizes = false;
+       
+       /* obtain key from context */
+       symmetricKeyBits(context, session(), CSSM_ALGID_AES, 
+               encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
+               keyData, keyLen);
+       
+       switch(keyLen) {
+               case MIN_AES_KEY_BITS / 8:
+               case MID_AES_KEY_BITS / 8:
+               case MAX_AES_KEY_BITS / 8:
+                       break;
+               default:
+                       CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
+       }
+
+       /* 
+        * Validate context 
+        * block size is optional 
+        */
+       mBlockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE);
+       if(mBlockSize == 0) {
+               mBlockSize = DEFAULT_BLOCK_SIZE;                
+       }
+               
+       
+       /*
+        * Delete existing key if key size or block size changed
+        */
+       if((lastBlockSize == mBlockSize) && (mRawKeySize == keyLen)) {
+               sameKeyAndBlockSizes = true;
+       }
+       if((mAesKey != NULL) && !sameKeyAndBlockSizes) {
+               deleteKey();
+       }
+       
+       int opt128 = 0;
+#if            !GLADMAN_AES_128_ENABLE
+       if((mBlockSize == (MIN_AES_BLOCK_BITS/8)) &&
+          (keyLen == (MIN_AES_KEY_BITS/8)) &&
+          doAES128) {
+               opt128 = 1;
+       }
+#endif /* !GLADMAN_AES_128_ENABLE */
+       
+       /* create new key if needed */
+       if(mAesKey == NULL) {
+               mAesKey = (keyInstance *)session().malloc(sizeof(keyInstance));
+       }
+       
+       /* init key only if key size, block size, or key bits have changed */
+       if(!sameKeyAndBlockSizes || memcmp(mRawKey, keyData, mRawKeySize)) {
+               int artn = makeKey((keyInstance *)mAesKey, 
+                       keyLen * 8, 
+                       mBlockSize * 8, 
+                       (word8 *)keyData,
+                       opt128);
+               if(artn < 0) {
+                       aesError(artn, "makeKey");
+               }
+               
+               /* save this raw key data */
+               memmove(mRawKey, keyData, mRawKeySize); 
+               mRawKeySize = keyLen;
+       }
+
+#if            !GLADMAN_AES_128_ENABLE
+       if(opt128) {
+               /* optimized path */
+               mEncryptFcn = rijndaelBlockEncrypt128;
+               mDecryptFcn = rijndaelBlockDecrypt128;
+       }
+       else {
+               /* common standard path */
+               mEncryptFcn = rijndaelBlockEncrypt;
+               mDecryptFcn = rijndaelBlockDecrypt;
+       }
+#else
+       /* common standard path */
+       mEncryptFcn = rijndaelBlockEncrypt;
+       mDecryptFcn = rijndaelBlockDecrypt;
+#endif /* !GLADMAN_AES_128_ENABLE */
+       
+       /* Finally, have BlockCryptor do its setup */
+       setup(mBlockSize, context);
+       mInitFlag = true;
+}      
+
+/*
+ * Functions called by BlockCryptor
+ */
+void AESContext::encryptBlock(
+       const void              *plainText,                     // length implied (one block)
+       size_t                  plainTextLen,
+       void                    *cipherText,    
+       size_t                  &cipherTextLen,         // in/out, throws on overflow
+       bool                    final)                          // ignored
+{
+       if(plainTextLen != mBlockSize) {
+               CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
+       }
+       if(cipherTextLen < mBlockSize) {
+               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
+       }
+       int artn = mEncryptFcn(mAesKey, 
+               (word8 *)plainText, 
+               (word8 *)cipherText);
+       if(artn < 0) {
+               aesError(artn, "rijndaelBlockEncrypt");
+       }
+       cipherTextLen = mBlockSize;
+}
+
+void AESContext::decryptBlock(
+       const void              *cipherText,            // length implied (one cipher block)
+       size_t                  cipherTextLen,  
+       void                    *plainText,     
+       size_t                  &plainTextLen,          // in/out, throws on overflow
+       bool                    final)                          // ignored
+{
+       if(plainTextLen < mBlockSize) {
+               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
+       }
+       int artn = mDecryptFcn(mAesKey, 
+               (word8 *)cipherText, 
+               (word8 *)plainText);
+       if(artn < 0) {
+               aesError(artn, "rijndaelBlockDecrypt");
+       }
+       plainTextLen = mBlockSize;
+}
+