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),
86 #define SecVersionDbFlag(v) ((v & 0xFF) << 8)
88 #define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF)
90 #define SECDB_ATTR(var, name, kind, flags, copyValue, setValue) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags, copyValue, setValue }
92 typedef struct SecDbItem
*SecDbItemRef
;
93 typedef struct SecDbAttr SecDbAttr
;
95 typedef CFTypeRef (*SecDbItemCopyAttrValue
)(SecDbItemRef item
, const SecDbAttr
*attr
, CFErrorRef
*error
);
96 typedef bool (*SecDbItemSetAttrValue
)(SecDbItemRef item
, const SecDbAttr
*desc
, CFTypeRef value
, CFErrorRef
*error
);
102 SecDbItemCopyAttrValue copyValue
;
103 SecDbItemSetAttrValue setValue
;
106 typedef struct SecDbClass
{
108 bool itemclass
; // true if keychain items are stored in this class, false otherwise
109 const SecDbAttr
*attrs
[];
112 typedef struct SecDbSchema
{
115 const SecDbClass
*classes
[];
119 #define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr))
121 #define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask))
123 CFTypeRef
SecDbAttrCopyDefaultValue(const SecDbAttr
*attr
, CFErrorRef
*error
);
128 enum SecDbItemState
{
129 kSecDbItemDirty
, // We have no edata (or if we do it's invalid), attributes are the truth
130 kSecDbItemEncrypted
, // Attributes haven't been decrypted yet from edata
131 kSecDbItemClean
, // Attributes and _edata are in sync.
132 kSecDbItemDecrypting
, // Temporary state while we are decrypting so set knows not to blow away the edata.
133 kSecDbItemEncrypting
, // Temporary state while we are encrypting so set knows to move to clean.
134 kSecDbItemAlwaysEncrypted
, // As kSecDbItemEncrypted, but decryption is never attempted
135 kSecDbItemSecretEncrypted
, // Metadata is clean, but the secret data remains encrypted
140 const SecDbClass
*class;
142 keybag_handle_t keybag
;
143 enum SecDbItemState _edataState
;
144 CFMutableDictionaryRef attributes
;
145 CFDataRef credHandle
;
147 CFArrayRef callerAccessGroups
;
150 // TODO: Make this a callback to client
151 bool SecDbItemDecrypt(SecDbItemRef item
, bool decryptSecretData
, CFDataRef edata
, CFErrorRef
*error
);
153 CFTypeID
SecDbItemGetTypeID(void);
155 static inline size_t SecDbClassAttrCount(const SecDbClass
*dbClass
) {
157 SecDbForEachAttr(dbClass
, attr
) { n_attrs
++; }
161 const SecDbAttr
*SecDbClassAttrWithKind(const SecDbClass
*class, SecDbAttrKind kind
, CFErrorRef
*error
);
163 SecDbItemRef
SecDbItemCreateWithAttributes(CFAllocatorRef allocator
, const SecDbClass
*class, CFDictionaryRef attributes
, keybag_handle_t keybag
, CFErrorRef
*error
);
165 const SecDbClass
*SecDbItemGetClass(SecDbItemRef item
);
166 keybag_handle_t
SecDbItemGetKeybag(SecDbItemRef item
);
167 bool SecDbItemSetKeybag(SecDbItemRef item
, keybag_handle_t keybag
, CFErrorRef
*error
);
168 void SecDbItemSetCredHandle(SecDbItemRef item
, CFTypeRef cred_handle
);
169 void SecDbItemSetCallerAccessGroups(SecDbItemRef item
, CFArrayRef caller_access_groups
);
171 CFTypeRef
SecDbItemGetCachedValueWithName(SecDbItemRef item
, CFStringRef name
);
172 CFTypeRef
SecDbItemGetValue(SecDbItemRef item
, const SecDbAttr
*desc
, CFErrorRef
*error
);
173 CFTypeRef
SecDbItemGetValueKind(SecDbItemRef item
, SecDbAttrKind desc
, CFErrorRef
*error
);
175 bool SecDbItemSetValue(SecDbItemRef item
, const SecDbAttr
*desc
, CFTypeRef value
, CFErrorRef
*error
);
176 bool SecDbItemSetValues(SecDbItemRef item
, CFDictionaryRef values
, CFErrorRef
*error
);
177 bool SecDbItemSetValueWithName(SecDbItemRef item
, CFStringRef name
, CFTypeRef value
, CFErrorRef
*error
);
179 sqlite3_int64
SecDbItemGetRowId(SecDbItemRef item
, CFErrorRef
*error
);
180 bool SecDbItemSetRowId(SecDbItemRef item
, sqlite3_int64 rowid
, CFErrorRef
*error
);
181 bool SecDbItemClearRowId(SecDbItemRef item
, CFErrorRef
*error
);
183 bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item
);
184 bool SecDbItemIsSyncable(SecDbItemRef item
);
186 bool SecDbItemSetSyncable(SecDbItemRef item
, bool sync
, CFErrorRef
*error
);
188 bool SecDbItemIsTombstone(SecDbItemRef item
);
190 CFMutableDictionaryRef
SecDbItemCopyPListWithMask(SecDbItemRef item
, CFOptionFlags mask
, CFErrorRef
*error
);
192 CFDataRef
SecDbItemGetPrimaryKey(SecDbItemRef item
, CFErrorRef
*error
);
193 CFDataRef
SecDbItemGetSHA1(SecDbItemRef item
, CFErrorRef
*error
);
195 CFDataRef
SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item
, uint64_t handle
, CFErrorRef
*error
);
197 SecDbItemRef
SecDbItemCreateWithStatement(CFAllocatorRef allocator
, const SecDbClass
*class, sqlite3_stmt
*stmt
, keybag_handle_t keybag
, CFErrorRef
*error
, bool (^return_attr
)(const SecDbAttr
*attr
));
199 SecDbItemRef
SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator
, const SecDbClass
*class,
200 CFDataRef edata
, keybag_handle_t keybag
, CFErrorRef
*error
);
202 SecDbItemRef
SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator
, const SecDbClass
*class, CFDataRef primary_key
);
205 SecDbItemRef
SecDbItemCreateWithRowId(CFAllocatorRef allocator
, const SecDbClass
*class, sqlite_int64 row_id
, keybag_handle_t keybag
, CFErrorRef
*error
);
208 bool SecDbItemEnsureDecrypted(SecDbItemRef item
, bool decryptSecretData
, CFErrorRef
*error
);
210 SecDbItemRef
SecDbItemCopyWithUpdates(SecDbItemRef item
, CFDictionaryRef updates
, CFErrorRef
*error
);
212 bool SecDbItemInsertOrReplace(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
, void(^duplicate
)(SecDbItemRef item
, SecDbItemRef
*replace
));
214 // SecDbItemInsertOrReplace returns an error even when it succeeds; use this to determine if it's spurious
215 bool SecErrorIsSqliteDuplicateItemError(CFErrorRef error
);
217 bool SecDbItemInsert(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
);
219 bool SecDbItemDelete(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFBooleanRef makeTombstone
, CFErrorRef
*error
);
221 bool SecDbItemDoDeleteSilently(SecDbItemRef item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
);
223 // Low level update, just do the update
224 bool SecDbItemDoUpdate(SecDbItemRef old_item
, SecDbItemRef new_item
, SecDbConnectionRef dbconn
, CFErrorRef
*error
, bool (^use_attr_in_where
)(const SecDbAttr
*attr
));
226 // High level update, will replace tombstones and create them if needed.
227 bool SecDbItemUpdate(SecDbItemRef old_item
, SecDbItemRef new_item
, SecDbConnectionRef dbconn
, CFBooleanRef makeTombstone
, bool uuid_from_primary_key
, CFErrorRef
*error
);
231 // MARK: SQL Construction helpers -- These should become private in the future
233 void SecDbAppendElement(CFMutableStringRef sql
, CFStringRef value
, bool *needComma
);
234 void SecDbAppendWhereOrAnd(CFMutableStringRef sql
, bool *needWhere
);
235 void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
);
236 void SecDbAppendWhereOrAndNotEquals(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
);
237 void SecDbAppendWhereOrAndIn(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
, CFIndex count
);
238 void SecDbAppendWhereOrAndNotIn(CFMutableStringRef sql
, CFStringRef col
, bool *needWhere
, CFIndex count
);
240 // MARK: type converters.
241 // TODO: these should be static and private to SecDbItem, or part of the schema
243 CFStringRef
copyString(CFTypeRef obj
);
244 CFDataRef
copyData(CFTypeRef obj
);
245 CFTypeRef
copyBlob(CFTypeRef obj
);
246 CFDataRef
copySHA1(CFTypeRef obj
);
247 CFTypeRef
copyNumber(CFTypeRef obj
);
248 CFDateRef
copyDate(CFTypeRef obj
);
249 CFTypeRef
copyUUID(CFTypeRef obj
);
251 // MARK: cFErrorPropagate which handles errSecAuthNeeded
253 bool SecErrorPropagate(CFErrorRef possibleError CF_CONSUMED
, CFErrorRef
*error
) {
254 if (possibleError
&& error
&& *error
&& CFErrorGetCode(*error
) == errSecAuthNeeded
)
255 CFReleaseNull(*error
);
256 return CFErrorPropagate(possibleError
, error
);
260 bool SecDbItemInV2(SecDbItemRef item
);
261 bool SecDbItemInV2AlsoInV0(SecDbItemRef item
);
263 // For debug output filtering
264 bool SecDbItemIsEngineInternalState(SecDbItemRef itemObject
);
268 #endif /* _SECURITYD_SECDBITEM_H_ */