2 * Copyright (c) 2007-2010,2012-2015 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@
25 * SecTrustStoreServer.c - CertificateSource API to a system root certificate store
27 #include "SecTrustStoreServer.h"
29 #include <Security/SecCertificateInternal.h>
30 #include <Security/SecFramework.h>
33 #include <dispatch/dispatch.h>
38 #include <sys/param.h>
41 #include <CoreFoundation/CFData.h>
42 #include <CoreFoundation/CFPropertyList.h>
43 #include <CoreFoundation/CFURL.h>
44 #include <AssertMacros.h>
45 #include <utilities/debugging.h>
46 #include <Security/SecBasePriv.h>
47 #include <Security/SecInternal.h>
48 #include <ipc/securityd_client.h>
49 #include "trust/trustd/SecTrustStoreServer.h"
50 #include "utilities/sqlutils.h"
51 #include "utilities/SecDb.h"
52 #include <utilities/SecCFError.h>
53 #include "utilities/SecFileLocations.h"
54 #include <utilities/SecDispatchRelease.h>
55 #include "trust/trustd/SecTrustLoggingServer.h"
56 #include <os/variant_private.h>
58 #include <utilities/SecCFWrappers.h>
59 #include <utilities/SecInternalReleasePriv.h>
61 /* uid of the _securityd user. */
62 #define SECURTYD_UID 64
64 static dispatch_once_t kSecTrustStoreUserOnce
;
65 static SecTrustStoreRef kSecTrustStoreUser
= NULL
;
68 static const char copyParentsSQL
[] = "SELECT data FROM tsettings WHERE subj=?";
69 static const char containsSQL
[] = "SELECT tset FROM tsettings WHERE sha1=?";
70 static const char insertSQL
[] = "INSERT OR REPLACE INTO tsettings(sha1,subj,tset,data)VALUES(?,?,?,?)";
71 static const char deleteSQL
[] = "DELETE FROM tsettings WHERE sha1=?";
72 static const char deleteAllSQL
[] = "BEGIN EXCLUSIVE TRANSACTION; DELETE from tsettings; COMMIT TRANSACTION; VACUUM;";
73 static const char copyAllSQL
[] = "SELECT data,tset FROM tsettings ORDER BY sha1";
74 static const char countAllSQL
[] = "SELECT COUNT(*) FROM tsettings";
77 #define kSecTrustStoreName CFSTR("TrustStore")
78 #define kSecTrustStoreDbExtension CFSTR("sqlite3")
80 #define kTrustStoreFileName CFSTR("TrustStore.sqlite3")
83 struct __SecTrustStore
{
84 dispatch_queue_t queue
;
86 sqlite3_stmt
*copyParents
;
87 sqlite3_stmt
*contains
;
89 bool containsSettings
; // For optimization of high-use calls.
93 // MARK: Corporate Root functions
96 // MARK: Trust store functions
98 static int sec_create_path(const char *path
)
100 char pathbuf
[PATH_MAX
];
101 size_t pos
, len
= strlen(path
);
102 if (len
== 0 || len
> PATH_MAX
)
103 return SQLITE_CANTOPEN
;
104 memcpy(pathbuf
, path
, len
);
105 for (pos
= len
-1; pos
> 0; --pos
)
107 /* Search backwards for trailing '/'. */
108 if (pathbuf
[pos
] == '/')
111 /* Attempt to create parent directories of the database. */
112 if (!mkdir(pathbuf
, 0777))
120 return SQLITE_CANTOPEN
;
122 return SQLITE_READONLY
;
125 if (err
== ENOSPC
|| err
== EDQUOT
)
130 /* EFAULT || ELOOP | ENAMETOOLONG || something else */
131 return SQLITE_INTERNAL
;
138 static int sec_sqlite3_open(const char *db_name
, sqlite3
**s3h
,
142 s3e
= sqlite3_open(db_name
, s3h
);
143 if (s3e
== SQLITE_CANTOPEN
&& create_path
) {
144 /* Make sure the path to db_name exists and is writable, then
146 s3e
= sec_create_path(db_name
);
148 s3e
= sqlite3_open(db_name
, s3h
);
154 static int64_t SecTrustStoreCountAll(SecTrustStoreRef ts
) {
155 __block
int64_t result
= -1;
156 require_quiet(ts
, errOutNotLocked
);
157 dispatch_sync(ts
->queue
, ^{
158 sqlite3_stmt
*countAllStmt
= NULL
;
159 int s3e
= sqlite3_prepare_v2(ts
->s3h
, countAllSQL
, sizeof(countAllSQL
),
160 &countAllStmt
, NULL
);
161 if (s3e
== SQLITE_OK
) {
162 s3e
= sqlite3_step(countAllStmt
);
163 if (s3e
== SQLITE_ROW
) {
164 result
= sqlite3_column_int64(countAllStmt
, 0);
169 verify_noerr(sqlite3_finalize(countAllStmt
));
177 static SecTrustStoreRef
SecTrustStoreCreate(const char *db_name
,
182 require(ts
= (SecTrustStoreRef
)malloc(sizeof(struct __SecTrustStore
)), errOut
);
183 ts
->queue
= dispatch_queue_create("truststore", DISPATCH_QUEUE_SERIAL
);
184 require_noerr(s3e
= sec_sqlite3_open(db_name
, &ts
->s3h
, create
), errOut
);
186 s3e
= sqlite3_prepare_v3(ts
->s3h
, copyParentsSQL
, sizeof(copyParentsSQL
),
187 SQLITE_PREPARE_PERSISTENT
, &ts
->copyParents
, NULL
);
188 if (create
&& s3e
== SQLITE_ERROR
) {
189 /* sqlite3_prepare returns SQLITE_ERROR if the table we are
190 compiling this statement for doesn't exist. */
192 s3e
= sqlite3_exec(ts
->s3h
,
193 "CREATE TABLE tsettings("
194 "sha1 BLOB NOT NULL DEFAULT '',"
195 "subj BLOB NOT NULL DEFAULT '',"
200 "CREATE INDEX isubj ON tsettings(subj);"
201 , NULL
, NULL
, &errmsg
);
203 secwarning("CREATE TABLE cert: %s", errmsg
);
204 sqlite3_free(errmsg
);
206 require_noerr(s3e
, errOut
);
207 s3e
= sqlite3_prepare_v3(ts
->s3h
, copyParentsSQL
, sizeof(copyParentsSQL
),
208 SQLITE_PREPARE_PERSISTENT
, &ts
->copyParents
, NULL
);
210 require_noerr(s3e
, errOut
);
211 require_noerr(s3e
= sqlite3_prepare_v3(ts
->s3h
, containsSQL
, sizeof(containsSQL
), SQLITE_PREPARE_PERSISTENT
,
212 &ts
->contains
, NULL
), errOut
);
214 if (SecTrustStoreCountAll(ts
) == 0) {
215 ts
->containsSettings
= false;
217 /* In the error case where SecTrustStoreCountAll returns a negative result,
218 * we'll pretend there are contents in the trust store so that we still do
220 ts
->containsSettings
= true;
228 sqlite3_close(ts
->s3h
);
229 dispatch_release_safe(ts
->queue
);
232 secerror("Failed to create trust store database: %d", s3e
);
233 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationCreate
, TAFatalError
, s3e
);
238 static bool SecExtractFilesystemPathForKeychainFile(CFStringRef file
, UInt8
*buffer
, CFIndex maxBufLen
)
240 bool translated
= false;
241 CFURLRef fileURL
= SecCopyURLForFileInKeychainDirectory(file
);
243 if (fileURL
&& CFURLGetFileSystemRepresentation(fileURL
, false, buffer
, maxBufLen
))
245 CFReleaseSafe(fileURL
);
250 static void SecTrustStoreInitUser(void) {
251 const char path
[MAXPATHLEN
];
253 if (SecExtractFilesystemPathForKeychainFile(kTrustStoreFileName
, (UInt8
*) path
, (CFIndex
) sizeof(path
)))
255 kSecTrustStoreUser
= SecTrustStoreCreate(path
, true);
256 if (kSecTrustStoreUser
)
257 kSecTrustStoreUser
->readOnly
= false;
261 /* AUDIT[securityd](done):
262 domainName (ok) is a caller provided string of any length (might be 0), only
263 its cf type has been checked.
265 SecTrustStoreRef
SecTrustStoreForDomainName(CFStringRef domainName
, CFErrorRef
*error
) {
266 if (CFEqual(CFSTR("user"), domainName
)) {
267 dispatch_once(&kSecTrustStoreUserOnce
, ^{ SecTrustStoreInitUser(); });
268 return kSecTrustStoreUser
;
270 SecError(errSecParam
, error
, CFSTR("unknown domain: %@"), domainName
);
275 /* AUDIT[securityd](done):
276 ts (ok) might be NULL.
277 certificate (ok) is a valid SecCertificateRef.
278 trustSettingsDictOrArray (checked by CFPropertyListCreateXMLData) is either
279 NULL, a dictionary or an array, but its contents have not been checked.
281 bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts
,
282 SecCertificateRef certificate
,
283 CFTypeRef tsdoa
, CFErrorRef
*error
) {
285 require_action_quiet(ts
, errOutNotLocked
, ok
= SecError(errSecParam
, error
, CFSTR("truststore is NULL")));
286 require_action_quiet(!ts
->readOnly
, errOutNotLocked
, ok
= SecError(errSecReadOnly
, error
, CFSTR("truststore is readOnly")));
287 dispatch_sync(ts
->queue
, ^{
288 CFTypeRef trustSettingsDictOrArray
= tsdoa
;
289 sqlite3_stmt
*insert
= NULL
;
290 CFDataRef xmlData
= NULL
;
291 CFArrayRef array
= NULL
;
294 require_action_quiet(subject
= SecCertificateGetNormalizedSubjectContent(certificate
),
295 errOut
, ok
= SecError(errSecParam
, error
, CFSTR("get normalized subject failed")));
297 require_action_quiet(digest
= SecCertificateGetSHA1Digest(certificate
), errOut
, ok
= SecError(errSecParam
, error
, CFSTR("get sha1 digest failed")));
299 /* Do some basic checks on the trust settings passed in. */
300 if (trustSettingsDictOrArray
== NULL
) {
301 require_action_quiet(array
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
), errOut
, ok
= SecError(errSecAllocate
, error
, CFSTR("CFArrayCreate failed")));
302 trustSettingsDictOrArray
= array
;
304 else if(CFGetTypeID(trustSettingsDictOrArray
) == CFDictionaryGetTypeID()) {
306 array
= CFArrayCreate(NULL
, &trustSettingsDictOrArray
, 1,
307 &kCFTypeArrayCallBacks
);
308 trustSettingsDictOrArray
= array
;
311 require_action_quiet(CFGetTypeID(trustSettingsDictOrArray
) == CFArrayGetTypeID(), errOut
, ok
= SecError(errSecParam
, error
, CFSTR("trustSettingsDictOrArray neither dict nor array")));
314 require_action_quiet(xmlData
= CFPropertyListCreateXMLData(kCFAllocatorDefault
,
315 trustSettingsDictOrArray
), errOut
, ok
= SecError(errSecParam
, error
, CFSTR("xml encode failed")));
317 int s3e
= sqlite3_exec(ts
->s3h
, "BEGIN EXCLUSIVE TRANSACTION", NULL
, NULL
, NULL
);
318 require_action_quiet(s3e
== SQLITE_OK
, errOut
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
320 /* Parameter order is sha1,subj,tset,data. */
321 require_noerr_action_quiet(s3e
= sqlite3_prepare_v2(ts
->s3h
, insertSQL
, sizeof(insertSQL
),
322 &insert
, NULL
), errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
323 require_noerr_action_quiet(s3e
= sqlite3_bind_blob_wrapper(insert
, 1,
324 CFDataGetBytePtr(digest
), CFDataGetLength(digest
), SQLITE_STATIC
),
325 errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
326 require_noerr_action_quiet(s3e
= sqlite3_bind_blob_wrapper(insert
, 2,
327 CFDataGetBytePtr(subject
), CFDataGetLength(subject
),
328 SQLITE_STATIC
), errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
329 require_noerr_action_quiet(s3e
= sqlite3_bind_blob_wrapper(insert
, 3,
330 CFDataGetBytePtr(xmlData
), CFDataGetLength(xmlData
),
331 SQLITE_STATIC
), errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
332 require_noerr_action_quiet(s3e
= sqlite3_bind_blob_wrapper(insert
, 4,
333 SecCertificateGetBytePtr(certificate
),
334 SecCertificateGetLength(certificate
), SQLITE_STATIC
), errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
335 s3e
= sqlite3_step(insert
);
336 if (s3e
== SQLITE_DONE
) {
337 /* Great the insert worked. */
339 ts
->containsSettings
= true;
341 require_noerr_action_quiet(s3e
, errOutSql
, ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
));
347 s3e
= sqlite3_finalize(insert
);
350 if (ok
&& s3e
== SQLITE_OK
) {
351 s3e
= sqlite3_exec(ts
->s3h
, "COMMIT TRANSACTION", NULL
, NULL
, NULL
);
354 if (!ok
|| s3e
!= SQLITE_OK
) {
355 secerror("Failed to update trust store: (%d) %@", s3e
, error
? *error
: NULL
);
356 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationWrite
, TAFatalError
, s3e
);
357 sqlite3_exec(ts
->s3h
, "ROLLBACK TRANSACTION", NULL
, NULL
, NULL
);
359 ok
= SecError(errSecInternal
, error
, CFSTR("sqlite3 error: %d"), s3e
);
364 CFReleaseSafe(xmlData
);
365 CFReleaseSafe(array
);
371 /* AUDIT[securityd](done):
372 ts (ok) might be NULL.
373 digest (ok) is a data of any length (might be 0).
375 bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts
,
376 CFDataRef digest
, CFErrorRef
*error
) {
377 require_quiet(ts
, errOutNotLocked
);
378 require(!ts
->readOnly
, errOutNotLocked
);
379 dispatch_sync(ts
->queue
, ^{
381 sqlite3_stmt
*deleteStmt
= NULL
;
383 require_noerr(s3e
= sqlite3_prepare_v2(ts
->s3h
, deleteSQL
, sizeof(deleteSQL
),
384 &deleteStmt
, NULL
), errOut
);
385 require_noerr(s3e
= sqlite3_bind_blob_wrapper(deleteStmt
, 1,
386 CFDataGetBytePtr(digest
), CFDataGetLength(digest
), SQLITE_STATIC
),
388 s3e
= sqlite3_step(deleteStmt
);
392 verify_noerr(sqlite3_finalize(deleteStmt
));
394 if (s3e
!= SQLITE_OK
&& s3e
!= SQLITE_DONE
) {
395 secerror("Removal of certificate from trust store failed: %d", s3e
);
396 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationWrite
, TAFatalError
, s3e
);
403 bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts
, CFErrorRef
*error
)
405 __block
bool removed_all
= false;
406 require(ts
, errOutNotLocked
);
407 require(!ts
->readOnly
, errOutNotLocked
);
408 dispatch_sync(ts
->queue
, ^{
409 int s3e
=sqlite3_exec(ts
->s3h
, deleteAllSQL
, NULL
, NULL
, NULL
);
410 if (s3e
== SQLITE_OK
) {
412 ts
->containsSettings
= false;
414 secerror("Clearing of trust store failed: %d", s3e
);
415 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationWrite
, TAFatalError
, s3e
);
418 /* prepared statements become unusable after deleteAllSQL, reset them */
420 sqlite3_finalize(ts
->copyParents
);
421 sqlite3_prepare_v3(ts
->s3h
, copyParentsSQL
, sizeof(copyParentsSQL
), SQLITE_PREPARE_PERSISTENT
,
422 &ts
->copyParents
, NULL
);
424 sqlite3_finalize(ts
->contains
);
425 sqlite3_prepare_v3(ts
->s3h
, containsSQL
, sizeof(containsSQL
), SQLITE_PREPARE_PERSISTENT
,
426 &ts
->contains
, NULL
);
432 CFArrayRef
SecTrustStoreCopyParents(SecTrustStoreRef ts
,
433 SecCertificateRef certificate
, CFErrorRef
*error
) {
434 __block CFMutableArrayRef parents
= NULL
;
435 require(ts
, errOutNotLocked
);
436 dispatch_sync(ts
->queue
, ^{
438 CFDataRef issuer
= NULL
;
439 require(issuer
= SecCertificateGetNormalizedIssuerContent(certificate
),
441 require_quiet(ts
->containsSettings
, ok
);
442 /* @@@ Might have to use SQLITE_TRANSIENT */
443 require_noerr(s3e
= sqlite3_bind_blob_wrapper(ts
->copyParents
, 1,
444 CFDataGetBytePtr(issuer
), CFDataGetLength(issuer
),
445 SQLITE_STATIC
), errOut
);
447 require(parents
= CFArrayCreateMutable(kCFAllocatorDefault
, 0,
448 &kCFTypeArrayCallBacks
), errOut
);
450 s3e
= sqlite3_step(ts
->copyParents
);
451 if (s3e
== SQLITE_ROW
) {
452 SecCertificateRef cert
;
453 require(cert
= SecCertificateCreateWithBytes(kCFAllocatorDefault
,
454 sqlite3_column_blob(ts
->copyParents
, 0),
455 sqlite3_column_bytes(ts
->copyParents
, 0)), errOut
);
456 CFArrayAppendValue(parents
, cert
);
459 require(s3e
== SQLITE_DONE
|| s3e
== SQLITE_OK
, errOut
);
466 secerror("Failed to read parents from trust store: %d", s3e
);
467 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationRead
, TAFatalError
, s3e
);
473 verify_noerr(sqlite3_reset(ts
->copyParents
));
474 verify_noerr(sqlite3_clear_bindings(ts
->copyParents
));
480 static bool SecTrustStoreQueryCertificateWithDigest(SecTrustStoreRef ts
,
481 CFDataRef digest
, bool *contains
, CFArrayRef
*usageConstraints
, CFErrorRef
*error
) {
484 __block
bool ok
= true;
485 require_action_quiet(ts
, errOutNotLocked
, ok
= SecError(errSecParam
, error
, CFSTR("ts is NULL")));
486 dispatch_sync(ts
->queue
, ^{
487 CFDataRef xmlData
= NULL
;
488 CFPropertyListRef trustSettings
= NULL
;
490 require_action_quiet(ts
->containsSettings
, errOut
, ok
= true);
491 require_noerr_action(s3e
= sqlite3_bind_blob_wrapper(ts
->contains
, 1,
492 CFDataGetBytePtr(digest
), CFDataGetLength(digest
), SQLITE_STATIC
),
493 errOut
, ok
= SecDbErrorWithStmt(s3e
, ts
->contains
, error
, CFSTR("sqlite3_bind_blob failed")));
494 s3e
= sqlite3_step(ts
->contains
);
495 if (s3e
== SQLITE_ROW
) {
498 if (usageConstraints
) {
499 require_action(xmlData
= CFDataCreate(NULL
,
500 sqlite3_column_blob(ts
->contains
, 0),
501 sqlite3_column_bytes(ts
->contains
, 0)), errOut
, ok
= false);
502 require_action(trustSettings
= CFPropertyListCreateWithData(NULL
,
504 kCFPropertyListImmutable
,
505 NULL
, error
), errOut
, ok
= false);
506 require_action(CFGetTypeID(trustSettings
) == CFArrayGetTypeID(), errOut
, ok
= false);
507 *usageConstraints
= CFRetain(trustSettings
);
510 require_action(s3e
== SQLITE_DONE
|| s3e
== SQLITE_OK
, errOut
,
511 ok
= SecDbErrorWithStmt(s3e
, ts
->contains
, error
, CFSTR("sqlite3_step failed")));
516 secerror("Failed to query for cert in trust store: %d", s3e
);
517 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationRead
, TAFatalError
, s3e
);
519 verify_noerr(sqlite3_reset(ts
->contains
));
520 verify_noerr(sqlite3_clear_bindings(ts
->contains
));
521 CFReleaseNull(xmlData
);
522 CFReleaseNull(trustSettings
);
528 bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts
,
529 CFDataRef digest
, bool *contains
, CFErrorRef
*error
) {
530 return SecTrustStoreQueryCertificateWithDigest(ts
, digest
, contains
, NULL
, error
);
533 bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts
,
534 CFDataRef digest
, CFArrayRef
*usageConstraints
, CFErrorRef
*error
) {
535 return SecTrustStoreQueryCertificateWithDigest(ts
, digest
, NULL
, usageConstraints
, error
);
538 bool _SecTrustStoreCopyAll(SecTrustStoreRef ts
, CFArrayRef
*trustStoreContents
, CFErrorRef
*error
) {
539 __block
bool ok
= true;
540 __block CFMutableArrayRef CertsAndSettings
= NULL
;
541 require_action_quiet(ts
, errOutNotLocked
, ok
= SecError(errSecParam
, error
, CFSTR("ts is NULL")));
542 require_action_quiet(trustStoreContents
, errOutNotLocked
, ok
= SecError(errSecParam
, error
, CFSTR("trustStoreContents is NULL")));
543 dispatch_sync(ts
->queue
, ^{
544 sqlite3_stmt
*copyAllStmt
= NULL
;
545 CFDataRef cert
= NULL
;
546 CFDataRef xmlData
= NULL
;
547 CFPropertyListRef trustSettings
= NULL
;
548 CFArrayRef certSettingsPair
= NULL
;
550 require_noerr(s3e
= sqlite3_prepare_v2(ts
->s3h
, copyAllSQL
, sizeof(copyAllSQL
),
551 ©AllStmt
, NULL
), errOut
);
552 require(CertsAndSettings
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
), errOut
);
554 s3e
= sqlite3_step(copyAllStmt
);
555 if (s3e
== SQLITE_ROW
) {
556 require(cert
= CFDataCreate(kCFAllocatorDefault
,
557 sqlite3_column_blob(copyAllStmt
, 0),
558 sqlite3_column_bytes(copyAllStmt
, 0)), errOut
);
559 require(xmlData
= CFDataCreate(NULL
,
560 sqlite3_column_blob(copyAllStmt
, 1),
561 sqlite3_column_bytes(copyAllStmt
, 1)), errOut
);
562 require(trustSettings
= CFPropertyListCreateWithData(NULL
,
564 kCFPropertyListImmutable
,
565 NULL
, error
), errOut
);
566 const void *pair
[] = { cert
, trustSettings
};
567 require(certSettingsPair
= CFArrayCreate(NULL
, pair
, 2, &kCFTypeArrayCallBacks
), errOut
);
568 CFArrayAppendValue(CertsAndSettings
, certSettingsPair
);
571 CFReleaseNull(xmlData
);
572 CFReleaseNull(trustSettings
);
573 CFReleaseNull(certSettingsPair
);
575 require_action(s3e
== SQLITE_DONE
|| s3e
== SQLITE_OK
, errOut
, ok
= SecDbErrorWithStmt(s3e
, copyAllStmt
, error
, CFSTR("sqlite3_step failed")));
582 secerror("Failed to query for all certs in trust store: %d", s3e
);
583 TrustdHealthAnalyticsLogErrorCodeForDatabase(TATrustStore
, TAOperationRead
, TAFatalError
, s3e
);
585 CFReleaseNull(xmlData
);
586 CFReleaseNull(trustSettings
);
587 CFReleaseNull(certSettingsPair
);
590 verify_noerr(sqlite3_finalize(copyAllStmt
));
592 if (CertsAndSettings
) {
593 *trustStoreContents
= CertsAndSettings
;
600 #else // !TARGET_OS_IPHONE
601 /* On macOS the trust store has nothing in it by default */
602 static void SecTrustStoreInitUser(void) {
603 SecTrustStoreRef ts
= (SecTrustStoreRef
)malloc(sizeof(struct __SecTrustStore
));
604 memset(ts
, 0, sizeof(struct __SecTrustStore
));
606 kSecTrustStoreUser
= ts
;
609 SecTrustStoreRef
SecTrustStoreForDomainName(CFStringRef domainName
, CFErrorRef
*error
) {
610 if (CFEqual(CFSTR("user"), domainName
)) {
611 dispatch_once(&kSecTrustStoreUserOnce
, ^{ SecTrustStoreInitUser(); });
612 return kSecTrustStoreUser
;
614 SecError(errSecParam
, error
, CFSTR("unknown domain: %@"), domainName
);
619 bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts
,
620 SecCertificateRef certificate
,
621 CFTypeRef trustSettingsDictOrArray
, CFErrorRef
*error
) {
622 return SecError(errSecUnimplemented
, error
, CFSTR("trust store is not modifiable on this platform"));
625 bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts
, CFDataRef digest
, CFErrorRef
*error
) {
626 return SecError(errSecUnimplemented
, error
, CFSTR("trust store is not modifiable on this platform"));
629 bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts
, CFErrorRef
*error
) {
630 return SecError(errSecUnimplemented
, error
, CFSTR("trust store is not modifiable on this platform"));
633 CFArrayRef
SecTrustStoreCopyParents(SecTrustStoreRef ts
,
634 SecCertificateRef certificate
, CFErrorRef
*error
) {
635 CFArrayRef parents
= NULL
;
639 bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts
, CFDataRef digest
, bool *contains
, CFErrorRef
*error
) {
646 bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts
, CFDataRef digest
, CFArrayRef
*usageConstraints
, CFErrorRef
*error
) {
650 bool _SecTrustStoreCopyAll(SecTrustStoreRef ts
, CFArrayRef
*trustStoreContents
, CFErrorRef
*error
) {
651 CFMutableArrayRef CertsAndSettings
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
652 if (CertsAndSettings
) {
653 *trustStoreContents
= CertsAndSettings
;