2  * Copyright (c) 2013-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  * SOSMessage.c -  Creation and decoding of SOSMessage objects. 
  29 #include "keychain/SecureObjectSync/SOSMessage.h" 
  31 #include <AssertMacros.h> 
  32 #include <CoreFoundation/CoreFoundation.h> 
  33 #include "keychain/SecureObjectSync/SOSDigestVector.h" 
  34 #include "keychain/SecureObjectSync/SOSManifest.h" 
  35 #include "keychain/SecureObjectSync/SOSInternal.h" 
  36 #include <corecrypto/ccder.h> 
  39 #include <utilities/SecCFError.h> 
  40 #include <utilities/SecCFRelease.h> 
  41 #include <utilities/SecCFWrappers.h> 
  42 #include <utilities/array_size.h> 
  43 #include <utilities/der_date.h> 
  44 #include <utilities/der_plist.h> 
  45 #include <utilities/der_plist_internal.h> 
  46 #include <utilities/debugging.h> 
  47 #include <utilities/iCloudKeychainTrace.h> 
  49 // TODO: This is a layer violation, we need a better way to do this 
  50 // Currently it's only used for logging. 
  51 #include <securityd/SecItemDataSource.h> 
  53 #if defined(SOSMessageFormatSpecification) && 0 
  55 -- Secure Object Syncing Peer to Peer Message format ASN
.1 definition
 
  56 -- Everything MUST be DER encoded unless otherwise noted
.  These exceptions
 
  57 -- Allow us to stream messages on a streamy network
, without loading more
 
  58 -- than one object into memory at once
. 
  60 SOSMessage 
