2  * Copyright (c) 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  * SOSBackupEvent.c -  Implementation of a secure object syncing peer 
  28 #include <Security/SecureObjectSync/SOSBackupEvent.h> 
  29 #include <corecrypto/ccsha1.h> 
  30 #include <utilities/SecCFError.h> 
  31 #include <utilities/SecCFRelease.h> 
  32 #include <utilities/array_size.h> 
  33 #include <utilities/der_plist.h> 
  34 #include <utilities/der_plist_internal.h> 
  35 #include <AssertMacros.h> 
  42     Event ASN.1 definitions 
  44 ResetEvent := SEQUENCE { 
  45     keybag OCTET STRING OPTIONAL 
  63 DeleteEvent := OCTET STRING 
  65 CompleteEvent := INTEGER 
  71     complete CompleteEvent 
  76 static size_t der_sizeof_backup_reset(CFDataRef keybag
) { 
  77     return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
  78         keybag 
? ccder_sizeof_raw_octet_string(CFDataGetLength(keybag
)) : 0); 
  81 static uint8_t* der_encode_backup_reset(CFDataRef keybag
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) { 
  82     return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
  83         keybag 
? ccder_encode_raw_octet_string(CFDataGetLength(keybag
), CFDataGetBytePtr(keybag
), der
, der_end
) : der_end
); 
  86 static size_t der_sizeof_backup_add(CFDictionaryRef add
) { 
  87     return der_sizeof_dictionary(add
, NULL
); 
  90 static uint8_t* der_encode_backup_add(CFDictionaryRef add
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) { 
  91     // der_dictionary tag is CCDER_CONSTRUCTED_SET 
  92     return der_encode_dictionary(add
, error
, der
, der_end
); 
  95 static size_t der_sizeof_backup_delete(CFDataRef deletedDigest
) { 
  96     return ccder_sizeof_raw_octet_string(CFDataGetLength(deletedDigest
)); 
  99 static uint8_t* der_encode_backup_delete(CFDataRef deletedDigest
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) { 
 100     return ccder_encode_raw_octet_string(CFDataGetLength(deletedDigest
), CFDataGetBytePtr(deletedDigest
), der
, der_end
); 
 103 static size_t der_sizeof_backup_complete(uint64_t event_num
) { 
 104     return ccder_sizeof_uint64(event_num
); 
 107 static uint8_t* der_encode_backup_complete(uint64_t event_num
, CFErrorRef
* error
, const uint8_t* der
, uint8_t* der_end
) { 
 108     return ccder_encode_uint64(event_num
, der
, der_end
); 
 116 static bool SOSBackupEventWrite(FILE *journalFile
, CFErrorRef 
*error
, 
 118                                 uint8_t *(^encode
)(const uint8_t *der
, uint8_t *der_end
)) 
 121     CFMutableDataRef derObject 
= CFDataCreateMutable(kCFAllocatorDefault
, len
); 
 122     CFDataSetLength(derObject
, len
); 
 123     uint8_t *der_end 
= CFDataGetMutableBytePtr(derObject
); 
 124     const uint8_t *der 
= der_end
; 
 127     require(der_end 
= encode(der
, der_end
), xit
); 
 128     require_action(der 
== der_end
, xit
, SecError(-1, error
, CFSTR("size mismatch der: %zu der_end: %zu"))); 
 130     ok 
= SecCheckErrno(1 != fwrite(der
, len
, 1, journalFile
), error
, CFSTR("fwrite %s"), journalFile
); 
 132     CFReleaseSafe(derObject
); 
 136 bool SOSBackupEventWriteReset(FILE *journalFile
, CFDataRef keybag
, CFErrorRef 
*error
) { 
 137     return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_reset(keybag
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) { 
 138         return der_encode_backup_reset(keybag
, error
, der
, der_end
); 
 142 bool SOSBackupEventWriteDelete(FILE *journalFile
, CFDataRef deletedDigest
, CFErrorRef 
*error
) { 
 143     return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_delete(deletedDigest
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) { 
 144         return der_encode_backup_delete(deletedDigest
, error
, der
, der_end
); 
 148 bool SOSBackupEventWriteAdd(FILE *journalFile
, CFDictionaryRef backup_item
, CFErrorRef 
*error
) { 
 149     return SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_add(backup_item
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) { 
 150         return der_encode_backup_add(backup_item
, error
, der
, der_end
); 
 154 bool SOSBackupEventWriteCompleteMarker(FILE *journalFile
, uint64_t eventID
, CFErrorRef 
*error
) { 
 155     bool ok 
= SOSBackupEventWrite(journalFile
, error
, der_sizeof_backup_complete(eventID
), ^uint8_t *(const uint8_t *der
, uint8_t *der_end
) { 
 156         return der_encode_backup_complete(eventID
, error
, der
, der_end
); 
 158     // TODO: Move this to right before we send a notification or something.