]> git.saurik.com Git - apple/security.git/blob - keychain/trust/TrustedPeers/TPPeerStableInfo.m
Security-58286.41.2.tar.gz
[apple/security.git] / keychain / trust / TrustedPeers / TPPeerStableInfo.m
1 /*
2 * Copyright (c) 2017 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 #import "TPPeerStableInfo.h"
25 #import "TPUtils.h"
26
27 static const NSString *kClock = @"clock";
28 static const NSString *kPolicyVersion = @"policyVersion";
29 static const NSString *kPolicyHash = @"policyHash";
30 static const NSString *kPolicySecrets = @"policySecrets";
31
32
33 @interface TPPeerStableInfo ()
34
35 @property (nonatomic, strong) NSDictionary *dict;
36 @property (nonatomic, assign) TPCounter clock;
37 @property (nonatomic, assign) TPCounter policyVersion;
38 @property (nonatomic, strong) NSString *policyHash;
39 @property (nonatomic, strong) NSDictionary<NSString*,NSData*> *policySecrets;
40 @property (nonatomic, strong) NSData *stableInfoPList;
41 @property (nonatomic, strong) NSData *stableInfoSig;
42
43 @end
44
45
46 @implementation TPPeerStableInfo
47
48 + (instancetype)stableInfoWithDict:(NSDictionary *)dict
49 clock:(TPCounter)clock
50 policyVersion:(TPCounter)policyVersion
51 policyHash:(NSString *)policyHash
52 policySecrets:(NSDictionary<NSString*,NSData*> *)policySecrets
53 trustSigningKey:(id<TPSigningKey>)trustSigningKey
54 error:(NSError **)error
55 {
56 NSMutableDictionary *mutDict = [NSMutableDictionary dictionaryWithDictionary:dict];
57 mutDict[kClock] = @(clock);
58 mutDict[kPolicyVersion] = @(policyVersion);
59 mutDict[kPolicyHash] = policyHash;
60 mutDict[kPolicySecrets] = policySecrets;
61
62 NSData *data = [TPUtils serializedPListWithDictionary:mutDict];
63 NSData *sig = [trustSigningKey signatureForData:data withError:error];
64 if (nil == sig) {
65 return nil;
66 }
67 TPPeerStableInfo *info = [self stableInfoWithPListData:data stableInfoSig:sig];;
68 assert(info);
69 return info;
70 }
71
72 + (instancetype)stableInfoWithPListData:(NSData *)stableInfoPList
73 stableInfoSig:(NSData *)stableInfoSig
74 {
75 id dict = [NSPropertyListSerialization propertyListWithData:stableInfoPList
76 options:NSPropertyListImmutable
77 format:nil
78 error:NULL];
79 if (![dict isKindOfClass:[NSDictionary class]]) {
80 return nil;
81 }
82
83 TPPeerStableInfo* info = [[TPPeerStableInfo alloc] init];
84
85 if (![dict[kClock] isKindOfClass:[NSNumber class]]) {
86 return nil;
87 }
88 info.clock = [dict[kClock] unsignedLongLongValue];
89
90 if (![dict[kPolicyVersion] isKindOfClass:[NSNumber class]]) {
91 return nil;
92 }
93 info.policyVersion = [dict[kPolicyVersion] unsignedLongLongValue];
94
95 if (![dict[kPolicyHash] isKindOfClass:[NSString class]]) {
96 return nil;
97 }
98 info.policyHash = dict[kPolicyHash];
99
100 if ([dict[kPolicySecrets] isKindOfClass:[NSDictionary class]]) {
101 NSDictionary *secrets = dict[kPolicySecrets];
102 for (id name in secrets) {
103 NSAssert([name isKindOfClass:[NSString class]], @"plist keys must be strings");
104 if (![secrets[name] isKindOfClass:[NSData class]]) {
105 return nil;
106 }
107 }
108 info.policySecrets = secrets;
109 } else if (nil == dict[kPolicySecrets]) {
110 info.policySecrets = @{};
111 } else {
112 return nil;
113 }
114
115 info.dict = dict;
116 info.stableInfoPList = [stableInfoPList copy];
117 info.stableInfoSig = [stableInfoSig copy];
118
119 return info;
120 }
121
122 - (BOOL)isEqualToPeerStableInfo:(TPPeerStableInfo *)other
123 {
124 if (other == self) {
125 return YES;
126 }
127 return [self.stableInfoPList isEqualToData:other.stableInfoPList]
128 && [self.stableInfoSig isEqualToData:other.stableInfoSig];
129 }
130
131 #pragma mark - NSObject
132
133 - (BOOL)isEqual:(id)object
134 {
135 if (self == object) {
136 return YES;
137 }
138 if (![object isKindOfClass:[TPPeerStableInfo class]]) {
139 return NO;
140 }
141 return [self isEqualToPeerStableInfo:object];
142 }
143
144 @end