:= SEQUENCE 
{ 
  62         v0          V0
-MESSAGE
-BODY
-CLASS
 
  69 V0
-MESSAGE
-BODY
-CLASS ::= CLASS
 
  71      &messageType    
INTEGER (manifestDigest
, manifest
, manifestDeltaAndObjects
) 
  72      &version        INTEGER OPTIONAL 
default v0
 
  75     WITH SYNTAX 
{&Type IDENTIFIED BY 
&messageType
} 
  77 ManifestDigest ::= OCTECT 
STRING (length 
20) 
  79 Manifest ::= OCTECT STRING 
-- (length 
20 * number of entries
) 
  81 manifestDigestBody ::= 
  82     { ManifestDigest IDENTIFIED BY 
{manifestDigest
}} 
  85     { Manifest IDENTIFIED BY 
{manifest
}} 
  87  manifestDeltaAndObjectsBody ::= 
  88     { ManifestDeltaAndObjects IDENTIFIED BY 
{manifestDeltaAndObjects
}} 
  90 SOSV1MessageBody ::= MESSAGE
-BODY
-CLASS
 
  92 ManifestDeltaAndObjects ::= SEQUENCE 
{ 
  93      manfestDigest ManifestDigest
 
  96      addedObjects SEQUENCE OF SOSObject
 
 102     -- top level SEQUENCE may be Constructed
, indefinite
-length BER encoded
 
 103     header         SOSMessageHeader
, 
 104     deltas         
[0] IMPLICIT SOSManifestDeltas OPTIONAL
, 
 105     extensions     
[1] IMPLICIT SOSExtensions OPTIONAL
, 
 106     objects        
[2] IMPLICIT SEQUENCE OF SOSObject OPTIONAL
 
 107         -- [2] IMPLICIT SEQUENCE OF SOSObject may be Constructed
, 
 108         -- indefinite
-length BER encoded 
-- } 
 110 SOSMessageHeader ::= SEQUENCE 
{ 
 111     version         
[0] IMPLICIT SOSMessageVersion DEFAULT v2
, 
 112     creationTime    GeneralizedTime OPTIONAL
, 
 113         -- When 
this message was created by the sender 
for tracking latency
 
 114     sequenceNumber  SOSSequenceNumber OPTIONAL
, 
 115         -- Message Sequence Number 
for tracking packet loss in transport
 
 116     digestTypes     SOSDigestTypes OPTIONAL
, 
 117         -- Determines the size 
and format of each SOSManifestDigest 
and the
 
 118         -- elements of each SOSManifest
. 
 119         -- We send the intersection our desired SOSDigestTypes 
and our peers
 
 120         -- last received SOSDigestType
. If we never received a message from our
 
 121         -- peer we send our entire desired set 
and set the digestTypesProposed
 
 123         -- If the intersection is the empty set we fallback to sha1
 
 124         -- Each digest 
and manifest entry is constructed by appending the
 
 125         -- agreed upon digests in the order they are listed in the DER encoded
 
 127     messageFlags    BIT STRING 
{ 
 131         digestTypesProposed                 (3), 
 132             -- This is a partial update 
and might 
not contain accurate manifest 
deltas (check 
this against spec 
--mb
), only objects
 
 133         clearGetObjects                     (4), -- WIP mb ignore
 
 134             -- Stop sending me objects 
for this delta update
, I will send you mine instead 
if you give me a full manifest delta
 
 135         didClearGetObjectsSinceLastDelta    (5)  -- WIP mb ignore
 
 136             -- clearGetObjects was set during 
this delta update
, do not 
 137             -- set it 
again (STICKY until either peer clears delta
) -- } 
 138         skipHello                           (6)  -- Respond with at least a manifest
 
 139     senderDigest    SOSManifestDigest
, 
 140         -- The senders manifest digest at the time of sending 
this message
. 
 141     baseDigest      
[0] IMPLICIT SOSManifestDigest
, 
 142         -- What 
this message is based on
, if it contains deltas
.  If missing we assume the empty set
 
 143     proposedDigest  
[1] IMPLICIT SOSManifestDigest
, 
 144         -- What the receiver should have after patching baseDigest with
 
 145         -- additions 
and removals 
-- } 
 147 SOSMessageVersion ::= INTEGER 
{ v0(0), v2(2), v3(3) } 
 149 SOSSequenceNumber ::= INTEGER
 
 151 -- Note 
this is 
not implemented in v2 it only supports sha1
 
 152 SOSDigestTypes ::= SEQUENCE 
{ 
 153     messageFlags    BIT STRING 
{ 
 154         sha1(0) -- implied 
if SOSDigestTypes is 
not present
 
 159             digestAlgorithms SET OF AlgorithmIdentifier
 
 160             -- Same as AlgorithmIdentifier from X
.509 -- } } 
 162 SOSManifestDeltas ::= SEQUENCE 
{ 
 164     additions   SOSManifest 
} 
 166 SOSExtensions ::= SEQUENCE 
SIZE (1..MAX
) OF SOSExtension
 
 168 SOSExtension ::= SEQUENCE 
{ 
 169     extnID      OBJECT IDENTIFIER
, 
 170     critical    BOOLEAN DEFAULT FALSE
, 
 171     extnValue   OCTET STRING 
} 
 173 SOSManifest ::= OCTET STRING
 
 174     -- DER encoding is sorted 
and ready to merge
. 
 175     -- All SOSDigest entries in a SOSManifest 
/must
/ be the same size
 
 176     -- As the negotiated SOSManifestEntry
.  Se comment in SOSMessageBody
 
 179 SOSManifestDigest  ::= OCTET STRING
 
 181 SOSObject ::= SEQUENCE 
{ 
 182     [0] conflict OCTECT STRING OPTIONAL
 
 183     [1] change OCTECT STRING OPTIONAL
 
 184     object SecDictionary 
} 
 186 SecDictionary ::= SET of SecKVPair
 
 188 SecKVPair ::= SEQUENCE 
{ 
 192 SecValue ::= CHOICE 
{ 
 201 SecArray ::= SEQUENCE of SecValue
 
 204 AlgorithmIdentifier ::= SEQUENCE 
{ 
 205 algorithm        OBJECT IDENTIFIER
, 
 206 parameters       ANY DEFINED BY algorithm OPTIONAL 
} 
 207 -- contains a value of the type
 
 208 -- registered 
for use with the
 
 209 -- algorithm object identifier value
 
 211 #endif // defined(SOSMessageFormatSpecification) && 0 
 215 static inline bool SecMallocOk(const void *ptr
) { 
 216     if (ptr
) return true; 
 222 static void appendObjects(CFMutableStringRef desc
, CFArrayRef objects
) { 
 223     __block 
bool needComma 
= false; 
 224     CFArrayForEach(objects
, ^(const void *value
) { 
 226             CFStringAppend(desc
, CFSTR(",")); 
 230         SecItemServerAppendItemDescription(desc
, value
); 
 238 // MARK: SOSMessage implementation. 
 241 // Legacy v1 message type numbers 
 242 enum SOSMessageType 
{ 
 243     SOSManifestInvalidMessageType 
= 0, 
 244     SOSManifestDigestMessageType 
= 1, 
 245     SOSManifestMessageType 
= 2, 
 246     SOSManifestDeltaAndObjectsMessageType 
= 3, 
 249 struct __OpaqueSOSMessage 
{ 
 253     const uint8_t *objectsDer
; 
 256     CFDataRef senderDigest
; 
 257     CFDataRef baseDigest
; 
 258     CFDataRef proposedDigest
; 
 259     SOSManifestRef removals
; 
 260     SOSManifestRef additions
; 
 262     CFMutableArrayRef objects
; 
 264     SOSMessageFlags flags
; 
 265     uint64_t sequenceNumber
; 
 266     CFAbsoluteTime creationTime
; 
 267     uint64_t version
;               // Message version (currently always 2) 
 268     bool indefiniteLength
;          // If set to true the top SEQUENCE and the OBJECTS SEQUENCE are written indefinite length. 
 271 CFGiblisWithCompareFor(SOSMessage
) 
 273 static Boolean 
SOSMessageCompare(CFTypeRef cf1
, CFTypeRef cf2
) { 
 274     SOSMessageRef M 
= (SOSMessageRef
)cf1
; 
 275     SOSMessageRef P 
= (SOSMessageRef
)cf2
; 
 276     if (M
->flags 
!= P
->flags
) return false; 
 277     if (M
->sequenceNumber 
!= P
->sequenceNumber
) return false; 
 278     if (M
->creationTime 
!= P
->creationTime
) return false; 
 279     //if (!CFEqualSafe(M->der, P->der)) return false; 
 280     if (!CFEqualSafe(M
->senderDigest
, P
->senderDigest
)) return false; 
 281     if (!CFEqualSafe(M
->baseDigest
, P
->baseDigest
)) return false; 
 282     if (!CFEqualSafe(M
->proposedDigest
, P
->proposedDigest
)) return false; 
 283     if (!CFEqualSafe(M
->removals
, P
->removals
)) return false; 
 284     if (!CFEqualSafe(M
->additions
, P
->additions
)) return false; 
 286     // TODO Compare Objects if present. 
 291 static void SOSMessageDestroy(CFTypeRef cf
) { 
 292     SOSMessageRef message 
= (SOSMessageRef
)cf
; 
 293     CFReleaseNull(message
->der
); 
 294     CFReleaseNull(message
->senderDigest
); 
 295     CFReleaseNull(message
->baseDigest
); 
 296     CFReleaseNull(message
->proposedDigest
); 
 297     CFReleaseNull(message
->additions
); 
 298     CFReleaseNull(message
->removals
); 
 299     CFReleaseNull(message
->objects
); 
 302 // TODO: Remove this layer violation! 
 303 #include <securityd/SecItemServer.h> 
 305 static uint64_t SOSMessageInferType(SOSMessageRef message
, CFErrorRef 
*error
); 
 307 static CFStringRef 
SOSMessageCopyFormatDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) { 
 308     SOSMessageRef message 
= (SOSMessageRef
)cf
; 
 309     static const uint8_t zero
[4] = {}; 
 310     const uint8_t *S 
= message
->senderDigest 
? CFDataGetBytePtr(message
->senderDigest
) : zero
; 
 311     const uint8_t *B 
= message
->baseDigest 
? CFDataGetBytePtr(message
->baseDigest
) : zero
; 
 312     const uint8_t *P 
= message
->proposedDigest 
? CFDataGetBytePtr(message
->proposedDigest
) : zero
; 
 313     CFDateRef creationDate 
= CFDateCreate(CFGetAllocator(message
), message
->creationTime
); 
 315     CFMutableStringRef objects 
= CFStringCreateMutable(kCFAllocatorDefault
, 0); 
 317     // TODO: Remove this layer violation! 
 318     SOSDataSourceFactoryRef dsf 
= SecItemDataSourceFactoryGetDefault(); 
 319     SOSDataSourceRef ds 
= SOSDataSourceFactoryCreateDataSource(dsf
, kSecAttrAccessibleWhenUnlocked
, NULL
); 
 322         __block 
size_t maxEntries 
= 16; 
 323         CFStringAppendFormat(objects
, NULL
, CFSTR("{[%zu]"), SOSMessageCountObjects(message
)); 
 324         SOSMessageWithSOSObjects(message
, ds
, NULL
, ^(SOSObjectRef object
, bool *stop
) { 
 325             CFDataRef digest 
= SOSObjectCopyDigest(ds
, object
, NULL
); 
 326             const uint8_t *O 
= CFDataGetBytePtr(digest
); 
 327             CFStringAppendFormat(objects
, NULL
, CFSTR(" %02X%02X%02X%02X"), O
[0],O
[1],O
[2],O
[3]); 
 328             CFReleaseSafe(digest
); 
 330                 CFStringAppend(objects
, CFSTR("...")); 
 334         CFStringAppend(objects
, CFSTR("}")); 
 336         CFStringAppend(objects
, CFSTR("{NO DATASOURCE}")); 
 339     CFStringRef desc 
= NULL
; 
 340     if (message
->version 
== 0) { 
 341         switch (SOSMessageInferType(message
, NULL
)) { 
 342             case SOSManifestInvalidMessageType
: 
 343                 desc 
= CFStringCreateWithFormat(CFGetAllocator(message
), NULL
, CFSTR("<MSGInvalid %"PRIu64
" >"), message
->sequenceNumber
); 
 345             case SOSManifestDigestMessageType
: 
 346                 desc 
= CFStringCreateWithFormat(CFGetAllocator(message
), NULL
, CFSTR("<MSGDigest %"PRIu64
" %02X%02X%02X%02X>"), message
->sequenceNumber
, S
[0],S
[1],S
[2],S
[3]); 
 348             case SOSManifestMessageType
: 
 349                 desc 
= CFStringCreateWithFormat(CFGetAllocator(message
), NULL
, CFSTR("<MSGManifest %"PRIu64
" %@>"), message
->sequenceNumber
, message
->additions
); 
 351             case SOSManifestDeltaAndObjectsMessageType
: 
 352                 desc 
= CFStringCreateWithFormat(CFGetAllocator(message
), NULL
, CFSTR("<MSGObjects %"PRIu64
" %02X%02X%02X%02X %@ %@ %@"), 
 353                                                 message
->sequenceNumber
, 
 355                                                 message
->removals
, message
->additions
, 
 360         desc 
= CFStringCreateWithFormat
 
 361         (CFGetAllocator(message
), NULL
, CFSTR("<MSG %"PRIu64
" %@ %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %@ %@ %@ %s%s%s%s%s%s%s>"), 
 362         message
->sequenceNumber
, 
 367         message
->removals
, message
->additions
, 
 369         (message
->flags 
& kSOSMessageGetObjects
) ? "G" : "g", 
 370         (message
->flags 
& kSOSMessageJoinRequest
) ? "J" : "j", 
 371         (message
->flags 
& kSOSMessagePartial
) ? "P" : "p", 
 372         (message
->flags 
& kSOSMessageDigestTypesProposed
) ? "D" : "d", 
 373         (message
->flags 
& kSOSMessageClearGetObjects
) ? "K" : "k", 
 374         (message
->flags 
& kSOSMessageDidClearGetObjectsSinceLastDelta
) ? "Z" : "z", 
 375         (message
->flags 
& kSOSMessageSkipHello
) ? "H" : "h"); 
 377     CFReleaseSafe(creationDate
); 
 378     CFReleaseSafe(objects
); 
 383 // MARK: SOSMessage encoding 
 386 // Create an SOSMessage ready to be encoded. 
 387 SOSMessageRef 
SOSMessageCreate(CFAllocatorRef allocator
, uint64_t version
, CFErrorRef 
*error
) { 
 388     SOSMessageRef message 
= CFTypeAllocate(SOSMessage
, struct __OpaqueSOSMessage
, allocator
); 
 389     message
->version 
= version
; 
 393 // TODO: Remove me this is for testing only, tests should use the real thing. 
 394 SOSMessageRef 
SOSMessageCreateWithManifests(CFAllocatorRef allocator
, SOSManifestRef sender
, 
 395                                             SOSManifestRef base
, SOSManifestRef proposed
, 
 396                                             bool includeManifestDeltas
, CFErrorRef 
*error
) { 
 397     SOSMessageRef message 
= SOSMessageCreate(allocator
, kEngineMessageProtocolVersion
, error
); 
 398     if (!SOSMessageSetManifests(message
, sender
, base
, proposed
, includeManifestDeltas
, NULL
, error
)) 
 399         CFReleaseNull(message
); 
 403 bool SOSMessageSetManifests(SOSMessageRef message
, SOSManifestRef sender
, 
 404                             SOSManifestRef base
, SOSManifestRef proposed
, 
 405                             bool includeManifestDeltas
, SOSManifestRef objectsSent
, 
 407     if (!message
) return true; 
 409     // TODO: Check at v2 encoding time 
 410     // if (!sender) return (SOSMessageRef)SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("no sender manifest specified for SOSMessage")); 
 411     message
->baseDigest 
= CFRetainSafe(SOSManifestGetDigest(base
, NULL
)); 
 412     secinfo("engine", "SOSMessageSetManifests: setting base digest to %@ %zu", message
->baseDigest
, SOSManifestGetCount(base
)); 
 413     message
->proposedDigest 
= CFRetainSafe(SOSManifestGetDigest(proposed
, NULL
)); 
 414     secinfo("engine", "SOSMessageSetManifests: setting proposed digest to %@ %zu", message
->proposedDigest
, SOSManifestGetCount(proposed
)); 
 415     message
->senderDigest 
= CFRetainSafe(SOSManifestGetDigest(sender
, NULL
)); 
 416     secinfo("engine", "SOSMessageSetManifests: setting sender digest to %@ %zu", message
->senderDigest
, SOSManifestGetCount(sender
)); 
 418     if (includeManifestDeltas
) { 
 419         SOSManifestRef additions 
= NULL
; 
 420         ok 
= SOSManifestDiff(base
, proposed
, &message
->removals
, &additions
, error
); 
 421         if (message
->version 
== 0) { 
 422             message
->additions 
= additions
; 
 424             message
->additions 
= SOSManifestCreateComplement(objectsSent
, additions
, error
); 
 425             CFReleaseSafe(additions
); 
 431 void SOSMessageSetFlags(SOSMessageRef message
, SOSMessageFlags flags
) { 
 432     message
->flags 
= flags
; 
 435 // Add an extension to this message 
 436 void SOSMessageAddExtension(SOSMessageRef message
, CFDataRef oid
, bool isCritical
, CFDataRef extension
) { 
 438     secerror("not implemented yet!"); 
 441 static bool SecMessageIsObjectValid(CFDataRef object
, CFErrorRef 
*error
) { 
 442     const uint8_t *der 
= CFDataGetBytePtr(object
); 
 443     const uint8_t *der_end 
= der 
+ CFDataGetLength(object
); 
 446     der 
= ccder_decode_tag(&tag
, der
, der_end
); 
 448         return SOSErrorCreate(kSOSErrorBadFormat
, error
, NULL
, CFSTR("Invalid DER, no tag found")); 
 449     if (tag 
== CCDER_EOL
) 
 450         return SOSErrorCreate(kSOSErrorBadFormat
, error
, NULL
, CFSTR("Object has EOL tag")); 
 451     der 
= ccder_decode_len(&len
, der
, der_end
); 
 453         return SOSErrorCreate(kSOSErrorBadFormat
, error
, NULL
, CFSTR("Object with tag %lu has no valid DER length"), tag
); 
 456         return SOSErrorCreate(kSOSErrorBadFormat
, error
, NULL
, CFSTR("Object has %td trailing unused bytes"), der_end 
- der
); 
 460 bool SOSMessageAppendObject(SOSMessageRef message
, CFDataRef object
, CFErrorRef 
*error
) { 
 461     if (!SecMessageIsObjectValid(object
, error
)) return false; 
 462     if (!message
->objects
) 
 463         message
->objects 
= CFArrayCreateMutableForCFTypes(CFGetAllocator(message
)); 
 464     if (message
->objects
) 
 465         CFArrayAppendValue(message
->objects
, object
); 
 469 static CC_NONNULL_ALL
 
 470 size_t ccder_sizeof_bit_string(cc_size n
, const cc_unit 
*s
) { 
 471     return ccder_sizeof(CCDER_BIT_STRING
, ccn_sizeof(ccn_bitlen(n
, s
)) + 1); 
 474 static CC_NONNULL_ALL
 
 475 uint8_t *ccder_encode_bit_string(cc_size n
, const cc_unit 
*s
, const uint8_t *der
, uint8_t *der_end
) { 
 476     size_t bits 
= ccn_bitlen(n
, s
); 
 477     size_t out_size 
= ccn_sizeof(bits
) + 1; 
 478     der_end 
= ccder_encode_body_nocopy(out_size
, der
, der_end
); 
 480         ccn_write_uint_padded(n
, s
, out_size
, der_end
); 
 481     return ccder_encode_tl(CCDER_BIT_STRING
, out_size
, der
, der_end
); 
 486 size_t der_sizeof_implicit_data(ccder_tag tag
, CFDataRef data
) { 
 489     return ccder_sizeof_implicit_raw_octet_string(tag
, CFDataGetLength(data
)); 
 493 static CC_NONNULL((3, 4)) 
 494 uint8_t *der_encode_implicit_data(ccder_tag tag
, CFDataRef data
, const uint8_t *der
, uint8_t *der_end
) { 
 497     return ccder_encode_implicit_raw_octet_string(tag
, CFDataGetLength(data
), CFDataGetBytePtr(data
), der
, der_end
); 
 500 static size_t der_sizeof_message_header(SOSMessageRef message
, CFErrorRef 
*error
) { 
 501     if (!message
->senderDigest
) { 
 502         // TODO: Create Error. 
 506     flags
[0] = (cc_unit
)message
->flags
; // TODO Fix cast or something 
 508     return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
 509         der_sizeof_generalizedtime(message
->creationTime
, error
) + 
 510         ccder_sizeof_uint64(message
->sequenceNumber
) + 
 511         ccder_sizeof_bit_string(array_size(flags
), flags
) + 
 512         der_sizeof_implicit_data(CCDER_OCTET_STRING
, message
->senderDigest
) + 
 513         der_sizeof_implicit_data(0 | CCDER_CONTEXT_SPECIFIC
, message
->baseDigest
) + 
 514         der_sizeof_implicit_data(1 | CCDER_CONTEXT_SPECIFIC
, message
->proposedDigest
)); 
 517 static uint8_t *der_encode_message_header(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 518     if (!message
->senderDigest
) { 
 519         // TODO: Create Error. 
 523     flags
[0] = (cc_unit
)message
->flags
; // TODO Fix cast or something 
 524     return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
 525         der_encode_generalizedtime(message
->creationTime
, error
, der
, 
 526         ccder_encode_uint64(message
->sequenceNumber
, der
, 
 527         ccder_encode_bit_string(array_size(flags
), flags
, der
, 
 528         der_encode_implicit_data(CCDER_OCTET_STRING
, message
->senderDigest
, der
, 
 529         der_encode_implicit_data(0 | CCDER_CONTEXT_SPECIFIC
, message
->baseDigest
, der
, 
 530         der_encode_implicit_data(1 | CCDER_CONTEXT_SPECIFIC
, message
->proposedDigest
, der
, der_end
))))))); 
 533 static size_t der_sizeof_deltas(SOSMessageRef message
) { 
 534     if (!message
->additions 
&& !message
->removals
) return 0; 
 535     if (message
->version 
== 0) { 
 536         return ccder_sizeof(CCDER_OCTET_STRING
, SOSManifestGetSize(message
->removals
))+ 
 537                ccder_sizeof(CCDER_OCTET_STRING
, SOSManifestGetSize(message
->additions
)); 
 539         return ccder_sizeof(0 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, 
 540                             ccder_sizeof(CCDER_OCTET_STRING
, SOSManifestGetSize(message
->removals
))+ 
 541                             ccder_sizeof(CCDER_OCTET_STRING
, SOSManifestGetSize(message
->additions
))); 
 545 static uint8_t *der_encode_deltas(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 546     if (!message
->additions 
&& !message
->removals
) return der_end
; 
 547     if (message
->version 
== 0) { 
 548         return der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->removals
), der
, 
 549             der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
), der
, der_end
)); 
 551         return ccder_encode_constructed_tl(0 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, der_end
, der
, 
 552             der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->removals
), der
, 
 553             der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
), der
, der_end
))); 
 557 static size_t der_sizeof_extensions(SOSMessageRef message
) { 
 558     // We don't support any yet. 
 562 static uint8_t *der_encode_extensions(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 563     // We don't support any yet. 
 567 static size_t der_sizeof_objects(SOSMessageRef message
) { 
 569     if (message
->objects
) { 
 571         CFArrayForEachC(message
->objects
, data
) { 
 572             len 
+= (size_t)CFDataGetLength(data
); 
 574     } else if (message
->version 
!= 0) 
 577     if (message
->indefiniteLength
) 
 580         return ccder_sizeof(2 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, len
); 
 583 static uint8_t *der_encode_objects(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 584     if (!message
->objects 
&& message
->version 
!= 0) return der_end
; 
 585     const uint8_t *original_der_end 
= der_end
; 
 586     if (message
->indefiniteLength
) 
 587         der_end 
= ccder_encode_tl(CCDER_EOL
, 0, der
, der_end
); 
 589     for (CFIndex position 
= (message
->objects 
? CFArrayGetCount(message
->objects
) : 0) - 1; position 
>= 0; --position
) { 
 590         CFDataRef object 
= CFArrayGetValueAtIndex(message
->objects
, position
); 
 591         der_end 
= ccder_encode_body(CFDataGetLength(object
), CFDataGetBytePtr(object
), der
, der_end
); 
 593     if (message
->indefiniteLength
) { 
 594         return ccder_encode_tag(2 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, der
, 
 595                ccder_encode_len(0, der
, der_end
)); 
 597         ccder_tag otag 
= message
->version 
== 0 ? CCDER_CONSTRUCTED_SEQUENCE 
: 2 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
; 
 598         return ccder_encode_constructed_tl(otag
, original_der_end
, der
, der_end
); 
 602 static size_t der_sizeof_v2_message(SOSMessageRef message
, CFErrorRef 
*error
) { 
 603     size_t body_size 
= (der_sizeof_message_header(message
, error
) + 
 604                         der_sizeof_deltas(message
) + 
 605                         der_sizeof_extensions(message
) + 
 606                         der_sizeof_objects(message
)); 
 607     if (message
->indefiniteLength
) 
 608         return body_size 
+ 4; 
 610         return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, body_size
); 
 614 static uint8_t *der_encode_v2_message(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 615     const uint8_t *original_der_end 
= der_end
; 
 616     if (message
->indefiniteLength
) 
 617         der_end 
= ccder_encode_tl(CCDER_EOL
, 0, der
, der_end
); 
 619     der_end 
= der_encode_message_header(message
, error
, der
, 
 620         der_encode_deltas(message
, error
, der
, 
 621         der_encode_extensions(message
, error
, der
, 
 622         der_encode_objects(message
, error
, der
, der_end
)))); 
 624     if (message
->indefiniteLength
) { 
 625         return ccder_encode_tag(CCDER_CONSTRUCTED_SEQUENCE
, der
, 
 626                ccder_encode_len(0, der
, der_end
)); 
 628         return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, original_der_end
, der
, der_end
); 
 632 //------------------------------------------------------------------------------------------------------------------------------------ 
 634 //------------------------------------------------------------------------------------------------------------------------------------ 
 636 /* ManifestDigest message */ 
 637 static size_t der_sizeof_manifest_digest_message(SOSMessageRef message
, CFErrorRef 
*error
) { 
 638     if (!message
->senderDigest 
|| CFDataGetLength(message
->senderDigest
) != SOSDigestSize
) { 
 639         SOSErrorCreate(kSOSErrorProcessingFailure
, error
, NULL
, CFSTR("digest length mismatch")); 
 642     return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
 643                         (ccder_sizeof_uint64(SOSManifestDigestMessageType
) + 
 644                          ccder_sizeof_raw_octet_string(SOSDigestSize
))); 
 647 static uint8_t *der_encode_manifest_digest_message(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 648     secinfo("engine", "der_encode_manifest_digest_message: encoded sender digest as %@", message
->senderDigest
); 
 649     return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
 650            ccder_encode_uint64(SOSManifestDigestMessageType
, der
, 
 651            ccder_encode_raw_octet_string(SOSDigestSize
, CFDataGetBytePtr(message
->senderDigest
), der
, der_end
))); 
 654 /* Manifest message */ 
 655 static size_t der_sizeof_manifest_message(SOSMessageRef message
, CFErrorRef 
*error
) { 
 656     if (!message
->additions
) { 
 657         SOSErrorCreate(kSOSErrorProcessingFailure
, error
, NULL
, CFSTR("no manifest for manifest message")); 
 660     return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
 661         (ccder_sizeof_uint64(SOSManifestMessageType
) + 
 662          der_sizeof_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
)))); 
 665 static uint8_t *der_encode_manifest_message(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 666     secinfo("engine", "der_encode_manifest_message: encoded message additions as (%zu, %@)", SOSManifestGetCount(message
->additions
), SOSManifestGetDigest(message
->additions
, NULL
)); 
 667     return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
 668                ccder_encode_uint64(SOSManifestMessageType
, der
, 
 669                der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
), der
, der_end
))); 
 672 /* ManifestDeltaAndObjects message */ 
 673 static size_t der_sizeof_manifest_and_objects_message(SOSMessageRef message
, CFErrorRef 
*error
) { 
 674     if (!message
->baseDigest 
|| CFDataGetLength(message
->baseDigest
) != SOSDigestSize
) { 
 675         SOSErrorCreate(kSOSErrorProcessingFailure
, error
, NULL
, CFSTR("digest length mismatch")); 
 679     return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
 680         (ccder_sizeof_uint64(SOSManifestDeltaAndObjectsMessageType
) + 
 681          ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE
, 
 682              (ccder_sizeof_raw_octet_string(SOSDigestSize
) + 
 683               der_sizeof_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->removals
)) + 
 684               der_sizeof_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
)) + 
 685               der_sizeof_objects(message
))))); 
 688 static uint8_t *der_encode_manifest_and_objects_message(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 689     secinfo("engine", "der_encode_manifest_and_objects_message: encoded base digest as %@", message
->baseDigest
); 
 690     return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
 691                ccder_encode_uint64(SOSManifestDeltaAndObjectsMessageType
, der
, 
 692                ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, der_end
, der
, 
 693                    ccder_encode_raw_octet_string(SOSDigestSize
, CFDataGetBytePtr(message
->baseDigest
), der
, 
 694                    der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->removals
), der
, 
 695                    der_encode_implicit_data(CCDER_OCTET_STRING
, SOSManifestGetData(message
->additions
), der
, 
 696                    der_encode_objects(message
, error
, der
, der_end
))))))); 
 699 static uint64_t SOSMessageInferType(SOSMessageRef message
, CFErrorRef 
*error
) { 
 700     if (message
->baseDigest
) { 
 701         // TODO: Assert that we don't have senderDigest or proposedDigest 
 702         if (SOSManifestGetCount(message
->removals
) || SOSManifestGetCount(message
->additions
) || SOSMessageCountObjects(message
)) { 
 703             return SOSManifestDeltaAndObjectsMessageType
; 
 705             // NOTE: If we force a SOSManifestDeltaAndObjectsMessageType instead then 
 706             // true v0 peers will overwrite their last objects message to us.  However this 
 707             // implements the current v0 behaviour 
 708             return SOSManifestDigestMessageType
; 
 710     } else if (message
->additions
) { 
 711         // TODO: Assert that we don't have senderDigest, proposedDigest, additions, removals or objects 
 712         return SOSManifestMessageType
; 
 713     } else if (message
->senderDigest
) { 
 714         // TODO: Assert that we don't have proposedDigest, removals or objects 
 715         return SOSManifestDigestMessageType
; 
 717     // TODO: Create error. 
 718     return SOSManifestInvalidMessageType
; 
 721 static size_t der_sizeof_message(SOSMessageRef message
, uint64_t messageType
, CFErrorRef 
*error
) { 
 722     switch (messageType
) { 
 723         case SOSManifestInvalidMessageType
: 
 724             return der_sizeof_v2_message(message
, error
); 
 725         case SOSManifestDigestMessageType
: 
 726             return der_sizeof_manifest_digest_message(message
, error
); 
 727         case SOSManifestMessageType
: 
 728             return der_sizeof_manifest_message(message
, error
); 
 729         case SOSManifestDeltaAndObjectsMessageType
: 
 730             return der_sizeof_manifest_and_objects_message(message
, error
); 
 735 static uint8_t *der_encode_message(SOSMessageRef message
, uint64_t messageType
, CFErrorRef 
*error
, const uint8_t *der
, uint8_t *der_end
) { 
 736     switch (messageType
) { 
 737         case SOSManifestInvalidMessageType
: 
 738             return der_encode_v2_message(message
, error
, der
, der_end
); 
 739         case SOSManifestDigestMessageType
: 
 740             return der_encode_manifest_digest_message(message
, error
, der
, der_end
); 
 741         case SOSManifestMessageType
: 
 742             return der_encode_manifest_message(message
, error
, der
, der_end
); 
 743         case SOSManifestDeltaAndObjectsMessageType
: 
 744             return der_encode_manifest_and_objects_message(message
, error
, der
, der_end
); 
 749 // Encode an SOSMessage, calls addObject callback and appends returned objects 
 750 // one by one, until addObject returns NULL. 
 751 CFDataRef 
SOSMessageCreateData(SOSMessageRef message
, uint64_t sequenceNumber
, CFErrorRef 
*error
) { 
 752     // Version 2 message have sequence numbers, version 0 messages do not. 
 753     uint64_t messageType 
= SOSManifestInvalidMessageType
; 
 754     message
->sequenceNumber 
= sequenceNumber
; 
 755     if (message
->version 
== 0) { 
 756         message
->indefiniteLength 
= false; 
 757         messageType 
= SOSMessageInferType(message
, error
); 
 763         message
->creationTime 
= floor(CFAbsoluteTimeGetCurrent()); 
 765     size_t der_size 
= der_sizeof_message(message
, messageType
, error
); 
 766     CFMutableDataRef data 
= CFDataCreateMutable(NULL
, der_size
); 
 771     CFDataSetLength(data
, der_size
); 
 772     uint8_t *der_end 
= CFDataGetMutableBytePtr(data
); 
 773     const uint8_t *der 
= der_end
; 
 776     der_end 
= der_encode_message(message
, messageType
, error
, der
, der_end
); 
 777     if (der 
!= der_end
) { 
 778         secwarning("internal error %td bytes unused in der buffer", der_end 
- der
); 
 784 // MARK: SOSMessage decoding 
 787 #define CCBER_LEN_INDEFINITE ((size_t)-1) 
 789 // Decode BER length field.  Sets *lenp to ccber_indefinite_len if this is an indefinite length encoded object. 
 790 // Behaves like ccder_decode_len in every other way. 
 791 static CC_NONNULL((1, 3)) 
 792 const uint8_t *ccber_decode_len(size_t *lenp
, const uint8_t *der
, const uint8_t *der_end
) { 
 793     if (der 
&& der 
< der_end
) { 
 796             *lenp 
= CCBER_LEN_INDEFINITE
; 
 799             der 
= ccder_decode_len(lenp
, der
, der_end
); 
 804 static const uint8_t *der_decode_generalizedtime(CFAbsoluteTime 
*at
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 805     const uint8_t *times_end 
= NULL
; 
 806     der 
= ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME
, ×_end
, der
, der_end
); 
 807     der 
= der_decode_generalizedtime_body(at
, error
, der
, times_end
); 
 808     if (times_end 
!= der
) { 
 809         secwarning("internal error %td bytes unused in generalizedtime DER buffer", times_end 
- der
); 
 814 static const uint8_t *der_decode_optional_generalizedtime(CFAbsoluteTime 
*at
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 815     const uint8_t *times_end 
= der_decode_generalizedtime(at
, error
, der
, der_end
); 
 816     return times_end 
? times_end 
: der
; 
 819 static CC_NONNULL((2, 4)) 
 820 const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag
, uint64_t* r
, const uint8_t *der
, const uint8_t *der_end
) { 
 822     der 
= ccder_decode_tl(expected_tag
, &len
, der
, der_end
); 
 823     if (der 
&& len 
&& (*der 
& 0x80) != 0x80) { 
 824         if (ccn_read_uint(ccn_nof_size(sizeof(*r
)), (cc_unit
*)r
, len
, der
) >= 0) 
 830 static const uint8_t *ccder_decode_optional_implicit_uint64(ccder_tag expected_tag
, uint64_t *value
, const uint8_t *der
, const uint8_t *der_end
) { 
 831     const uint8_t *ui64_end 
= ccder_decode_implicit_uint64(expected_tag
, value
, der
, der_end
); 
 832     return ui64_end 
? ui64_end 
: der
; 
 836 static const uint8_t *ccder_decode_optional_uint64(uint64_t *value
, const uint8_t *der
, const uint8_t *der_end
) { 
 837     const uint8_t *ui64_end 
= ccder_decode_uint64(value
, der
, der_end
); 
 838     return ui64_end 
? ui64_end 
: der
; 
 841 static const uint8_t *ccder_decode_digest_types(SOSMessageRef message
, const uint8_t *der
, const uint8_t *der_end
) { 
 842     const uint8_t *dt_end
; 
 843     der 
= ccder_decode_sequence_tl(&dt_end
, der
, der_end
); 
 844     if (!der
) return NULL
; 
 845     // Skip over digestType body for now. 
 846     // TODO: Support DigestType 
 850 static const uint8_t *ccder_decode_optional_digest_types(SOSMessageRef message
, const uint8_t *der
, const uint8_t *der_end
) { 
 851     const uint8_t *dt_end 
= ccder_decode_digest_types(message
, der
, der_end
); 
 852     return dt_end 
? dt_end 
: der
; 
 855 static const uint8_t *ccder_decode_bit_string(cc_size n
, size_t *r_bitlen
, cc_unit 
*r
, const uint8_t *der
, const uint8_t *der_end
) { 
 857     const uint8_t *body 
= ccder_decode_tl(CCDER_BIT_STRING
, &len
, der
, der_end
); 
 858     if (!body 
|| len 
< 1) 
 861     if (r_bitlen
) *r_bitlen 
= (len 
- 1) * 8 - (body
[0] & 7); 
 862     ccn_read_uint(1, r
, len 
- 1, body 
+ 1); 
 866 static const uint8_t *der_decode_implicit_data(ccder_tag expected_tag
, CFDataRef 
*data
, const uint8_t *der
, const uint8_t *der_end
) { 
 868     der 
= ccder_decode_tl(expected_tag
, &len
, der
, der_end
); 
 870         *data 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, der
, len
, kCFAllocatorNull
); 
 879 static const uint8_t *der_decode_optional_implicit_data(ccder_tag expected_tag
, CFDataRef 
*data
, const uint8_t *der
, const uint8_t *der_end
) { 
 880     const uint8_t *data_end 
= der_decode_implicit_data(expected_tag
, data
, der
, der_end
); 
 881     return data_end 
? data_end 
: der
; 
 884 static const uint8_t *der_decode_deltas_body(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 885     CFDataRef removals 
= NULL
, additions 
= NULL
; 
 886     der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &removals
, der
, der_end
); 
 887     der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &additions
, der
, der_end
); 
 889         message
->removals 
= SOSManifestCreateWithData(removals
, error
); 
 890         message
->additions 
= SOSManifestCreateWithData(additions
, error
); 
 891         if (!message
->removals 
|| !message
->additions
) { 
 892             CFReleaseNull(message
->removals
); 
 893             CFReleaseNull(message
->additions
); 
 897     CFReleaseSafe(removals
); 
 898     CFReleaseSafe(additions
); 
 903 static const uint8_t *der_decode_deltas(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 904     const uint8_t *deltas_end 
= NULL
; 
 905     der 
= ccder_decode_constructed_tl(0 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, &deltas_end
, der
, der_end
); 
 906     return der_decode_deltas_body(message
, error
, der
, deltas_end
); 
 909 static const uint8_t *der_decode_optional_deltas(SOSMessageRef message
, const uint8_t *der
, const uint8_t *der_end
) { 
 910     const uint8_t *seq_end 
= der_decode_deltas(message
, NULL
, der
, der_end
); 
 911     return seq_end 
? seq_end 
: der
; 
 914 static const uint8_t *der_decode_extensions(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 915     const uint8_t *extensions_end
; 
 916     der 
= ccder_decode_constructed_tl(1 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
, &extensions_end
, der
, der_end
); 
 917     if (!der
) return NULL
; 
 918     // Skip over extensions for now. 
 919     return extensions_end
; 
 922 static const uint8_t *der_decode_optional_extensions(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 923     const uint8_t *extensions_end 
= der_decode_extensions(message
, NULL
, der
, der_end
); 
 924     return extensions_end 
? extensions_end 
: der
; 
 927 static const uint8_t *der_foreach_objects(size_t length
, const uint8_t *der
, const uint8_t *der_end
, CFErrorRef 
*error
, void(^withObject
)(CFDataRef object
, bool *stop
)) { 
 930     // Look ahead at the tag 
 931     while (!stop 
&& ccder_decode_tag(&tag
, der
, der_end
) && tag 
!= CCDER_EOL
) { 
 932         const uint8_t *object_end 
= NULL
; 
 933         if (!ccder_decode_constructed_tl(tag
, &object_end
, der
, der_end
)) { 
 934             SOSErrorCreate(kSOSErrorDecodeFailure
, error
, NULL
, CFSTR("failed to decode object header")); 
 938             CFDataRef object 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, der
, object_end 
- der
, kCFAllocatorNull
); 
 939             withObject(object
, &stop
); 
 940             CFReleaseSafe(object
); 
 944     if (length 
== CCBER_LEN_INDEFINITE
) { 
 946         der 
= ccder_decode_tl(CCDER_EOL
, &len
, der
, der_end
); 
 948             secwarning("%td length ", der_end 
- der
); 
 951     if (!stop 
&& der 
!= der_end
) 
 952         secwarning("%td trailing bytes after objects DER", der_end 
- der
); 
 957 static const uint8_t *der_decode_objects(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 959     size_t objects_len 
= 0; 
 960     der 
= ccder_decode_tag(&tag
, der
, der_end
); 
 961     if (tag 
!= (2 | CCDER_CONTEXT_SPECIFIC 
| CCDER_CONSTRUCTED
)) return NULL
; 
 962     der 
= ccber_decode_len(&objects_len
, der
, der_end
); 
 963     if (objects_len 
!= CCBER_LEN_INDEFINITE 
&& der_end 
- der 
!= (ptrdiff_t)objects_len
) { 
 964         secwarning("%td trailing bytes after SOSMessage DER", (der_end 
- der
) - (ptrdiff_t)objects_len
); 
 966     // Remember a pointer into message->der where objects starts. 
 967     message
->objectsDer 
= der
; 
 968     message
->objectsLen 
= objects_len
; 
 970     return der 
+ objects_len
; 
 973 static const uint8_t *der_decode_optional_objects(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 974     const uint8_t *seq_end 
= der_decode_objects(message
, NULL
, der
, der_end
); 
 975     return seq_end 
? seq_end 
: der
; 
 979 // Move to ccder and possibly refactor ccder_decode_constructed_tl to call this. 
 980 #ifdef CCDER_DECODE_CONSTRUCTED_LEN_SPECIFIER 
 981 CCDER_DECODE_CONSTRUCTED_LEN_SPECIFIER
 
 983 inline CC_NONNULL((1, 3)) 
 985 ccder_decode_constructed_len(const uint8_t **body_end
, 
 986                              const uint8_t *der
, const uint8_t *der_end
) { 
 988     der 
= ccder_decode_len(&len
, der
, der_end
); 
 989     *body_end 
= der 
+ len
; 
 994 static const uint8_t *der_decode_message_header(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
 995     cc_unit flags
[1] = {}; 
 996     der 
= ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE
, &der_end
, der
, der_end
); 
 997     message
->version 
= 2; 
 998     der 
= ccder_decode_optional_implicit_uint64(0 | CCDER_CONTEXT_SPECIFIC
, &message
->version
, der
, der_end
); 
 999     der 
= der_decode_optional_generalizedtime(&message
->creationTime
, error
, der
, der_end
); 
1000     der 
= ccder_decode_optional_uint64(&message
->sequenceNumber
, der
, der_end
); 
1001     der 
= ccder_decode_optional_digest_types(message
, der
, der_end
); 
1002     der 
= ccder_decode_bit_string(array_size(flags
), NULL
, flags
, der
, der_end
); 
1003     message
->flags 
= flags
[0]; 
1005     der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &message
->senderDigest
, der
, der_end
); 
1006     secinfo("engine", "der_decode_message_header: decoded sender digest as %@", message
->senderDigest
); 
1008     der 
= der_decode_optional_implicit_data(0 | CCDER_CONTEXT_SPECIFIC
, &message
->baseDigest
, der
, der_end
); 
1009     secinfo("engine", "der_decode_message_header: decoded base digest as %@", message
->baseDigest
); 
1011     der 
= der_decode_optional_implicit_data(1 | CCDER_CONTEXT_SPECIFIC
, &message
->proposedDigest
, der
, der_end
); 
1012     secinfo("engine", "der_decode_message_header: decoded proposed digest as %@", message
->proposedDigest
); 
1017 static const uint8_t * 
1018 der_decode_manifest_and_objects_message(SOSMessageRef message
, 
1019                                         CFErrorRef 
*error
, const uint8_t *der
, 
1020                                         const uint8_t *der_end
) { 
1021     size_t objects_len 
= 0; 
1022     const uint8_t *body_end
; 
1023     der 
= ccder_decode_sequence_tl(&body_end
, der
, der_end
); 
1024     if (body_end 
!= der_end
) { 
1025         SOSErrorCreate(kSOSErrorInvalidMessage
, error
, NULL
, CFSTR("Trailing garbage at end of message")); 
1028     der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &message
->baseDigest
, der
, body_end
); 
1029     secinfo("engine", "der_decode_manifest_and_objects_message: decoded base digest as %@", message
->baseDigest
); 
1031     der 
= der_decode_deltas_body(message
, error
, der
, body_end
); 
1032     // Remember a pointer into message->der where objects starts. 
1033     der 
= message
->objectsDer 
= ccder_decode_tl(CCDER_CONSTRUCTED_SEQUENCE
, &objects_len
, der
, body_end
); 
1034     message
->objectsLen 
= objects_len
; 
1036     return der 
? der 
+ objects_len 
: NULL
; 
1039 static const uint8_t *der_decode_v0_message_body(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
1040     uint64_t messageType 
= 0; 
1041     der 
= ccder_decode_uint64(&messageType
, der
, der_end
); 
1042     if (der
) switch (messageType
) { 
1043         case SOSManifestDigestMessageType
: 
1045             der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &message
->senderDigest
, der
, der_end
); 
1046             secinfo("engine", "der_decode_v0_message_body: received a DigestMessage with sender digest: %@", message
->senderDigest
); 
1049         case SOSManifestMessageType
: 
1051             CFDataRef manifestBody 
= NULL
; 
1052             der 
= der_decode_implicit_data(CCDER_OCTET_STRING
, &manifestBody
, der
, der_end
); 
1053             if (!der
) return NULL
; 
1054             if (der 
!= der_end
) { 
1055                 secwarning("%td trailing bytes after deltas DER", der_end 
- der
); 
1057             message
->additions 
= SOSManifestCreateWithData(manifestBody
, error
); 
1058             secinfo("engine", "der_decode_v0_message_body: received a ManifestMessage with (%zu, %@)", SOSManifestGetCount(message
->additions
), SOSManifestGetDigest(message
->additions
, NULL
)); 
1059             CFReleaseSafe(manifestBody
); 
1062         case SOSManifestDeltaAndObjectsMessageType
: 
1064             der 
= der_decode_manifest_and_objects_message(message
, error
, der
, der_end
); 
1068             SOSErrorCreate(kSOSErrorInvalidMessage
, error
, NULL
, CFSTR("Invalid message type %llu"), messageType
); 
1074 static const uint8_t *der_decode_message(SOSMessageRef message
, CFErrorRef 
*error
, const uint8_t *der
, const uint8_t *der_end
) { 
1076     size_t body_len 
= 0; 
1078     der 
= ccder_decode_tag(&tag
, der
, der_end
); 
1079     if (tag 
!= CCDER_CONSTRUCTED_SEQUENCE
) return NULL
; 
1080     der 
= ccber_decode_len(&body_len
, der
, der_end
); 
1081     if (der 
&& body_len 
&& body_len 
!= CCBER_LEN_INDEFINITE 
&& (der_end 
- der
) != (ptrdiff_t)body_len
) { 
1082         secwarning("%td trailing bytes after SOSMessage DER", (der_end 
- der
) - (ptrdiff_t)body_len
); 
1083         der_end 
= der 
+ body_len
; 
1086     if (ccder_decode_tag(&tag
, der
, der_end
)) switch (tag
) { 
1087         case CCDER_INTEGER
: // v0 
1088             if (body_len 
== CCBER_LEN_INDEFINITE
) 
1089                 der 
= NULL
; // Not supported for v0 messages 
1091                 der 
= der_decode_v0_message_body(message
, error
, der
, der_end
); 
1093         case CCDER_CONSTRUCTED_SEQUENCE
: //v2 
1094             der 
= der_decode_message_header(message
, error
, der
, der_end
); 
1095             der 
= der_decode_optional_deltas(message
, der
, der_end
); 
1096             der 
= der_decode_optional_extensions(message
, error
, der
, der_end
); 
1097             der 
= der_decode_optional_objects(message
, error
, der
, der_end
); 
1103 // Decode a SOSMessage 
1104 SOSMessageRef 
SOSMessageCreateWithData(CFAllocatorRef allocator
, CFDataRef derData
, CFErrorRef 
*error
) { 
1106         return (SOSMessageRef
)SOSErrorCreate(kSOSErrorDecodeFailure
, error
, NULL
, CFSTR("NULL data => no SOSMessage")); 
1107     SOSMessageRef message 
= CFTypeAllocate(SOSMessage
, struct __OpaqueSOSMessage
, allocator
); 
1109         return (SOSMessageRef
)SOSErrorCreate(kSOSErrorAllocationFailure
, error
, NULL
, CFSTR("failed to alloc SOSMessage")); 
1110     message
->der 
= CFRetainSafe(derData
); 
1111     const uint8_t *der 
= CFDataGetBytePtr(derData
); 
1112     const uint8_t *der_end 
= der 
+ CFDataGetLength(derData
); 
1113     der 
= der_decode_message(message
, error
, der
, der_end
); 
1114     if (!der_end 
|| der 
!= der_end
) { 
1115         if (error 
&& !*error
) 
1116             SOSErrorCreate(kSOSErrorDecodeFailure
, error
, NULL
, CFSTR("SOSMessage DER decoding failure %td bytes left"), der_end 
- der
); 
1117         return CFReleaseSafe(message
); 
1122 // Read values from a decoded messgage 
1124 CFDataRef 
SOSMessageGetBaseDigest(SOSMessageRef message
) { 
1125     return message
->baseDigest
; 
1128 CFDataRef 
SOSMessageGetProposedDigest(SOSMessageRef message
) { 
1129     return message
->proposedDigest
; 
1132 CFDataRef 
SOSMessageGetSenderDigest(SOSMessageRef message
) { 
1133     return message
->senderDigest
; 
1136 SOSMessageFlags 
SOSMessageGetFlags(SOSMessageRef message
) { 
1137     return message
->flags
; 
1140 uint64_t SOSMessageGetSequenceNumber(SOSMessageRef message
) { 
1141     return message
->sequenceNumber
; 
1144 SOSManifestRef 
SOSMessageGetRemovals(SOSMessageRef message
) { 
1145     return message
->removals
; 
1148 SOSManifestRef 
SOSMessageGetAdditions(SOSMessageRef message
) { 
1149     return message
->additions
; 
1152 // Iterate though the extensions in a decoded SOSMessage.  If criticalOnly is 
1153 // true all non critical extensions are skipped. 
1154 void SOSMessageWithExtensions(SOSMessageRef message
, bool criticalOnly
, void(^withExtension
)(CFDataRef oid
, bool isCritical
, CFDataRef extension
, bool *stop
)) { 
1158 size_t SOSMessageCountObjects(SOSMessageRef message
) { 
1159     if (message
->objects
) 
1160         return CFArrayGetCount(message
->objects
); 
1161     if (!message
->objectsDer
) 
1163     const uint8_t *der 
= CFDataGetBytePtr(message
->der
); 
1164     const uint8_t *der_end 
= der 
+ CFDataGetLength(message
->der
); 
1165     __block 
size_t count 
= 0; 
1166     der_foreach_objects(message
->objectsLen
, message
->objectsDer
, der_end
, NULL
, ^(CFDataRef object
, bool *stop
){ ++count
; }); 
1170 // Iterate though the objects in a decoded SOSMessage. 
1171 bool SOSMessageWithObjects(SOSMessageRef message
, CFErrorRef 
*error
, 
1172                            void(^withObject
)(CFDataRef object
, bool *stop
)) { 
1173     if (message
->objects
) { 
1175         CFArrayForEachC(message
->objects
, object
) { 
1177             withObject(object
, &stop
); 
1183     if (!message
->objectsDer
) 
1185     const uint8_t *der 
= CFDataGetBytePtr(message
->der
); 
1186     const uint8_t *der_end 
= der 
+ CFDataGetLength(message
->der
); 
1187     return der_foreach_objects(message
->objectsLen
, message
->objectsDer
, der_end
, error
, withObject
); 
1190 bool SOSMessageWithSOSObjects(SOSMessageRef message
, SOSDataSourceRef dataSource
, CFErrorRef 
*error
, 
1191                            void(^withObject
)(SOSObjectRef object
, bool *stop
)) { 
1192     return SOSMessageWithObjects(message
, error
, ^(CFDataRef object
, bool *stop
) { 
1193         CFDictionaryRef plist 
= NULL
; 
1194         const uint8_t *der 
= CFDataGetBytePtr(object
); 
1195         const uint8_t *der_end 
= der 
+ CFDataGetLength(object
); 
1196         // TODO Remove intermediate plist format 
1197         der 
= der_decode_dictionary(kCFAllocatorDefault
, kCFPropertyListImmutable
, &plist
, error
, der
, der_end
); 
1199             SOSObjectRef peersObject 
= SOSObjectCreateWithPropertyList(dataSource
, plist
, error
); 
1200             withObject(peersObject
, stop
); 
1201             CFReleaseSafe(peersObject
); 
1203         CFReleaseSafe(plist
);