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");