1/*
2 * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*!
25 @header SecDbItem
26 The functions provided in SecDbItem provide an interface to
27 database items (certificates, keys, identities, and passwords).
28 */
29
30#ifndef _SECURITYD_SECDBITEM_H_
31#define _SECURITYD_SECDBITEM_H_
32
33#include <CoreFoundation/CoreFoundation.h>
34#include <TargetConditionals.h>
35#include <corecrypto/ccsha1.h> // For CCSHA1_OUTPUT_SIZE
36#include <sqlite3.h>
37#include <utilities/SecCFError.h>
38#include <utilities/SecCFWrappers.h>
39#include <utilities/SecDb.h>
40#include <utilities/SecAKSWrappers.h>
41
42#if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR)
43#define USE_KEYSTORE  1
44#elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR
45#define USE_KEYSTORE  1
46#else /* no keystore on this platform */
47#define USE_KEYSTORE  0
48#endif
49
50#if USE_KEYSTORE
51#include <Kernel/IOKit/crypto/AppleKeyStoreDefs.h>
52#endif /* USE_KEYSTORE */
53
54__BEGIN_DECLS
55
56// TODO: Get this out of this file
57#if USE_KEYSTORE
58typedef int32_t keyclass_t;
59#else
60
61/* TODO: this needs to be available in the sim! */
62#define kAppleKeyStoreKeyWrap 0
63#define kAppleKeyStoreKeyUnwrap 1
64typedef int32_t keyclass_t;
65typedef int32_t key_handle_t;
66enum key_classes {
67    key_class_ak = 6,
68    key_class_ck,
69    key_class_dk,
70    key_class_aku,
71    key_class_cku,
72    key_class_dku
73};
74#endif /* !USE_KEYSTORE */
75
76// MARK SecDbAttrKind, SecDbFlag
77
78typedef enum {
79    kSecDbBlobAttr,  // CFString or CFData, preserves caller provided type.
80    kSecDbDataAttr,
81    kSecDbStringAttr,
82    kSecDbNumberAttr,
83    kSecDbDateAttr,
84    kSecDbCreationDateAttr,
85    kSecDbModificationDateAttr,
86    kSecDbSHA1Attr,
87    kSecDbRowIdAttr,
88    kSecDbEncryptedDataAttr,
89    kSecDbPrimaryKeyAttr,
90    kSecDbSyncAttr,
91    kSecDbTombAttr,
92    kSecDbAccessAttr
93} SecDbAttrKind;
94
95enum {
96    kSecDbPrimaryKeyFlag    = (1 <<  0),    // attr is part of primary key
97    kSecDbInFlag            = (1 <<  1),    // attr exists in db
98    kSecDbIndexFlag         = (1 <<  2),    // attr should have a db index
99    kSecDbSHA1ValueInFlag   = (1 <<  3),    // col in db is sha1 of attr value
100    kSecDbReturnAttrFlag    = (1 <<  4),
101    kSecDbReturnDataFlag    = (1 <<  5),
102    kSecDbReturnRefFlag     = (1 <<  6),
103    kSecDbInCryptoDataFlag  = (1 <<  7),
104    kSecDbInHashFlag        = (1 <<  8),
105    kSecDbInBackupFlag      = (1 <<  9),
106    kSecDbDefault0Flag      = (1 << 10),    // default attr value is 0
107    kSecDbDefaultEmptyFlag  = (1 << 11),    // default attr value is ""
108    kSecDbNotNullFlag       = (1 << 12),    // attr value can't be null
109};
110
111#define SecVersionDbFlag(v) ((v & 0xFF) << 8)
112
113#define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF)
114
115#define SECDB_ATTR(var, name, kind, flags) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags }
116
117typedef struct SecDbAttr {
118    CFStringRef name;
119    SecDbAttrKind kind;
120    CFOptionFlags flags;
121} SecDbAttr;
122
123typedef struct SecDbClass {
124    CFStringRef name;
125    const SecDbAttr *attrs[];
126} SecDbClass;
127
128typedef struct Pair *SecDbPairRef;
129typedef struct Query *SecDbQueryRef;
130
131/* Return types. */
132typedef uint32_t ReturnTypeMask;
133enum
134{
135    kSecReturnDataMask = 1 << 0,
136    kSecReturnAttributesMask = 1 << 1,
137    kSecReturnRefMask = 1 << 2,
138    kSecReturnPersistentRefMask = 1 << 3,
139};
140
141/* Constant indicating there is no limit to the number of results to return. */
142enum
143{
144    kSecMatchUnlimited = kCFNotFound
145};
146
147typedef struct Pair
148{
149    const void *key;
150    const void *value;
151} Pair;
152
153/* Nothing in this struct is retained since all the
154 values below are extracted from the dictionary passed in by the
155 caller. */
156typedef struct Query
157{
158    /* Class of this query. */
159    const SecDbClass *q_class;
160
161    /* Dictionary with all attributes and values in clear (to be encrypted). */
162    CFMutableDictionaryRef q_item;
163
164    /* q_pairs is an array of Pair structs.  Elements with indices
165     [0, q_attr_end) contain attribute key value pairs.  Elements with
166     indices [q_match_begin, q_match_end) contain match key value pairs.
167     Thus q_attr_end is the number of attrs in q_pairs and
168     q_match_begin - q_match_end is the number of matches in q_pairs.  */
169    CFIndex q_match_begin;
170    CFIndex q_match_end;
171    CFIndex q_attr_end;
172
173    CFErrorRef q_error;
174    ReturnTypeMask q_return_type;
175
176    CFDataRef q_data;
177    CFTypeRef q_ref;
178    sqlite_int64 q_row_id;
179
180    CFArrayRef q_use_item_list;
181    CFBooleanRef q_use_tomb;
182#if defined(MULTIPLE_KEYCHAINS)
183    CFArrayRef q_use_keychain;
184    CFArrayRef q_use_keychain_list;
185#endif /* !defined(MULTIPLE_KEYCHAINS) */
186
187    /* Value of kSecMatchLimit key if present. */
188    CFIndex q_limit;
189
190    /* True if query contained a kSecAttrSynchronizable attribute,
191     * regardless of its actual value. If this is false, then we
192     * will add an explicit sync=0 to the query. */
193    bool q_sync;
194
195    // Set to true if we modified any item as part of executing this query
196    bool q_changed;
197
198    // Set to true if we modified any synchronizable item as part of executing this query
199    bool q_sync_changed;
200
201    /* Keybag handle to use for this item. */
202    keybag_handle_t q_keybag;
203    keyclass_t q_keyclass;
204    //CFStringRef q_keyclass_s;
205
206    // SHA1 digest of DER encoded primary key
207    CFDataRef q_primary_key_digest;
208
209    CFArrayRef q_match_issuer;
210
211    /* Store all the corrupted rows found during the query */
212    CFMutableArrayRef corrupted_rows;
213
214    Pair q_pairs[];
215} Query;
216
217
218#define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr))
219
220#define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask))
221
222// MARK: Stuff that needs to move out of SecItemServer.c
223
224// Move this or do crypto in a block
225bool ks_encrypt_data(keybag_handle_t keybag, keyclass_t keyclass, CFDataRef plainText, CFDataRef *pBlob, CFErrorRef *error);
226bool ks_decrypt_data(keybag_handle_t keybag, keyclass_t *pkeyclass, CFDataRef blob, CFDataRef *pPlainText,
227                            uint32_t *version_p, CFErrorRef *error);
228
229CFDataRef kc_copy_sha1(size_t len, const void *data, CFErrorRef *error);
230CFDataRef kc_copy_plist_sha1(CFPropertyListRef plist, CFErrorRef *error);
231CFDataRef kc_plist_copy_der(CFPropertyListRef plist, CFErrorRef *error);
232Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, CFErrorRef *error);
233bool query_destroy(Query *q, CFErrorRef *error);
234
235// MARK: SecDbItem
236
237typedef struct SecDbItem *SecDbItemRef;
238
239enum SecDbItemState {
240    kSecDbItemDirty,          // We have no edata (or if we do it's invalid), attributes are the truth
241    kSecDbItemEncrypted,      // Attributes haven't been decrypted yet from edata
242    kSecDbItemClean,          // Attributes and _edata are in sync.
243    kSecDbItemDecrypting,     // Temporary state while we are decrypting so set knows not to blow away the edata.
244    kSecDbItemEncrypting,     // Temporary state while we are encrypting so set knows to move to clean.
245};
246
247struct SecDbItem {
248    CFRuntimeBase _base;
249    const SecDbClass *class;
250    keyclass_t keyclass;
251    keybag_handle_t keybag;
252    //sqlite3_int64 _rowid;
253    //CFDataRef _primaryKey;
254    //CFDataRef _sha1;
255    //CFDataRef _edata;
256    enum SecDbItemState _edataState;
257    CFMutableDictionaryRef attributes;
258};
259
260// TODO: Make this a callback to client
261bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFErrorRef *error);
262
263CFTypeID SecDbItemGetTypeID(void);
264
265static inline size_t SecDbClassAttrCount(const SecDbClass *dbClass) {
266    size_t n_attrs = 0;
267    SecDbForEachAttr(dbClass, attr) { n_attrs++; }
268    return n_attrs;
269}
270
271const SecDbAttr *SecDbClassAttrWithKind(const SecDbClass *class, SecDbAttrKind kind, CFErrorRef *error);
272
273SecDbItemRef SecDbItemCreateWithAttributes(CFAllocatorRef allocator, const SecDbClass *class, CFDictionaryRef attributes, keybag_handle_t keybag, CFErrorRef *error);
274
275const SecDbClass *SecDbItemGetClass(SecDbItemRef item);
276const keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item);
277bool SecDbItemSetKeybag(SecDbItemRef item, keybag_handle_t keybag, CFErrorRef *error);
278keyclass_t SecDbItemGetKeyclass(SecDbItemRef item, CFErrorRef *error);
279bool SecDbItemSetKeyclass(SecDbItemRef item, keyclass_t keyclass, CFErrorRef *error);
280
281CFTypeRef SecDbItemGetCachedValueWithName(SecDbItemRef item, CFStringRef name);
282CF_RETURNS_NOT_RETAINED CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error);
283
284bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value, CFErrorRef *error);
285bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error);
286bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error);
287
288sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error);
289bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error);
290
291bool SecDbItemIsSyncable(SecDbItemRef item);
292
293bool SecDbItemSetSyncable(SecDbItemRef item, bool sync, CFErrorRef *error);
294
295bool SecDbItemIsTombstone(SecDbItemRef item);
296
297CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error);
298
299CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error);
300CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error);
301
302CFDataRef SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item, uint64_t handle, CFErrorRef *error);
303
304SecDbItemRef SecDbItemCreateWithStatement(CFAllocatorRef allocator, const SecDbClass *class, sqlite3_stmt *stmt, keybag_handle_t keybag, CFErrorRef *error, bool (^return_attr)(const SecDbAttr *attr));
305
306SecDbItemRef SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator, const SecDbClass *class,
307                                              CFDataRef edata, keybag_handle_t keybag, CFErrorRef *error);
308
309SecDbItemRef SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator, const SecDbClass *class, CFDataRef primary_key);
310
311#if 0
312SecDbItemRef SecDbItemCreateWithRowId(CFAllocatorRef allocator, const SecDbClass *class, sqlite_int64 row_id, keybag_handle_t keybag, CFErrorRef *error);
313#endif
314
315SecDbItemRef SecDbItemCopyWithUpdates(SecDbItemRef item, CFDictionaryRef updates, CFErrorRef *error);
316
317SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFErrorRef *error);
318
319bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace));
320
321bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error);
322
323bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error);
324
325// Low level update, just do the update
326bool SecDbItemDoUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, CFErrorRef *error, bool (^use_attr_in_where)(const SecDbAttr *attr));
327
328// High level update, will replace tombstones and create them if needed.
329bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error);
330
331bool SecDbItemSelect(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef *error,
332                     bool (^use_attr_in_where)(const SecDbAttr *attr),
333                     bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere),
334                     bool (^bind_added_where)(sqlite3_stmt *stmt, int col),
335                     void (^handle_row)(SecDbItemRef item, bool *stop));
336
337CFStringRef SecDbItemCopySelectSQL(SecDbQueryRef query,
338                                   bool (^return_attr)(const SecDbAttr *attr),
339                                   bool (^use_attr_in_where)(const SecDbAttr *attr),
340                                   bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere));
341bool SecDbItemSelectBind(SecDbQueryRef query, sqlite3_stmt *stmt, CFErrorRef *error,
342                         bool (^use_attr_in_where)(const SecDbAttr *attr),
343                         bool (^bind_added_where)(sqlite3_stmt *stmt, int col));
344
345
346// MARK: -
347// MARK: SQL Construction helpers -- These should become private in the future
348
349void SecDbAppendElement(CFMutableStringRef sql, CFStringRef value, bool *needComma);
350void SecDbAppendWhereOrAnd(CFMutableStringRef sql, bool *needWhere);
351void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql, CFStringRef col, bool *needWhere);
352
353// MARK: -
354// MARK: SecItemDb (a SecDb of SecDbItems)
355
356typedef struct SecItemDb *SecItemDbRef;
357typedef struct SecItemDbConnection *SecItemDbConnectionRef;
358
359struct SecItemDb {
360    CFRuntimeBase _base;
361    SecDbRef db;
362    CFDictionaryRef classes; // className -> SecItemClass mapping
363};
364
365struct SecItemDbConnection {
366    SecDbConnectionRef db;
367};
368
369SecItemDbRef SecItemDbCreate(SecDbRef db);
370SecItemDbRef SecItemDbRegisterClass(SecItemDbRef db, const SecDbClass *class, void(^upgrade)(SecDbItemRef item, uint32_t current_version));
371
372SecItemDbConnectionRef SecItemDbAquireConnection(SecItemDbRef db);
373void SecItemDbReleaseConnection(SecItemDbRef db, SecItemDbConnectionRef dbconn);
374
375bool SecItemDbInsert(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error);
376
377bool SecItemDbDelete(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error);
378
379// Low level update, just do the update
380bool SecItemDbDoUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error,
381                       bool (^use_attr_in_where)(const SecDbAttr *attr));
382
383// High level update, will replace tombstones and create them if needed.
384bool SecItemDbUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error);
385
386bool SecItemDbSelect(SecItemDbConnectionRef dbconn, SecDbQueryRef query, CFErrorRef *error,
387                     bool (^use_attr_in_where)(const SecDbAttr *attr),
388                     bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere),
389                     bool (^bind_added_where)(sqlite3_stmt *stmt, int col),
390                     void (^handle_row)(SecDbItemRef item, bool *stop));
391
392// MARK: type converters.
393// TODO: these should be static and private to SecDbItem, or part of the schema
394
395CFStringRef copyString(CFTypeRef obj);
396CFDataRef copyData(CFTypeRef obj);
397CFTypeRef copyBlob(CFTypeRef obj);
398CFDataRef copySHA1(CFTypeRef obj);
399CFTypeRef copyNumber(CFTypeRef obj);
400CFDateRef copyDate(CFTypeRef obj);
401
402__END_DECLS
403
404#endif /* _SECURITYD_SECDBITEM_H_ */
405