2 * Copyright (c) 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@
26 The functions provided in SecDbItem provide an interface to
27 database items (certificates, keys, identities, and passwords).
30 #ifndef _SECURITYD_SECDBITEM_H_
31 #define _SECURITYD_SECDBITEM_H_
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <TargetConditionals.h>
35 #include <corecrypto/ccsha1.h> // For CCSHA1_OUTPUT_SIZE
37 #include "utilities/SecCFError.h"
38 #include "utilities/SecCFWrappers.h"
39 #include "utilities/SecDb.h"
40 #include "keychain/securityd/SecKeybagSupport.h"
41 #include <Security/SecAccessControl.h>
42 #include <Security/SecBasePriv.h>
44 // MARK SecDbAttrKind, SecDbFlag
47 kSecDbBlobAttr
, // CFString or CFData, preserves caller provided type.
52 kSecDbCreationDateAttr
,
53 kSecDbModificationDateAttr
,
56 kSecDbEncryptedDataAttr
,
62 kSecDbAccessControlAttr
,
67 kSecDbPrimaryKeyFlag
= (1 << 0), // attr is part of primary key
68 kSecDbInFlag
= (1 << 1), // attr exists in db
69 kSecDbIndexFlag
= (1 << 2), // attr should have a db index
70 kSecDbSHA1ValueInFlag
= (1 << 3), // col in db is sha1 of attr value
71 kSecDbReturnAttrFlag
= (1 << 4),
72 kSecDbReturnDataFlag
= (1 << 5),
73 kSecDbReturnRefFlag
= (1 << 6),
74 kSecDbInCryptoDataFlag
= (1 << 7),
75 kSecDbInHashFlag
= (1 << 8),
76 kSecDbInBackupFlag
= (1 << 9),
77 kSecDbDefault0Flag
= (1 << 10), // default attr value is 0
78 kSecDbDefaultEmptyFlag
= (1 << 11), // default attr value is ""
79 kSecDbNotNullFlag
= (1 << 12), // attr value can't be null
80 kSecDbInAuthenticatedDataFlag
= (1 << 13), // attr is in authenticated data
81 kSecDbSyncPrimaryKeyV0
= (1 << 14),
82 kSecDbSyncPrimaryKeyV2
= (1 << 15),
83 kSecDbSyncFlag
= (1 << 16),
84 kSecDbSyncSOSCannotSyncFlag
= (1 << 17),
87 #define SecVersionDbFlag(v) ((v & 0xFF) << 8)
89 #define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF)
91 #define SECDB_ATTR(var, name, kind, flags, copyValue, setValue) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags, copyValue, setValue }
93 typedef struct SecDbItem
*SecDbItemRef
;
94 typedef struct SecDbAttr SecDbAttr
;
96 typedef CFTypeRef (*SecDbItemCopyAttrValue
)(SecDbItemRef item
, const SecDbAttr
*attr
, CFErrorRef
*error
);
97 typedef bool (*SecDbItemSetAttrValue
)(SecDbItemRef item
, const SecDbAttr
*desc
, CFTypeRef value
, CFErrorRef
*error
);
103 SecDbItemCopyAttrValue copyValue
;
104 SecDbItemSetAttrValue setValue
;
107 typedef struct SecDbClass
{
109 bool itemclass
; // true if keychain items are stored in this class, false otherwise
110 const SecDbAttr
*attrs
[];
113 typedef struct SecDbSchema
{
116 const SecDbClass
*classes
[];
120 #define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr))
122 #define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask))
124 CFTypeRef
SecDbAttrCopyDefaultValue(const SecDbAttr
*attr
, CFErrorRef
*error
);
129 enum SecDbItemState
{
130 kSecDbItemDirty
, // We have no edata (or if we do it's invalid), attributes are the truth
131 kSecDbItemEncrypted
, // Attributes haven't been decrypted yet from edata
132 kSecDbItemClean
, // Attributes and _edata are in sync.
133 kSecDbItemDecrypting
, // Temporary state while we are decrypting so set knows not to blow away the edata.
134 kSecDbItemEncrypting
, // Temporary state while we are encrypting so set knows to move to clean.
135 kSecDbItemAlwaysEncrypted
, // As kSecDbItemEncrypted, but decryption is never attempted
136 kSecDbItemSecretEncrypted
, // Metadata is clean, but the secret data remains encrypted
141 const SecDbClass
*class;
143 keybag_handle_t keybag
;
144 enum SecDbItemState _edataState
;
145 CFMutableDictionaryRef attributes
;
146 CFDataRef credHandle
;
148 CFArrayRef callerAccessGroups
;
151 // TODO: Make this a callback to client
152 bool SecDbItemDecrypt(SecDbItemRef item
, bool decryptSecretData
, CFDataRef edata
, CFErrorRef
*error
);
154 CFTypeID
SecDbItemGetTypeID(void);
156 static inline size_t SecDbClassAttrCount(const SecDbClass
*dbClass
) {
158 SecDbForEachAttr(dbClass
, attr
) { n_attrs
++; }
162 const SecDbAttr
*SecDbClassAttrWithKind(const SecDbClass
*class, SecDbAttrKind kind
, CFErrorRef
*error
);
164 SecDbItemRef
SecDbItemCreateWithAttributes(CFAllocatorRef allocator
, const SecDbClass
*class, CFDictionaryRef attributes
, keybag_handle_t keybag
, CFErrorRef
*error
);
166 const SecDbClass
*SecDbItemGetClass(SecDbItemRef item
);
167 keybag_handle_t
SecDbItemGetKeybag(SecDbItemRef item
);
168 bool SecDbItemSetKeybag(SecDbItemRef item
, keybag_handle_t keybag
, CFErrorRef
*error
);
169 void SecDbItemSetCredHandle(SecDbItemRef item
, CFTypeRef cred_handle
);
170 void SecDbItemSetCallerAccessGroups(SecDbItemRef item
, CFArrayRef caller_access_groups
);
172 CFTypeRef
SecDbItemGetCachedValueWithName(SecDbItemRef item
, CFStringRef name
);
173 CFTypeRef
SecDbItemGetValue(SecDbItemRef item
, const SecDbAttr
*desc
, CFErrorRef
*error
);
174 CFTypeRef
SecDbItemGetValueKind(SecDbItemRef item
, SecDbAttrKind desc
, CFErrorRef
*error
);
176 bool SecDbItemSetValue(SecDbItemRef item
, const SecDbAttr
*desc
, CFTypeRef value
, CFErrorRef
*error
);
177 bool SecDbItemSetValues(SecDbItemRef item
, CFDictionaryRef values
, CFErrorRef
*error
);
178 bool SecDbItemSetValueWithName(SecDbItemRef item
, CFStringRef name
, CFTypeRef value
, CFErrorRef
*error
);
180 // Copies a given attribute from source to target. If source does not have that atttribute,
181 // doesn't modify target.
182 bool SecItemPreserveAttribute(SecDbItemRef target
, SecDbItemRef source
, const SecDbAttr
* attr
);
184 sqlite3_int64
SecDbItemGetRowId(SecDbItemRef item
, CFErrorRef
*error
);
185 bool SecDbItemSetRowId(SecDbItemRef item
, sqlite3_int64 rowid
, CFErrorRef
*error
);
186 bool SecDbItemClearRowId(SecDbItemRef item
, CFErrorRef
*error
);
188 bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item
);
189 bool SecDbItemIsSyncable(SecDbItemRef item
);
191 bool SecDbItemSetSyncable(SecDbItemRef item
, bool sync
, CFErrorRef
*error
);
193 bool SecDbItemIsTombstone(SecDbItemRef item
);
195 CFMutableDictionaryRef
SecDbItemCopyPListWithMask(SecDbItemRef item
, CFOptionFlags mask
, CFErrorRef
*error
);
198 * Note that "mask" requires a single option, but flagsToSkip can have any number combined.
200 CFMutableDictionaryRef
SecDbItemCopyPListWithFlagAndSkip(SecDbItemRef item
,
202 CFOptionFlags flagsToSkip
,
205 CFDataRef
SecDbItemGetPrimaryKey(SecDbItemRef item
, CFErrorRef
*error
);
206 CFDataRef
SecDbItemGetSHA1(SecDbItemRef item
, CFErrorRef
*error
);
208 CFDataRef
SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item
, uint64_t handle
, CFErrorRef
*error
);
210 SecDbItemRef
SecDbItemCreateWithStatement(CFAllocatorRef allocator
, const SecDbClass
*class, sqlite3_stmt
*stmt
, keybag_handle_t keybag
, CFErrorRef
*error
, bool (^return_attr
)(const SecDbAttr
*attr
));
212 SecDbItemRef
SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator
, const SecDbClass
*class,
213 CFDataRef edata
, keybag_handle_t keybag
, CFErrorRef
*error
);
215 SecDbItemRef
SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator
, const SecDbClass
*class, CFDataRef primary_key
);
218 SecDbItemRef
SecDbItemCreateWithRowId(CFAllocatorRef allocator
, const SecDbClass
*class, sqlite_int64 row_id
, keybag_handle_t keybag
, CFErrorRef
*error
);
221 bool SecDbItemEnsureDecrypted(SecDbItemRef item
, bool decryptSecretData
, CFErrorRef
*error
);
223 SecDbItemRef
SecDbItemCopyWithUpdates(SecDbItemRef item
, CFDictionaryRef updates
, CFErrorRef
*error
);
225 bool SecDbItemInsertOrReplace(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
, void(^duplicate
)(SecDbItemRef item
, SecDbItemRef
*replace
));
227 // SecDbItemInsertOrReplace returns an error even when it succeeds; use this to determine if it's spurious
228 bool SecErrorIsSqliteDuplicateItemError(CFErrorRef error
);
230 // Note: this function might modify item, unless always_use_uuid_from_new_item is true
231 bool SecDbItemInsert(SecDbItemRef item
, SecDbConnectionRef dbconn
, bool always_use_uuid_from_new_item
, CFErrorRef
*error
);
233 bool SecDbItemDelete(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFBooleanRef makeTombstone
, bool tombstone_time_from_item
, CFErrorRef
*error
);
235 bool SecDbItemDoDeleteSilently(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
);
237 // Low level update, just do the update
238 bool SecDbItemDoUpdate(SecDbItemRef old_item
, SecDbItemRef new_item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
, bool (^use_attr_in_where
)(const SecDbAttr
*attr
));
240 // High level update, will replace tombstones and create them if needed.
241 bool SecDbItemUpdate(SecDbItemRef old_item
, SecDbItemRef new_item
, SecDbConnectionRef dbconn
, CFBooleanRef makeTombstone
, bool uuid_from_primary_key
, CFErrorRef
*error
);
245 // MARK: SQL Construction helpers -- These should become private in the future
247 void SecDbAppendElement(CFMutableStringRef sql
, CFStringRef value
, bool *needComma
);
248 void SecDbAppendWhereOrAnd(CFMutableStringRef sql
, bool *needWhere
);
249 void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
);
250 void SecDbAppendWhereOrAndNotEquals(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
);
251 void SecDbAppendWhereOrAndIn(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
, CFIndex count
);
252 void SecDbAppendWhereOrAndNotIn(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
, CFIndex count
);
254 // MARK: type converters.
255 // TODO: these should be static and private to SecDbItem, or part of the schema
257 CFStringRef
copyString(CFTypeRef obj
);
258 CFDataRef
copyData(CFTypeRef obj
);
259 CFTypeRef
copyBlob(CFTypeRef obj
);
260 CFDataRef
copySHA1(CFTypeRef obj
);
261 CFTypeRef
copyNumber(CFTypeRef obj
);
262 CFDateRef
copyDate(CFTypeRef obj
);
263 CFTypeRef
copyUUID(CFTypeRef obj
);
265 // MARK: cFErrorPropagate which handles errSecAuthNeeded
267 bool SecErrorPropagate(CFErrorRef possibleError CF_CONSUMED
, CFErrorRef
*error
) {
268 if (possibleError
&& error
&& *error
&& CFErrorGetCode(*error
) == errSecAuthNeeded
)
269 CFReleaseNull(*error
);
270 return CFErrorPropagate(possibleError
, error
);
274 bool SecDbItemInV2(SecDbItemRef item
);
275 bool SecDbItemInV2AlsoInV0(SecDbItemRef item
);
277 // For debug output filtering
278 bool SecDbItemIsEngineInternalState(SecDbItemRef itemObject
);
282 #endif /* _SECURITYD_SECDBITEM_H_ */