]> git.saurik.com Git - apple/security.git/blob - CertTool/cdsaUtils/cdsaUtils.c
Security-54.1.7.tar.gz
[apple/security.git] / CertTool / cdsaUtils / cdsaUtils.c
1 /*
2 File: cdsaUtils.c
3
4 Description: common CDSA access utilities
5
6 Author: dmitch
7
8 Copyright: © Copyright 2001 Apple Computer, Inc. All rights reserved.
9
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.
16
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.
35
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.
42
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.
52 */
53
54 #include "cdsaUtils.h"
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <Security/SecCertificate.h>
58 #include <strings.h>
59
60 static CSSM_VERSION vers = {2, 0};
61 static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
62
63 /*
64 * Standard app-level memory functions required by CDSA.
65 */
66 void * cuAppMalloc (uint32 size, void *allocRef) {
67 return( malloc(size) );
68 }
69
70 void cuAppFree (void *mem_ptr, void *allocRef) {
71 free(mem_ptr);
72 return;
73 }
74
75 void * cuAppRealloc (void *ptr, uint32 size, void *allocRef) {
76 return( realloc( ptr, size ) );
77 }
78
79 void * cuAppCalloc (uint32 num, uint32 size, void *allocRef) {
80 return( calloc( num, size ) );
81 }
82
83 static CSSM_API_MEMORY_FUNCS memFuncs = {
84 cuAppMalloc,
85 cuAppFree,
86 cuAppRealloc,
87 cuAppCalloc,
88 NULL
89 };
90
91 CSSM_BOOL cuCompareCssmData(const CSSM_DATA *d1,
92 const CSSM_DATA *d2)
93 {
94 if(d1->Length != d2->Length) {
95 return CSSM_FALSE;
96 }
97 if(memcmp(d1->Data, d2->Data, d1->Length)) {
98 return CSSM_FALSE;
99 }
100 return CSSM_TRUE;
101 }
102
103 /*
104 * Init CSSM; returns CSSM_FALSE on error. Reusable.
105 */
106 static CSSM_BOOL cssmInitd = CSSM_FALSE;
107
108 CSSM_BOOL cuCssmStartup()
109 {
110 CSSM_RETURN crtn;
111 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
112
113 if(cssmInitd) {
114 return CSSM_TRUE;
115 }
116 crtn = CSSM_Init (&vers,
117 CSSM_PRIVILEGE_SCOPE_NONE,
118 &testGuid,
119 CSSM_KEY_HIERARCHY_NONE,
120 &pvcPolicy,
121 NULL /* reserved */);
122 if(crtn != CSSM_OK)
123 {
124 cuPrintError("CSSM_Init", crtn);
125 return CSSM_FALSE;
126 }
127 else {
128 cssmInitd = CSSM_TRUE;
129 return CSSM_TRUE;
130 }
131 }
132
133 /*
134 * Attach to CSP. Returns zero on error.
135 */
136 CSSM_CSP_HANDLE cuCspStartup(
137 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL
138 {
139 CSSM_CSP_HANDLE cspHand;
140 CSSM_RETURN crtn;
141 const CSSM_GUID *guid;
142
143 /* common CSSM init */
144 if(cuCssmStartup() == CSSM_FALSE) {
145 return 0;
146 }
147 if(bareCsp) {
148 guid = &gGuidAppleCSP;
149 }
150 else {
151 guid = &gGuidAppleCSPDL;
152 }
153 crtn = CSSM_ModuleLoad(guid,
154 CSSM_KEY_HIERARCHY_NONE,
155 NULL, // eventHandler
156 NULL); // AppNotifyCallbackCtx
157 if(crtn) {
158 cuPrintError("CSSM_ModuleLoad()", crtn);
159 return 0;
160 }
161 crtn = CSSM_ModuleAttach (guid,
162 &vers,
163 &memFuncs, // memFuncs
164 0, // SubserviceID
165 CSSM_SERVICE_CSP,
166 0, // AttachFlags
167 CSSM_KEY_HIERARCHY_NONE,
168 NULL, // FunctionTable
169 0, // NumFuncTable
170 NULL, // reserved
171 &cspHand);
172 if(crtn) {
173 cuPrintError("CSSM_ModuleAttach()", crtn);
174 return 0;
175 }
176 return cspHand;
177 }
178
179 /* Attach to DL side of CSPDL */
180 CSSM_DL_HANDLE cuDlStartup()
181 {
182 CSSM_DL_HANDLE dlHand = 0;
183 CSSM_RETURN crtn;
184
185 if(cuCssmStartup() == CSSM_FALSE) {
186 return 0;
187 }
188 crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL,
189 CSSM_KEY_HIERARCHY_NONE,
190 NULL, // eventHandler
191 NULL); // AppNotifyCallbackCtx
192 if(crtn) {
193 cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn);
194 return 0;
195 }
196 crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL,
197 &vers,
198 &memFuncs, // memFuncs
199 0, // SubserviceID
200 CSSM_SERVICE_DL,
201 0, // AttachFlags
202 CSSM_KEY_HIERARCHY_NONE,
203 NULL, // FunctionTable
204 0, // NumFuncTable
205 NULL, // reserved
206 &dlHand);
207 if(crtn) {
208 cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn);
209 return 0;
210 }
211 return dlHand;
212 }
213
214 CSSM_CL_HANDLE cuClStartup()
215 {
216 CSSM_CL_HANDLE clHand;
217 CSSM_RETURN crtn;
218
219 if(cuCssmStartup() == CSSM_FALSE) {
220 return 0;
221 }
222 crtn = CSSM_ModuleLoad(&gGuidAppleX509CL,
223 CSSM_KEY_HIERARCHY_NONE,
224 NULL, // eventHandler
225 NULL); // AppNotifyCallbackCtx
226 if(crtn) {
227 cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn);
228 return 0;
229 }
230 crtn = CSSM_ModuleAttach (&gGuidAppleX509CL,
231 &vers,
232 &memFuncs, // memFuncs
233 0, // SubserviceID
234 CSSM_SERVICE_CL, // SubserviceFlags - Where is this used?
235 0, // AttachFlags
236 CSSM_KEY_HIERARCHY_NONE,
237 NULL, // FunctionTable
238 0, // NumFuncTable
239 NULL, // reserved
240 &clHand);
241 if(crtn) {
242 cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn);
243 return 0;
244 }
245 else {
246 return clHand;
247 }
248 }
249
250 CSSM_TP_HANDLE cuTpStartup()
251 {
252 CSSM_TP_HANDLE tpHand;
253 CSSM_RETURN crtn;
254
255 if(cuCssmStartup() == CSSM_FALSE) {
256 return 0;
257 }
258 crtn = CSSM_ModuleLoad(&gGuidAppleX509TP,
259 CSSM_KEY_HIERARCHY_NONE,
260 NULL, // eventHandler
261 NULL); // AppNotifyCallbackCtx
262 if(crtn) {
263 cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn);
264 return 0;
265 }
266 crtn = CSSM_ModuleAttach (&gGuidAppleX509TP,
267 &vers,
268 &memFuncs, // memFuncs
269 0, // SubserviceID
270 CSSM_SERVICE_TP, // SubserviceFlags
271 0, // AttachFlags
272 CSSM_KEY_HIERARCHY_NONE,
273 NULL, // FunctionTable
274 0, // NumFuncTable
275 NULL, // reserved
276 &tpHand);
277 if(crtn) {
278 cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn);
279 return 0;
280 }
281 else {
282 return tpHand;
283 }
284 }
285
286 /*
287 * open a DB, ensure it's empty.
288 */
289 CSSM_DB_HANDLE cuDbStartup(
290 CSSM_DL_HANDLE dlHand, // from dlStartup()
291 const char *dbName)
292 {
293 CSSM_DB_HANDLE dbHand = 0;
294 CSSM_RETURN crtn;
295 CSSM_DBINFO dbInfo;
296
297 /* first delete possible existing DB, ignore error */
298 crtn = CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL);
299 switch(crtn) {
300 /* only allowed error is "no such file" */
301 case CSSM_OK:
302 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST:
303 break;
304 default:
305 cuPrintError("CSSM_DL_DbDelete", crtn);
306 return 0;
307 }
308
309 memset(&dbInfo, 0, sizeof(CSSM_DBINFO));
310
311 /* now create it */
312 crtn = CSSM_DL_DbCreate(dlHand,
313 dbName,
314 NULL, // DbLocation
315 &dbInfo,
316 // &Security::KeychainCore::Schema::DBInfo,
317 CSSM_DB_ACCESS_PRIVILEGED,
318 NULL, // CredAndAclEntry
319 NULL, // OpenParameters
320 &dbHand);
321 if(crtn) {
322 cuPrintError("CSSM_DL_DbCreate", crtn);
323 }
324 return dbHand;
325 }
326
327 /*
328 * Attach to existing DB or create an empty new one.
329 */
330 CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand,
331 char *dbName,
332 CSSM_BOOL doCreate,
333 CSSM_BOOL quiet)
334 {
335 CSSM_RETURN crtn;
336 CSSM_DB_HANDLE dbHand;
337
338 /* try open existing DB in either case */
339
340 crtn = CSSM_DL_DbOpen(dlHand,
341 dbName,
342 NULL, // DbLocation
343 CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
344 NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred
345 NULL, // void *OpenParameters
346 &dbHand);
347 if(crtn == CSSM_OK) {
348 return dbHand;
349 }
350 if(!doCreate) {
351 if(!quiet) {
352 printf("***no such data base (%s)\n", dbName);
353 cuPrintError("CSSM_DL_DbOpen", crtn);
354 }
355 return 0;
356 }
357 /* have to create one */
358 return cuDbStartup(dlHand, dbName);
359 }
360
361 /*
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.
365 */
366 CSSM_RETURN cuAddContextAttribute(CSSM_CC_HANDLE CCHandle,
367 uint32 AttributeType,
368 uint32 AttributeLength,
369 const void *AttributePtr)
370 {
371 CSSM_CONTEXT_ATTRIBUTE newAttr;
372 CSSM_RETURN crtn;
373
374 newAttr.AttributeType = AttributeType;
375 newAttr.AttributeLength = AttributeLength;
376 newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
377 crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
378 if(crtn) {
379 cuPrintError("CSSM_UpdateContextAttributes", crtn);
380 }
381 return crtn;
382 }
383
384
385 /*
386 * Derive symmetric key.
387 * Note in the X CSP, we never return an IV.
388 */
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
398 CSSM_KEY_PTR key)
399 {
400 CSSM_RETURN crtn;
401 CSSM_CC_HANDLE ccHand;
402 uint32 keyAttr;
403 CSSM_DATA dummyLabel;
404 CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
405 CSSM_DATA pbeData;
406 CSSM_ACCESS_CREDENTIALS creds;
407
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,
412 keyAlg,
413 keySizeInBits,
414 &creds,
415 NULL, // BaseKey
416 iterationCnt,
417 salt,
418 NULL, // seed
419 &ccHand);
420 if(crtn) {
421 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn);
422 return crtn;
423 }
424 keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF |
425 CSSM_KEYATTR_SENSITIVE;
426 dummyLabel.Length = keyLabelLen;
427 dummyLabel.Data = (uint8 *)keyLabel;
428
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,
435 &pbeData,
436 keyUsage,
437 keyAttr,
438 &dummyLabel,
439 NULL, // cred and acl
440 key);
441 if(crtn) {
442 cuPrintError("CSSM_DeriveKey", crtn);
443 return crtn;
444 }
445 crtn = CSSM_DeleteContext(ccHand);
446 if(crtn) {
447 cuPrintError("CSSM_DeleteContext", crtn);
448 }
449 return crtn;
450 }
451
452 /*
453 * Generate key pair of arbitrary algorithm.
454 */
455
456 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */
457 #define DO_DSA_GEN_PARAMS 0
458
459 CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand,
460 CSSM_DL_DB_HANDLE *dlDbHand, // optional
461 uint32 algorithm,
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.
471 {
472 CSSM_RETURN crtn;
473 CSSM_RETURN ocrtn;
474 CSSM_CC_HANDLE ccHand;
475 CSSM_DATA keyLabelData;
476
477 keyLabelData.Data = (uint8 *)keyLabel,
478 keyLabelData.Length = keyLabelLen;
479 memset(pubKey, 0, sizeof(CSSM_KEY));
480 memset(privKey, 0, sizeof(CSSM_KEY));
481
482 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
483 algorithm,
484 keySize,
485 NULL, // Seed
486 NULL, // Salt
487 NULL, // StartDate
488 NULL, // EndDate
489 NULL, // Params
490 &ccHand);
491 if(crtn) {
492 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn);
493 return crtn;
494 }
495
496 /* post-context-create algorithm-specific stuff */
497 switch(algorithm) {
498 #if DO_DSA_GEN_PARAMS
499 case CSSM_ALGID_DSA:
500 /*
501 * extra step - generate params - this just adds some
502 * info to the context
503 */
504 {
505 CSSM_DATA dummy = {0, NULL};
506 crtn = CSSM_GenerateAlgorithmParams(ccHand,
507 keySize, &dummy);
508 if(crtn) {
509 cuPrintError("CSSM_GenerateAlgorithmParams", crtn);
510 CSSM_DeleteContext(ccHand);
511 return crtn;
512 }
513 cuAppFree(dummy.Data, NULL);
514 }
515 break;
516 #endif /* DO_DSA_GEN_PARAMS */
517 default:
518 break;
519 }
520
521 /* optionally specify DL/DB storage location */
522 if(dlDbHand) {
523 crtn = cuAddContextAttribute(ccHand,
524 CSSM_ATTRIBUTE_DL_DB_HANDLE,
525 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
526 dlDbHand);
527 if(crtn) {
528 CSSM_DeleteContext(ccHand);
529 return crtn;
530 }
531 }
532 ocrtn = CSSM_GenerateKeyPair(ccHand,
533 pubKeyUsage,
534 pubAttrs,
535 &keyLabelData,
536 pubKey,
537 privKeyUsage,
538 privAttrs,
539 &keyLabelData, // same labels
540 NULL, // CredAndAclEntry
541 privKey);
542 if(ocrtn) {
543 cuPrintError("CSSM_GenerateKeyPair", ocrtn);
544 }
545 crtn = CSSM_DeleteContext(ccHand);
546 if(crtn) {
547 cuPrintError("CSSM_DeleteContext", crtn);
548 if(ocrtn == CSSM_OK) {
549 /* error on CSSM_GenerateKeyPair takes precedence */
550 ocrtn = crtn;
551 }
552 }
553 return ocrtn;
554 }
555
556 /*
557 * Add a certificate to an open DLDB.
558 */
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)
566 {
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;
573 CSSM_RETURN crtn;
574 CSSM_DB_UNIQUE_RECORD_PTR recordPtr;
575
576 /* issuer and serial number required, fake 'em */
577 CSSM_DATA issuer = {6, (uint8 *)"issuer"};
578 CSSM_DATA serial = {6, (uint8 *)"serial"};
579
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;
587
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;
593
594 attr++;
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;
600
601 attr++;
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;
607
608 attr++;
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;
614
615 attr++;
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;
621
622 attr++;
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;
628
629 recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
630 recordAttrs.SemanticInformation = 0;
631 recordAttrs.NumberOfAttributes = 6;
632 recordAttrs.AttributeData = attrs;
633
634 crtn = CSSM_DL_DataInsert(dlDbHand,
635 CSSM_DL_DB_RECORD_X509_CERTIFICATE,
636 &recordAttrs,
637 cert,
638 &recordPtr);
639 if(crtn) {
640 cuPrintError("CSSM_DL_DataInsert", crtn);
641 }
642 else {
643 CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr);
644 }
645 return crtn;
646 }
647
648 /*
649 * Add a certificate to an open DLDB.
650 */
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) // ??
658 {
659 SecCertificateRef certificate;
660
661 OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate);
662 if (!rslt)
663 {
664 rslt = SecCertificateAddToKeychain(certificate, keychain);
665 CFRelease(certificate);
666 }
667
668 return rslt;
669 }
670
671 /*
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.
675 */
676 #if 1
677 extern void cssmPerror(const char *how, CSSM_RETURN error);
678 #else
679 #include <Security/cssmapple.h>
680 #endif
681 /*
682 * Log CSSM error.
683 */
684 void cuPrintError(char *op, CSSM_RETURN err)
685 {
686 cssmPerror(op, err);
687 }