4 Description: common CDSA access utilities
8 Copyright: © Copyright 2001 Apple Computer, Inc. All rights reserved.
10 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
11 Computer, Inc. ("Apple") in consideration of your agreement to
12 the following terms, and your use, installation, modification
13 or redistribution of this Apple software constitutes acceptance
14 of these terms. If you do not agree with these terms, please
15 do not use, install, modify or redistribute this Apple software.
17 In consideration of your agreement to abide by the following
18 terms, and subject to these terms, Apple grants you a personal,
19 non-exclusive license, under Apple's copyrights in this
20 original Apple software (the "Apple Software"), to use,
21 reproduce, modify and redistribute the Apple Software, with
22 or without modifications, in source and/or binary forms;
23 provided that if you redistribute the Apple Software in
24 its entirety and without modifications, you must retain
25 this notice and the following text and disclaimers in all
26 such redistributions of the Apple Software. Neither the
27 name, trademarks, service marks or logos of Apple Computer,
28 Inc. may be used to endorse or promote products derived from the
29 Apple Software without specific prior written permission from
30 Apple. Except as expressly stated in this notice, no other
31 rights or licenses, express or implied, are granted by Apple
32 herein, including but not limited to any patent rights that
33 may be infringed by your derivative works or by other works
34 in which the Apple Software may be incorporated.
36 The Apple Software is provided by Apple on an "AS IS" basis.
37 APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
38 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
39 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
40 REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE
41 OR IN COMBINATION WITH YOUR PRODUCTS.
43 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
44 INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
48 AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
49 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING
50 NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE
51 HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 #include "cdsaUtils.h"
57 #include <Security/SecCertificate.h>
60 static CSSM_VERSION vers
= {2, 0};
61 static const CSSM_GUID testGuid
= { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
64 * Standard app-level memory functions required by CDSA.
66 void * cuAppMalloc (uint32 size
, void *allocRef
) {
67 return( malloc(size
) );
70 void cuAppFree (void *mem_ptr
, void *allocRef
) {
75 void * cuAppRealloc (void *ptr
, uint32 size
, void *allocRef
) {
76 return( realloc( ptr
, size
) );
79 void * cuAppCalloc (uint32 num
, uint32 size
, void *allocRef
) {
80 return( calloc( num
, size
) );
83 static CSSM_API_MEMORY_FUNCS memFuncs
= {
91 CSSM_BOOL
cuCompareCssmData(const CSSM_DATA
*d1
,
94 if(d1
->Length
!= d2
->Length
) {
97 if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) {
104 * Init CSSM; returns CSSM_FALSE on error. Reusable.
106 static CSSM_BOOL cssmInitd
= CSSM_FALSE
;
108 CSSM_BOOL
cuCssmStartup()
111 CSSM_PVC_MODE pvcPolicy
= CSSM_PVC_NONE
;
116 crtn
= CSSM_Init (&vers
,
117 CSSM_PRIVILEGE_SCOPE_NONE
,
119 CSSM_KEY_HIERARCHY_NONE
,
121 NULL
/* reserved */);
124 cuPrintError("CSSM_Init", crtn
);
128 cssmInitd
= CSSM_TRUE
;
134 * Attach to CSP. Returns zero on error.
136 CSSM_CSP_HANDLE
cuCspStartup(
137 CSSM_BOOL bareCsp
) // true ==> CSP, false ==> CSP/DL
139 CSSM_CSP_HANDLE cspHand
;
141 const CSSM_GUID
*guid
;
143 /* common CSSM init */
144 if(cuCssmStartup() == CSSM_FALSE
) {
148 guid
= &gGuidAppleCSP
;
151 guid
= &gGuidAppleCSPDL
;
153 crtn
= CSSM_ModuleLoad(guid
,
154 CSSM_KEY_HIERARCHY_NONE
,
155 NULL
, // eventHandler
156 NULL
); // AppNotifyCallbackCtx
158 cuPrintError("CSSM_ModuleLoad()", crtn
);
161 crtn
= CSSM_ModuleAttach (guid
,
163 &memFuncs
, // memFuncs
167 CSSM_KEY_HIERARCHY_NONE
,
168 NULL
, // FunctionTable
173 cuPrintError("CSSM_ModuleAttach()", crtn
);
179 /* Attach to DL side of CSPDL */
180 CSSM_DL_HANDLE
cuDlStartup()
182 CSSM_DL_HANDLE dlHand
= 0;
185 if(cuCssmStartup() == CSSM_FALSE
) {
188 crtn
= CSSM_ModuleLoad(&gGuidAppleCSPDL
,
189 CSSM_KEY_HIERARCHY_NONE
,
190 NULL
, // eventHandler
191 NULL
); // AppNotifyCallbackCtx
193 cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn
);
196 crtn
= CSSM_ModuleAttach (&gGuidAppleCSPDL
,
198 &memFuncs
, // memFuncs
202 CSSM_KEY_HIERARCHY_NONE
,
203 NULL
, // FunctionTable
208 cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn
);
214 CSSM_CL_HANDLE
cuClStartup()
216 CSSM_CL_HANDLE clHand
;
219 if(cuCssmStartup() == CSSM_FALSE
) {
222 crtn
= CSSM_ModuleLoad(&gGuidAppleX509CL
,
223 CSSM_KEY_HIERARCHY_NONE
,
224 NULL
, // eventHandler
225 NULL
); // AppNotifyCallbackCtx
227 cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn
);
230 crtn
= CSSM_ModuleAttach (&gGuidAppleX509CL
,
232 &memFuncs
, // memFuncs
234 CSSM_SERVICE_CL
, // SubserviceFlags - Where is this used?
236 CSSM_KEY_HIERARCHY_NONE
,
237 NULL
, // FunctionTable
242 cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn
);
250 CSSM_TP_HANDLE
cuTpStartup()
252 CSSM_TP_HANDLE tpHand
;
255 if(cuCssmStartup() == CSSM_FALSE
) {
258 crtn
= CSSM_ModuleLoad(&gGuidAppleX509TP
,
259 CSSM_KEY_HIERARCHY_NONE
,
260 NULL
, // eventHandler
261 NULL
); // AppNotifyCallbackCtx
263 cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn
);
266 crtn
= CSSM_ModuleAttach (&gGuidAppleX509TP
,
268 &memFuncs
, // memFuncs
270 CSSM_SERVICE_TP
, // SubserviceFlags
272 CSSM_KEY_HIERARCHY_NONE
,
273 NULL
, // FunctionTable
278 cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn
);
287 * open a DB, ensure it's empty.
289 CSSM_DB_HANDLE
cuDbStartup(
290 CSSM_DL_HANDLE dlHand
, // from dlStartup()
293 CSSM_DB_HANDLE dbHand
= 0;
297 /* first delete possible existing DB, ignore error */
298 crtn
= CSSM_DL_DbDelete(dlHand
, dbName
, NULL
, NULL
);
300 /* only allowed error is "no such file" */
302 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST
:
305 cuPrintError("CSSM_DL_DbDelete", crtn
);
309 memset(&dbInfo
, 0, sizeof(CSSM_DBINFO
));
312 crtn
= CSSM_DL_DbCreate(dlHand
,
316 // &Security::KeychainCore::Schema::DBInfo,
317 CSSM_DB_ACCESS_PRIVILEGED
,
318 NULL
, // CredAndAclEntry
319 NULL
, // OpenParameters
322 cuPrintError("CSSM_DL_DbCreate", crtn
);
328 * Attach to existing DB or create an empty new one.
330 CSSM_DB_HANDLE
cuDbStartupByName(CSSM_DL_HANDLE dlHand
,
336 CSSM_DB_HANDLE dbHand
;
338 /* try open existing DB in either case */
340 crtn
= CSSM_DL_DbOpen(dlHand
,
343 CSSM_DB_ACCESS_READ
| CSSM_DB_ACCESS_WRITE
,
344 NULL
, // CSSM_ACCESS_CREDENTIALS *AccessCred
345 NULL
, // void *OpenParameters
347 if(crtn
== CSSM_OK
) {
352 printf("***no such data base (%s)\n", dbName
);
353 cuPrintError("CSSM_DL_DbOpen", crtn
);
357 /* have to create one */
358 return cuDbStartup(dlHand
, dbName
);
362 * Given a context specified via a CSSM_CC_HANDLE, add a new
363 * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType,
364 * AttributeLength, and an untyped pointer.
366 CSSM_RETURN
cuAddContextAttribute(CSSM_CC_HANDLE CCHandle
,
367 uint32 AttributeType
,
368 uint32 AttributeLength
,
369 const void *AttributePtr
)
371 CSSM_CONTEXT_ATTRIBUTE newAttr
;
374 newAttr
.AttributeType
= AttributeType
;
375 newAttr
.AttributeLength
= AttributeLength
;
376 newAttr
.Attribute
.Data
= (CSSM_DATA_PTR
)AttributePtr
;
377 crtn
= CSSM_UpdateContextAttributes(CCHandle
, 1, &newAttr
);
379 cuPrintError("CSSM_UpdateContextAttributes", crtn
);
386 * Derive symmetric key.
387 * Note in the X CSP, we never return an IV.
389 CSSM_RETURN
cuCspDeriveKey(CSSM_CSP_HANDLE cspHand
,
390 uint32 keyAlg
, // CSSM_ALGID_RC5, etc.
391 const char *keyLabel
,
392 unsigned keyLabelLen
,
393 uint32 keyUsage
, // CSSM_KEYUSE_ENCRYPT, etc.
394 uint32 keySizeInBits
,
395 CSSM_DATA_PTR password
, // in PKCS-5 lingo
396 CSSM_DATA_PTR salt
, // ditto
397 uint32 iterationCnt
, // ditto
401 CSSM_CC_HANDLE ccHand
;
403 CSSM_DATA dummyLabel
;
404 CSSM_PKCS5_PBKDF2_PARAMS pbeParams
;
406 CSSM_ACCESS_CREDENTIALS creds
;
408 memset(key
, 0, sizeof(CSSM_KEY
));
409 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
410 crtn
= CSSM_CSP_CreateDeriveKeyContext(cspHand
,
411 CSSM_ALGID_PKCS5_PBKDF2
,
421 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn
);
424 keyAttr
= CSSM_KEYATTR_EXTRACTABLE
| CSSM_KEYATTR_RETURN_REF
|
425 CSSM_KEYATTR_SENSITIVE
;
426 dummyLabel
.Length
= keyLabelLen
;
427 dummyLabel
.Data
= (uint8
*)keyLabel
;
429 /* passing in password is pretty strange....*/
430 pbeParams
.Passphrase
= *password
;
431 pbeParams
.PseudoRandomFunction
= CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1
;
432 pbeData
.Data
= (uint8
*)&pbeParams
;
433 pbeData
.Length
= sizeof(pbeParams
);
434 crtn
= CSSM_DeriveKey(ccHand
,
439 NULL
, // cred and acl
442 cuPrintError("CSSM_DeriveKey", crtn
);
445 crtn
= CSSM_DeleteContext(ccHand
);
447 cuPrintError("CSSM_DeleteContext", crtn
);
453 * Generate key pair of arbitrary algorithm.
456 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */
457 #define DO_DSA_GEN_PARAMS 0
459 CSSM_RETURN
cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand
,
460 CSSM_DL_DB_HANDLE
*dlDbHand
, // optional
462 const char *keyLabel
,
463 unsigned keyLabelLen
,
464 uint32 keySize
, // in bits
465 CSSM_KEY_PTR pubKey
, // mallocd by caller
466 CSSM_KEYUSE pubKeyUsage
, // CSSM_KEYUSE_ENCRYPT, etc.
467 CSSM_KEYATTR_FLAGS pubAttrs
, // CSSM_KEYATTR_EXTRACTABLE, etc.
468 CSSM_KEY_PTR privKey
, // mallocd by caller
469 CSSM_KEYUSE privKeyUsage
, // CSSM_KEYUSE_DECRYPT, etc.
470 CSSM_KEYATTR_FLAGS privAttrs
) // CSSM_KEYATTR_EXTRACTABLE, etc.
474 CSSM_CC_HANDLE ccHand
;
475 CSSM_DATA keyLabelData
;
477 keyLabelData
.Data
= (uint8
*)keyLabel
,
478 keyLabelData
.Length
= keyLabelLen
;
479 memset(pubKey
, 0, sizeof(CSSM_KEY
));
480 memset(privKey
, 0, sizeof(CSSM_KEY
));
482 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
492 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn
);
496 /* post-context-create algorithm-specific stuff */
498 #if DO_DSA_GEN_PARAMS
501 * extra step - generate params - this just adds some
502 * info to the context
505 CSSM_DATA dummy
= {0, NULL
};
506 crtn
= CSSM_GenerateAlgorithmParams(ccHand
,
509 cuPrintError("CSSM_GenerateAlgorithmParams", crtn
);
510 CSSM_DeleteContext(ccHand
);
513 cuAppFree(dummy
.Data
, NULL
);
516 #endif /* DO_DSA_GEN_PARAMS */
521 /* optionally specify DL/DB storage location */
523 crtn
= cuAddContextAttribute(ccHand
,
524 CSSM_ATTRIBUTE_DL_DB_HANDLE
,
525 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE
),
528 CSSM_DeleteContext(ccHand
);
532 ocrtn
= CSSM_GenerateKeyPair(ccHand
,
539 &keyLabelData
, // same labels
540 NULL
, // CredAndAclEntry
543 cuPrintError("CSSM_GenerateKeyPair", ocrtn
);
545 crtn
= CSSM_DeleteContext(ccHand
);
547 cuPrintError("CSSM_DeleteContext", crtn
);
548 if(ocrtn
== CSSM_OK
) {
549 /* error on CSSM_GenerateKeyPair takes precedence */
557 * Add a certificate to an open DLDB.
559 CSSM_RETURN
cuAddCertToDb(
560 CSSM_DL_DB_HANDLE dlDbHand
,
561 const CSSM_DATA
*cert
,
562 CSSM_CERT_TYPE certType
,
563 CSSM_CERT_ENCODING certEncoding
,
564 const char *printName
, // C string
565 const CSSM_DATA
*publicKeyHash
)
567 CSSM_DB_ATTRIBUTE_DATA attrs
[6];
568 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs
;
569 CSSM_DB_ATTRIBUTE_DATA_PTR attr
= &attrs
[0];
570 CSSM_DATA certTypeData
;
571 CSSM_DATA certEncData
;
572 CSSM_DATA printNameData
;
574 CSSM_DB_UNIQUE_RECORD_PTR recordPtr
;
576 /* issuer and serial number required, fake 'em */
577 CSSM_DATA issuer
= {6, (uint8
*)"issuer"};
578 CSSM_DATA serial
= {6, (uint8
*)"serial"};
580 /* we spec six attributes, skipping alias */
581 certTypeData
.Data
= (uint8
*)&certType
;
582 certTypeData
.Length
= sizeof(CSSM_CERT_TYPE
);
583 certEncData
.Data
= (uint8
*)&certEncoding
;
584 certEncData
.Length
= sizeof(CSSM_CERT_ENCODING
);
585 printNameData
.Data
= (uint8
*)printName
;
586 printNameData
.Length
= strlen(printName
) + 1;
588 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
589 attr
->Info
.Label
.AttributeName
= "CertType";
590 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_UINT32
;
591 attr
->NumberOfValues
= 1;
592 attr
->Value
= &certTypeData
;
595 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
596 attr
->Info
.Label
.AttributeName
= "CertEncoding";
597 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_UINT32
;
598 attr
->NumberOfValues
= 1;
599 attr
->Value
= &certEncData
;
602 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
603 attr
->Info
.Label
.AttributeName
= "PrintName";
604 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
605 attr
->NumberOfValues
= 1;
606 attr
->Value
= &printNameData
;
609 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
610 attr
->Info
.Label
.AttributeName
= "PublicKeyHash";
611 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
612 attr
->NumberOfValues
= 1;
613 attr
->Value
= (CSSM_DATA_PTR
)publicKeyHash
;
616 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
617 attr
->Info
.Label
.AttributeName
= "Issuer";
618 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
619 attr
->NumberOfValues
= 1;
620 attr
->Value
= &issuer
;
623 attr
->Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
624 attr
->Info
.Label
.AttributeName
= "SerialNumber";
625 attr
->Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
626 attr
->NumberOfValues
= 1;
627 attr
->Value
= &serial
;
629 recordAttrs
.DataRecordType
= CSSM_DL_DB_RECORD_X509_CERTIFICATE
;
630 recordAttrs
.SemanticInformation
= 0;
631 recordAttrs
.NumberOfAttributes
= 6;
632 recordAttrs
.AttributeData
= attrs
;
634 crtn
= CSSM_DL_DataInsert(dlDbHand
,
635 CSSM_DL_DB_RECORD_X509_CERTIFICATE
,
640 cuPrintError("CSSM_DL_DataInsert", crtn
);
643 CSSM_DL_FreeUniqueRecord(dlDbHand
, recordPtr
);
649 * Add a certificate to an open DLDB.
651 CSSM_RETURN
cuAddCertToKC(
652 SecKeychainRef keychain
,
653 const CSSM_DATA
*cert
,
654 CSSM_CERT_TYPE certType
,
655 CSSM_CERT_ENCODING certEncoding
,
656 const char *printName
, // C string
657 const CSSM_DATA
*keyLabel
) // ??
659 SecCertificateRef certificate
;
661 OSStatus rslt
= SecCertificateCreateFromData(cert
, certType
, certEncoding
, &certificate
);
664 rslt
= SecCertificateAddToKeychain(certificate
, keychain
);
665 CFRelease(certificate
);
672 * This prototype does not exist in public Security headers in 10.1, but the
673 * function is in fact exported from the Security framework. A future release
674 * will include a public prototype for this function.
677 extern void cssmPerror(const char *how
, CSSM_RETURN error
);
679 #include <Security/cssmapple.h>
684 void cuPrintError(char *op
, CSSM_RETURN err
)