2  * Copyright (c) 2001,2003-2012,2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  23  * srCdsaUtils.cpp -- common CDSA access utilities 
  26 #include "srCdsaUtils.h" 
  29 #include <Security/SecCertificate.h> 
  30 #include <Security/cssmapple.h>                         /* for cssmPerror() */ 
  31 #include <Security/oidsalg.h>                           /* for cssmPerror() */ 
  34 static CSSM_VERSION vers 
= {2, 0}; 
  35 static const CSSM_GUID testGuid 
= { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; 
  38  * Standard app-level memory functions required by CDSA. 
  40 void * srAppMalloc (CSSM_SIZE size
, void *allocRef
) { 
  41         return( malloc(size
) ); 
  44 void srAppFree (void *mem_ptr
, void *allocRef
) { 
  49 void * srAppRealloc (void *ptr
, CSSM_SIZE size
, void *allocRef
) { 
  50         return( realloc( ptr
, size 
) ); 
  53 void * srAppCalloc (uint32 num
, CSSM_SIZE size
, void *allocRef
) { 
  54         return( calloc( num
, size 
) ); 
  57 static CSSM_API_MEMORY_FUNCS memFuncs 
= { 
  65 CSSM_BOOL 
srCompareCssmData(const CSSM_DATA 
*d1
, 
  68         if(d1
->Length 
!= d2
->Length
) { 
  71         if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) { 
  78  * Init CSSM; returns CSSM_FALSE on error. Reusable. 
  80 static CSSM_BOOL cssmInitd 
= CSSM_FALSE
; 
  82 CSSM_BOOL 
srCssmStartup() 
  85     CSSM_PVC_MODE pvcPolicy 
= CSSM_PVC_NONE
; 
  90         crtn 
= CSSM_Init (&vers
, 
  91                 CSSM_PRIVILEGE_SCOPE_NONE
, 
  93                 CSSM_KEY_HIERARCHY_NONE
, 
  98                 srPrintError("CSSM_Init", crtn
); 
 102                 cssmInitd 
= CSSM_TRUE
; 
 108  * Attach to CSP. Returns zero on error. 
 110 CSSM_CSP_HANDLE 
srCspStartup( 
 111         CSSM_BOOL bareCsp
)              // true ==> CSP, false ==> CSP/DL 
 113         CSSM_CSP_HANDLE cspHand
; 
 115         const CSSM_GUID 
*guid
; 
 117         /* common CSSM init */ 
 118         if(srCssmStartup() == CSSM_FALSE
) { 
 122                 guid 
= &gGuidAppleCSP
; 
 125                 guid 
= &gGuidAppleCSPDL
; 
 127         crtn 
= CSSM_ModuleLoad(guid
, 
 128                 CSSM_KEY_HIERARCHY_NONE
, 
 129                 NULL
,                   // eventHandler 
 130                 NULL
);                  // AppNotifyCallbackCtx 
 132                 srPrintError("CSSM_ModuleLoad()", crtn
); 
 135         crtn 
= CSSM_ModuleAttach (guid
, 
 137                 &memFuncs
,                      // memFuncs 
 141                 CSSM_KEY_HIERARCHY_NONE
, 
 142                 NULL
,                           // FunctionTable 
 147                 srPrintError("CSSM_ModuleAttach()", crtn
); 
 153 /* Attach to DL side of CSPDL */ 
 154 CSSM_DL_HANDLE 
srDlStartup() 
 156         CSSM_DL_HANDLE  dlHand 
= 0; 
 159         if(srCssmStartup() == CSSM_FALSE
) { 
 162         crtn 
= CSSM_ModuleLoad(&gGuidAppleCSPDL
, 
 163                 CSSM_KEY_HIERARCHY_NONE
, 
 164                 NULL
,                   // eventHandler 
 165                 NULL
);                  // AppNotifyCallbackCtx 
 167                 srPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn
); 
 170         crtn 
= CSSM_ModuleAttach (&gGuidAppleCSPDL
, 
 172                 &memFuncs
,                      // memFuncs 
 176                 CSSM_KEY_HIERARCHY_NONE
, 
 177                 NULL
,                           // FunctionTable 
 182                 srPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn
); 
 188 CSSM_CL_HANDLE 
srClStartup() 
 190         CSSM_CL_HANDLE clHand
; 
 193         if(srCssmStartup() == CSSM_FALSE
) { 
 196         crtn 
= CSSM_ModuleLoad(&gGuidAppleX509CL
, 
 197                 CSSM_KEY_HIERARCHY_NONE
, 
 198                 NULL
,                   // eventHandler 
 199                 NULL
);                  // AppNotifyCallbackCtx 
 201                 srPrintError("CSSM_ModuleLoad(AppleCL)", crtn
); 
 204         crtn 
= CSSM_ModuleAttach (&gGuidAppleX509CL
, 
 206                 &memFuncs
,                              // memFuncs 
 208                 CSSM_SERVICE_CL
,                // SubserviceFlags - Where is this used? 
 210                 CSSM_KEY_HIERARCHY_NONE
, 
 211                 NULL
,                                   // FunctionTable 
 216                 srPrintError("CSSM_ModuleAttach(AppleCL)", crtn
); 
 224 CSSM_TP_HANDLE 
srTpStartup() 
 226         CSSM_TP_HANDLE tpHand
; 
 229         if(srCssmStartup() == CSSM_FALSE
) { 
 232         crtn 
= CSSM_ModuleLoad(&gGuidAppleX509TP
, 
 233                 CSSM_KEY_HIERARCHY_NONE
, 
 234                 NULL
,                   // eventHandler 
 235                 NULL
);                  // AppNotifyCallbackCtx 
 237                 srPrintError("CSSM_ModuleLoad(AppleTP)", crtn
); 
 240         crtn 
= CSSM_ModuleAttach (&gGuidAppleX509TP
, 
 242                 &memFuncs
,                              // memFuncs 
 244                 CSSM_SERVICE_TP
,                // SubserviceFlags 
 246                 CSSM_KEY_HIERARCHY_NONE
, 
 247                 NULL
,                                   // FunctionTable 
 252                 srPrintError("CSSM_ModuleAttach(AppleTP)", crtn
); 
 261  * Given a context specified via a CSSM_CC_HANDLE, add a new 
 262  * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, 
 263  * AttributeLength, and an untyped pointer. 
 265 static CSSM_RETURN 
srAddContextAttribute(CSSM_CC_HANDLE CCHandle
, 
 266         uint32 AttributeType
, 
 267         uint32 AttributeLength
, 
 268         const void *AttributePtr
) 
 270         CSSM_CONTEXT_ATTRIBUTE          newAttr
; 
 273         newAttr
.AttributeType     
= AttributeType
; 
 274         newAttr
.AttributeLength   
= AttributeLength
; 
 275         newAttr
.Attribute
.Data    
= (CSSM_DATA_PTR
)AttributePtr
; 
 276         crtn 
= CSSM_UpdateContextAttributes(CCHandle
, 1, &newAttr
); 
 278                 srPrintError("CSSM_UpdateContextAttributes", crtn
); 
 285  * Derive symmetric key. 
 286  * Note in the X CSP, we never return an IV. 
 288 CSSM_RETURN 
srCspDeriveKey(CSSM_CSP_HANDLE cspHand
, 
 289                 uint32                          keyAlg
,                 // CSSM_ALGID_RC5, etc. 
 290                 const char                      *keyLabel
, 
 291                 unsigned                        keyLabelLen
, 
 292                 uint32                          keyUsage
,               // CSSM_KEYUSE_ENCRYPT, etc. 
 293                 uint32                          keySizeInBits
, 
 294                 CSSM_DATA_PTR           password
,               // in PKCS-5 lingo 
 295                 CSSM_DATA_PTR           salt
,                   // ditto 
 296                 uint32                          iterationCnt
,   // ditto 
 300         CSSM_CC_HANDLE                          ccHand
; 
 302         CSSM_DATA                                       dummyLabel
; 
 303         CSSM_PKCS5_PBKDF2_PARAMS        pbeParams
; 
 305         CSSM_ACCESS_CREDENTIALS         creds
; 
 307         memset(key
, 0, sizeof(CSSM_KEY
)); 
 308         memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
)); 
 309         crtn 
= CSSM_CSP_CreateDeriveKeyContext(cspHand
, 
 310                 CSSM_ALGID_PKCS5_PBKDF2
, 
 320                 srPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn
); 
 323         keyAttr 
= CSSM_KEYATTR_EXTRACTABLE 
| CSSM_KEYATTR_RETURN_REF 
| 
 324                           CSSM_KEYATTR_SENSITIVE
; 
 325         dummyLabel
.Length 
= keyLabelLen
; 
 326         dummyLabel
.Data 
= (uint8 
*)keyLabel
; 
 328         /* passing in password is pretty strange....*/ 
 329         pbeParams
.Passphrase 
= *password
; 
 330         pbeParams
.PseudoRandomFunction 
= CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1
; 
 331         pbeData
.Data 
= (uint8 
*)&pbeParams
; 
 332         pbeData
.Length 
= sizeof(pbeParams
); 
 333         crtn 
= CSSM_DeriveKey(ccHand
, 
 338                 NULL
,                   // cred and acl 
 341                 srPrintError("CSSM_DeriveKey", crtn
); 
 344         crtn 
= CSSM_DeleteContext(ccHand
); 
 346                 srPrintError("CSSM_DeleteContext", crtn
); 
 352  * Generate key pair of arbitrary algorithm. 
 355 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */ 
 356 #define DO_DSA_GEN_PARAMS               0 
 358 CSSM_RETURN 
srCspGenKeyPair(CSSM_CSP_HANDLE cspHand
, 
 359         CSSM_DL_DB_HANDLE 
*dlDbHand
,    // optional 
 361         const char *keyLabel
, 
 362         unsigned keyLabelLen
, 
 363         uint32 keySize
,                                 // in bits 
 364         CSSM_KEY_PTR pubKey
,                    // mallocd by caller 
 365         CSSM_KEYUSE pubKeyUsage
,                // CSSM_KEYUSE_ENCRYPT, etc. 
 366         CSSM_KEYATTR_FLAGS pubAttrs
,    // CSSM_KEYATTR_EXTRACTABLE, etc. 
 367         CSSM_KEY_PTR privKey
,                   // mallocd by caller 
 368         CSSM_KEYUSE privKeyUsage
,               // CSSM_KEYUSE_DECRYPT, etc. 
 369         CSSM_KEYATTR_FLAGS privAttrs
)   // CSSM_KEYATTR_EXTRACTABLE, etc. 
 373         CSSM_CC_HANDLE                  ccHand
; 
 374         CSSM_DATA                               keyLabelData
; 
 376         keyLabelData
.Data        
= (uint8 
*)keyLabel
, 
 377         keyLabelData
.Length      
= keyLabelLen
; 
 378         memset(pubKey
, 0, sizeof(CSSM_KEY
)); 
 379         memset(privKey
, 0, sizeof(CSSM_KEY
)); 
 381         crtn 
= CSSM_CSP_CreateKeyGenContext(cspHand
, 
 391                 srPrintError("CSSM_CSP_CreateKeyGenContext", crtn
); 
 395         /* post-context-create algorithm-specific stuff */ 
 397                 #if DO_DSA_GEN_PARAMS 
 400                          * extra step - generate params - this just adds some 
 401                          * info to the context 
 404                                 CSSM_DATA dummy 
= {0, NULL
}; 
 405                                 crtn 
= CSSM_GenerateAlgorithmParams(ccHand
, 
 408                                         srPrintError("CSSM_GenerateAlgorithmParams", crtn
); 
 409                                         CSSM_DeleteContext(ccHand
); 
 412                                 srAppFree(dummy
.Data
, NULL
); 
 415                 #endif  /* DO_DSA_GEN_PARAMS */ 
 420         /* optionally specify DL/DB storage location */ 
 422                 crtn 
= srAddContextAttribute(ccHand
, 
 423                         CSSM_ATTRIBUTE_DL_DB_HANDLE
, 
 424                         sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE
), 
 427                         CSSM_DeleteContext(ccHand
); 
 431         ocrtn 
= CSSM_GenerateKeyPair(ccHand
, 
 438                 &keyLabelData
,                  // same labels 
 439                 NULL
,                                   // CredAndAclEntry 
 442                 srPrintError("CSSM_GenerateKeyPair", ocrtn
); 
 444         crtn 
= CSSM_DeleteContext(ccHand
); 
 446                 srPrintError("CSSM_DeleteContext", crtn
); 
 447                 if(ocrtn 
== CSSM_OK
) { 
 448                         /* error on CSSM_GenerateKeyPair takes precedence */ 
 457  * Add a certificate to an open Keychain. 
 459 CSSM_RETURN 
srAddCertToKC( 
 460         SecKeychainRef          keychain
, 
 461         const CSSM_DATA         
*cert
, 
 462         CSSM_CERT_TYPE          certType
, 
 463         CSSM_CERT_ENCODING      certEncoding
, 
 464         const char                      *printName
,             // C string 
 465         const CSSM_DATA         
*keyLabel
)              // ?? 
 467         SecCertificateRef certificate
; 
 469         OSStatus rslt 
= SecCertificateCreateFromData(cert
, certType
, certEncoding
, &certificate
); 
 472                 rslt 
= SecCertificateAddToKeychain(certificate
, keychain
); 
 473                 CFRelease(certificate
); 
 480  * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an 
 483 unsigned srDER_ToInt(const CSSM_DATA 
*DER_Data
) 
 488         while(i 
< DER_Data
->Length
) { 
 489                 rtn 
|= DER_Data
->Data
[i
]; 
 490                 if(++i 
== DER_Data
->Length
) { 
 501 void srPrintError(const char *op
, CSSM_RETURN err
) 
 507  * Convert a CFString into a C string as safely as we can. Caller must 
 510 char *srCfStrToCString( 
 513         CFIndex len 
= CFStringGetLength(cfStr
) + 1; 
 514         char *cstr 
= (char *)malloc(len
); 
 518         if(!CFStringGetCString(cfStr
, cstr
, len
, kCFStringEncodingASCII
)) { 
 519                 printf("***CFStringGetCString error\n");