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