]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/SecWrappedKeys.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / SecWrappedKeys.cpp
diff --git a/Security/libsecurity_keychain/lib/SecWrappedKeys.cpp b/Security/libsecurity_keychain/lib/SecWrappedKeys.cpp
deleted file mode 100644 (file)
index e42f34c..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The 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.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * SecWrappedKeys.cpp - SecExportRep and SecImportRep methods dealing with 
- *             wrapped private keys (other than PKCS8 format).
- */
-
-#include "SecExternalRep.h"
-#include "SecImportExportUtils.h"
-#include "SecImportExportPem.h"
-#include "SecImportExportCrypto.h"
-#include <Security/cssmtype.h>
-#include <Security/cssmapi.h>
-#include <Security/SecKeyPriv.h>
-#include <security_asn1/SecNssCoder.h>
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <security_utilities/devrandom.h>
-
-#include <assert.h>
-
-using namespace Security;
-using namespace KeychainCore;
-
-static int hexToDigit(
-       char digit,
-       uint8 *rtn)             // RETURNED
-{
-       if((digit >= '0') && (digit <= '9')) {
-               *rtn = digit - '0';
-               return 0;
-       }
-       if((digit >= 'a') && (digit <= 'f')) {
-               *rtn = digit - 'a' + 10;
-               return 0;
-       }
-       if((digit >= 'A') && (digit <= 'F')) {
-               *rtn = digit - 'A' + 10;
-               return 0;
-       }
-       return -1;
-}
-
-/* 
- * Convert two ascii characters starting at cp to an unsigned char.
- * Returns nonzero on error.
- */
-static int hexToUchar(
-       const char *cp,
-       uint8 *rtn)             // RETURNED
-{
-       uint8 rtnc = 0;
-       uint8 c;
-       if(hexToDigit(*cp++, &c)) {
-               return -1;
-       }
-       rtnc = c << 4;
-       if(hexToDigit(*cp, &c)) {
-               return -1;
-       }
-       rtnc |= c;
-       *rtn = rtnc;
-       return 0;
-}
-
-/*
- * Given an array of PEM parameter lines, infer parameters for key derivation and 
- * encryption.
- */
-static OSStatus opensslPbeParams(
-       CFArrayRef                      paramLines,                     // elements are CFStrings
-       SecNssCoder                     &coder,                         // IV allocd with this
-       /* remaining arguments RETURNED */
-       CSSM_ALGORITHMS         &pbeAlg,
-       CSSM_ALGORITHMS         &keyAlg,
-       CSSM_ALGORITHMS         &encrAlg,
-       CSSM_ENCRYPT_MODE       &encrMode,
-       CSSM_PADDING            &encrPad,
-       uint32                          &keySizeInBits,
-       unsigned                        &blockSizeInBytes,
-       CSSM_DATA                       &iv)
-{
-       /* 
-        * This format requires PEM parameter lines. We could have gotten here
-        * without them if caller specified wrong format.
-        */
-        if(paramLines == NULL) {
-               SecImpExpDbg("importWrappedKeyOpenssl: no PEM parameter lines");
-               return errSecUnknownFormat;
-        }
-        CFStringRef dekInfo = NULL;
-        CFIndex numLines = CFArrayGetCount(paramLines);
-        for(CFIndex dex=0; dex<numLines; dex++) {
-               CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(paramLines, dex);
-               CFRange range;
-               range = CFStringFind(str, CFSTR("DEK-Info: "), 0);
-               if(range.length != 0) {
-                       dekInfo = str;
-                       break;
-               }
-        }
-        if(dekInfo == NULL) {
-               SecImpExpDbg("importWrappedKeyOpenssl: no DEK-Info lines");
-               return errSecUnknownFormat;
-        }
-        
-        /* drop down to C strings for low level grunging */
-        char cstr[1024];
-        if(!CFStringGetCString(dekInfo, cstr, sizeof(cstr), kCFStringEncodingASCII)) {
-               SecImpExpDbg("importWrappedKeyOpenssl: bad DEK-Info line (1)");
-               return errSecUnknownFormat;
-        }
-        
-       /* 
-        * This line looks like this:
-        * DEK-Info: DES-CBC,A22977A0A6A6F696
-        * 
-        * Now parse, getting the cipher spec and the IV.
-        */
-       char *cp = strchr(cstr, ':');
-       if(cp == NULL) {
-               SecImpExpDbg("importWrappedKeyOpenssl: bad DEK-Info line (2)");
-               return errSecUnknownFormat;
-       }
-       if((cp[1] == ' ') && (cp[2] != '\0')) {
-               /* as it normally does... */
-               cp += 2;
-       }
-       
-       /* We only support DES and 3DES here */
-       if(!strncmp(cp, "DES-EDE3-CBC", 12)) {
-               keyAlg = CSSM_ALGID_3DES_3KEY;
-               encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
-               keySizeInBits = 64 * 3;
-               blockSizeInBytes = 8;
-       }
-       else if(!strncmp(cp, "DES-CBC", 7)) {
-               keyAlg = CSSM_ALGID_DES;
-               encrAlg = CSSM_ALGID_DES;
-               keySizeInBits = 64;
-               blockSizeInBytes = 8;
-       }
-       else {
-               SecImpExpDbg("importWrappedKeyOpenssl: unrecognized wrap alg (%s)",
-                       cp);
-               return errSecUnknownFormat;
-       }
-
-       /* these are more or less fixed */
-       pbeAlg   = CSSM_ALGID_PBE_OPENSSL_MD5;
-       encrMode = CSSM_ALGMODE_CBCPadIV8;
-       encrPad  = CSSM_PADDING_PKCS7;
-       
-       /* now get the ASCII hex version of the IV */
-       cp = strchr(cp, ',');
-       if(cp == NULL) {
-               SecImpExpDbg("importWrappedKeyOpenssl: No IV in DEK-Info line");
-               return errSecUnknownFormat;
-       }
-       if(cp[1] != '\0') {
-               cp++;
-       }
-       
-       /* remainder should be just the IV */
-       if(strlen(cp) != (blockSizeInBytes * 2)) {
-               SecImpExpDbg("importWrappedKeyOpenssl: bad IV in DEK-Info line (1)");
-               return errSecUnknownFormat;
-       }
-       
-       coder.allocItem(iv, blockSizeInBytes);
-       for(unsigned dex=0; dex<blockSizeInBytes; dex++) {
-               if(hexToUchar(cp + (dex * 2), &iv.Data[dex])) {
-                       SecImpExpDbg("importWrappedKeyOpenssl: bad IV in DEK-Info line (2)");
-                       return errSecUnknownFormat;
-               }
-       }
-       return errSecSuccess;
-}
-
-/* 
- * Common code to derive an openssl-wrap style wrap/unwrap key.
- */
-static OSStatus deriveKeyOpensslWrap(
-       const SecKeyImportExportParameters      *keyParams,             // required 
-       CSSM_CSP_HANDLE                                         cspHand,                // required
-       impExpVerifyPhrase                                      vp,                             // import/export
-       CSSM_ALGORITHMS                                         pbeAlg,
-       CSSM_ALGORITHMS                                         keyAlg,
-       uint32                                                          keySizeInBits,
-       const CSSM_DATA                                         &salt,  
-       CSSM_KEY_PTR                                            derivedKey)
-{
-       CFDataRef       cfPhrase = NULL;
-       CSSM_KEY        *passKey = NULL;
-       OSStatus        ortn;
-       
-       /* passphrase or passkey? */
-       ortn = impExpPassphraseCommon(keyParams, cspHand, SPF_Data, vp,
-               (CFTypeRef *)&cfPhrase, &passKey);
-       if(ortn) {
-               return ortn;
-       }
-       /* subsequent errors to errOut: */
-
-       CSSM_CRYPTO_DATA                seed;
-       CSSM_CC_HANDLE                  ccHand = 0;
-       CSSM_ACCESS_CREDENTIALS creds;
-       SecNssCoder                             coder;
-       CSSM_DATA                               param = {0, NULL};
-       CSSM_DATA                               dummyLabel;
-       
-       memset(&seed, 0, sizeof(seed));
-       if(cfPhrase != NULL) {
-               size_t len = CFDataGetLength(cfPhrase);
-               coder.allocItem(seed.Param, len);
-               memmove(seed.Param.Data, CFDataGetBytePtr(cfPhrase), len);
-               CFRelease(cfPhrase);
-       }
-
-       memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-       ortn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
-               pbeAlg,
-               keyAlg,
-               keySizeInBits,
-               &creds,
-               passKey,                                // BaseKey
-               1,                                              // iterCount - yup, this is what openssl does
-               &salt,
-               &seed,  
-               &ccHand);
-       if(ortn) {
-               SecImpExpDbg("deriveKeyOpensslWrap: CSSM_CSP_CreateDeriveKeyContext error");
-               goto errOut;
-       }
-       
-       memset(derivedKey, 0, sizeof(CSSM_KEY));
-
-       dummyLabel.Data = (uint8 *)"temp unwrap key";
-       dummyLabel.Length = strlen((char *)dummyLabel.Data);
-       
-       ortn = CSSM_DeriveKey(ccHand,
-               &param,                                 // i.e., derived IV - don't want one
-               CSSM_KEYUSE_ANY,
-               /* not extractable even for the short time this key lives */
-               CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
-               &dummyLabel,
-               NULL,                   // cred and acl
-               derivedKey);
-       if(ortn) {
-               SecImpExpDbg("importWrappedKeyOpenssl: PKCS5 v1.5 CSSM_DeriveKey failure");
-       }
-       
-errOut:
-       if(ccHand != 0) {
-               CSSM_DeleteContext(ccHand);
-       }
-       if(passKey != NULL) {
-               CSSM_FreeKey(cspHand, NULL, passKey, CSSM_FALSE);
-               free(passKey);
-       }
-       return ortn;
-}
-
-OSStatus SecImportRep::importWrappedKeyOpenssl(
-       SecKeychainRef                                          importKeychain, // optional
-       CSSM_CSP_HANDLE                                         cspHand,                // required
-       SecItemImportExportFlags                        flags,
-       const SecKeyImportExportParameters      *keyParams,             // optional 
-       CFMutableArrayRef                                       outArray)               // optional, append here 
-{
-       assert(mExternFormat == kSecFormatWrappedOpenSSL);
-       
-       /* I think this is an assert - only private keys are wrapped in opensssl format */
-       assert(mExternType == kSecItemTypePrivateKey);
-       assert(cspHand != 0);
-       
-       if(keyParams == NULL) {
-               return errSecParam;
-       }
-       
-       OSStatus                                ortn;
-       SecNssCoder                             coder;
-       impExpKeyUnwrapParams   unwrapParams;
-       CSSM_ALGORITHMS                 pbeAlg = CSSM_ALGID_NONE;
-       CSSM_ALGORITHMS                 keyAlg = CSSM_ALGID_NONE;
-       uint32                                  keySizeInBits;
-       unsigned                                blockSizeInBytes;
-
-       memset(&unwrapParams, 0, sizeof(unwrapParams));
-
-       /* parse PEM header lines */
-       ortn = opensslPbeParams(mPemParamLines, coder,
-               pbeAlg, keyAlg, 
-               unwrapParams.encrAlg, 
-               unwrapParams.encrMode,
-               unwrapParams.encrPad, 
-               keySizeInBits, 
-               blockSizeInBytes, 
-               unwrapParams.iv);
-       if(ortn) {
-               return ortn;
-       }
-       
-       /* derive unwrapping key */
-       CSSM_KEY unwrappingKey;
-       
-       ortn = deriveKeyOpensslWrap(keyParams, cspHand, VP_Import, pbeAlg, keyAlg, 
-               keySizeInBits, 
-               unwrapParams.iv,                /* salt = IV for these algs */
-               &unwrappingKey);
-       if(ortn) {
-               return ortn;
-       }
-       
-       /* set up key to unwrap */
-       CSSM_KEY                                wrappedKey;
-       CSSM_KEYHEADER                  &hdr = wrappedKey.KeyHeader;
-       memset(&wrappedKey, 0, sizeof(CSSM_KEY));
-       hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
-       /* CspId : don't care */
-       hdr.BlobType = CSSM_KEYBLOB_WRAPPED;
-       hdr.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL;
-       hdr.AlgorithmId = mKeyAlg;
-       hdr.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
-       /* LogicalKeySizeInBits : calculated by CSP during unwrap */
-       hdr.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
-       hdr.KeyUsage = CSSM_KEYUSE_ANY;
-
-       wrappedKey.KeyData.Data = (uint8 *)CFDataGetBytePtr(mExternal);
-       wrappedKey.KeyData.Length = CFDataGetLength(mExternal);
-       
-       unwrapParams.unwrappingKey = &unwrappingKey;
-       
-       /* GO */
-       ortn =  impExpImportKeyCommon(&wrappedKey, importKeychain, cspHand,
-               flags, keyParams, &unwrapParams, NULL, outArray);
-               
-       if(unwrappingKey.KeyData.Data != NULL) {
-               CSSM_FreeKey(cspHand, NULL, &unwrappingKey, CSSM_FALSE);
-       }
-       return ortn;
-}
-
-/*
- * Hard coded parameters for export, we only do one flavor.
- */
-#define OPENSSL_WRAP_KEY_ALG   CSSM_ALGID_3DES_3KEY
-#define OPENSSL_WRAP_PBE_ALG   CSSM_ALGID_PBE_OPENSSL_MD5
-#define OPENSSL_WRAP_KEY_SIZE   (64 * 3)
-#define OPENSSL_WRAP_ENCR_ALG   CSSM_ALGID_3DES_3KEY_EDE
-#define OPENSSL_WRAP_ENCR_MODE  CSSM_ALGMODE_CBCPadIV8
-#define OPENSSL_WRAP_ENCR_PAD   CSSM_PADDING_PKCS7
-
-OSStatus impExpWrappedKeyOpenSslExport(
-       SecKeyRef                                                       secKey,
-       SecItemImportExportFlags                        flags,          
-       const SecKeyImportExportParameters      *keyParams,             // optional 
-       CFMutableDataRef                                        outData,                // output appended here
-       const char                                                      **pemHeader,    // RETURNED
-       CFArrayRef                                                      *pemParamLines) // RETURNED
-{
-       DevRandomGenerator              rng;
-       SecNssCoder                             coder;
-       CSSM_CSP_HANDLE                 cspHand = 0;
-       OSStatus                                ortn;
-       bool                                    releaseCspHand = false;
-       CFMutableArrayRef               paramLines;
-       CFStringRef                             cfStr;
-       char                                    dekStr[100];
-       char                                    ivStr[3];
-       
-       if(keyParams == NULL) {
-               return errSecParam;
-       }
-       
-       /* we need a CSPDL handle - try to get it from the key */       
-       ortn = SecKeyGetCSPHandle(secKey, &cspHand);
-       if(ortn) {
-               cspHand = cuCspStartup(CSSM_FALSE);
-               if(cspHand == 0) {
-                       return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
-               }
-               releaseCspHand = true;
-       }
-       /* subsequent errors to errOut: */
-       
-       /* 8 bytes of random IV/salt */
-       uint8 saltIv[8];
-       CSSM_DATA saltIvData = { 8, saltIv} ;
-       rng.random(saltIv, 8);
-       
-       /* derive wrapping key */
-       CSSM_KEY        wrappingKey;
-       wrappingKey.KeyData.Data = NULL;
-       wrappingKey.KeyData.Length = 0;
-       ortn = deriveKeyOpensslWrap(keyParams, cspHand, VP_Export, 
-               OPENSSL_WRAP_PBE_ALG, OPENSSL_WRAP_KEY_ALG,
-               OPENSSL_WRAP_KEY_SIZE,
-               saltIvData,             // IV == salt for this wrapping alg
-               &wrappingKey);
-       if(ortn) {
-               goto errOut;
-       }
-       
-       /* wrap the outgoing key */
-       CSSM_KEY wrappedKey;
-       memset(&wrappedKey, 0, sizeof(CSSM_KEY));
-       
-       ortn = impExpExportKeyCommon(cspHand, secKey, &wrappingKey, &wrappedKey,
-               OPENSSL_WRAP_ENCR_ALG, OPENSSL_WRAP_ENCR_MODE, OPENSSL_WRAP_ENCR_PAD,
-               CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL, 
-               CSSM_ATTRIBUTE_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
-               NULL, &saltIvData);
-       if(ortn) {
-               goto errOut;
-       }
-       
-       /*
-        * That wrapped key's KeyData is our output 
-        */
-       CFDataAppendBytes(outData, wrappedKey.KeyData.Data, wrappedKey.KeyData.Length);
-       
-       /* PEM header depends on key algorithm */
-       switch(wrappedKey.KeyHeader.AlgorithmId) {
-               case CSSM_ALGID_RSA:
-                       *pemHeader = PEM_STRING_RSA;
-                       break;  
-               case CSSM_ALGID_DH:
-                       *pemHeader = PEM_STRING_DH_PRIVATE;
-                       break; 
-               case CSSM_ALGID_DSA:
-                       *pemHeader = PEM_STRING_DSA;
-                       break;  
-               case CSSM_ALGID_ECDSA:
-                       *pemHeader = PEM_STRING_ECDSA_PRIVATE;
-                       break;  
-               default:
-                       SecImpExpDbg("impExpWrappedKeyOpenSslExport unknown private key alg "
-                               "%lu", (unsigned long)wrappedKey.KeyHeader.AlgorithmId);
-                       /* punt though I think something is seriously hosed */
-                       *pemHeader = "Private Key";
-       }
-       CSSM_FreeKey(cspHand, NULL, &wrappedKey, CSSM_FALSE);
-       
-       /* 
-        * Last thing: set up outgoing PEM parameter lines
-        */
-       assert(pemParamLines != NULL);
-       paramLines = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       cfStr = CFStringCreateWithCString(NULL, 
-               "Proc-Type: 4,ENCRYPTED", kCFStringEncodingASCII);
-       CFArrayAppendValue(paramLines, cfStr);
-       CFRelease(cfStr);               // owned by array now */
-       strcpy(dekStr, "DEK-Info: DES-EDE3-CBC,");
-       /* next goes the IV */
-       for(unsigned dex=0; dex<8; dex++) {
-               sprintf(ivStr, "%02X", saltIv[dex]);
-               strcat(dekStr, ivStr);
-       }
-       cfStr = CFStringCreateWithCString(NULL, dekStr, kCFStringEncodingASCII);
-       CFArrayAppendValue(paramLines, cfStr);
-       CFRelease(cfStr);               // owned by array now */
-       /* and an empty line */
-       cfStr = CFStringCreateWithCString(NULL, "", kCFStringEncodingASCII);
-       CFArrayAppendValue(paramLines, cfStr);
-       CFRelease(cfStr);               // owned by array now */
-       *pemParamLines = paramLines;
-       
-errOut:
-       if(wrappingKey.KeyData.Data != NULL) {
-               CSSM_FreeKey(cspHand, NULL, &wrappingKey, CSSM_FALSE);
-       }
-       return ortn;
-
-}
-