]> git.saurik.com Git - apple/security.git/blob - keychain/trust/TrustedPeers/TPHash.m
Security-58286.20.16.tar.gz
[apple/security.git] / keychain / trust / TrustedPeers / TPHash.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 "TPHash.h"
25
26 #import <CommonCrypto/CommonDigest.h>
27
28 @interface TPHashBuilder ()
29
30 @property (nonatomic, assign) TPHashAlgo algo;
31 @property (nonatomic, assign) CC_SHA256_CTX ctxSHA256; // used by SHA224 and SHA256
32 @property (nonatomic, assign) CC_SHA512_CTX ctxSHA512; // used by SHA384 and SHA512
33
34 @end
35
36 @implementation TPHashBuilder
37
38 + (TPHashAlgo)algoOfHash:(NSString *)hash
39 {
40 if ([hash hasPrefix:@"SHA224:"]) {
41 return kTPHashAlgoSHA224;
42 }
43 if ([hash hasPrefix:@"SHA256:"]) {
44 return kTPHashAlgoSHA256;
45 }
46 if ([hash hasPrefix:@"SHA384:"]) {
47 return kTPHashAlgoSHA384;
48 }
49 if ([hash hasPrefix:@"SHA512:"]) {
50 return kTPHashAlgoSHA512;
51 }
52 return kTPHashAlgoUnknown;
53 }
54
55 - (instancetype)init
56 {
57 self = [super init];
58 if (self) {
59 _algo = kTPHashAlgoUnknown;
60 }
61 return self;
62 }
63
64 - (instancetype)initWithAlgo:(TPHashAlgo)algo
65 {
66 self = [self init];
67 [self resetWithAlgo:algo];
68 return self;
69 }
70
71 - (void)resetWithAlgo:(TPHashAlgo)algo
72 {
73 _algo = algo;
74 switch (algo) {
75 case kTPHashAlgoSHA224:
76 CC_SHA224_Init(&_ctxSHA256);
77 break;
78 case kTPHashAlgoSHA256:
79 CC_SHA256_Init(&_ctxSHA256);
80 break;
81 case kTPHashAlgoSHA384:
82 CC_SHA384_Init(&_ctxSHA512);
83 break;
84 case kTPHashAlgoSHA512:
85 CC_SHA512_Init(&_ctxSHA512);
86 break;
87 default:
88 [self throwInvalidAlgo];
89 }
90 }
91
92 - (void)updateWithData:(NSData *)data
93 {
94 [self updateWithBytes:data.bytes len:data.length];
95 }
96
97 - (void)updateWithBytes:(const void *)data len:(size_t)len
98 {
99 switch (self.algo) {
100 case kTPHashAlgoSHA224:
101 CC_SHA224_Update(&_ctxSHA256, data, (CC_LONG)len);
102 break;
103 case kTPHashAlgoSHA256:
104 CC_SHA256_Update(&_ctxSHA256, data, (CC_LONG)len);
105 break;
106 case kTPHashAlgoSHA384:
107 CC_SHA384_Update(&_ctxSHA512, data, (CC_LONG)len);
108 break;
109 case kTPHashAlgoSHA512:
110 CC_SHA512_Update(&_ctxSHA512, data, (CC_LONG)len);
111 break;
112 default:
113 [self throwInvalidAlgo];
114 }
115 }
116
117 - (NSString *)finalHash
118 {
119 NSMutableData* data = [NSMutableData alloc];
120 NSString* name = nil;
121 switch (self.algo) {
122 case kTPHashAlgoSHA224:
123 data = [data initWithLength:224/8];
124 CC_SHA224_Final(data.mutableBytes, &_ctxSHA256);
125 name = @"SHA224";
126 break;
127 case kTPHashAlgoSHA256:
128 data = [data initWithLength:256/8];
129 CC_SHA256_Final(data.mutableBytes, &_ctxSHA256);
130 name = @"SHA256";
131 break;
132 case kTPHashAlgoSHA384:
133 data = [data initWithLength:384/8];
134 CC_SHA384_Final(data.mutableBytes, &_ctxSHA512);
135 name = @"SHA384";
136 break;
137 case kTPHashAlgoSHA512:
138 data = [data initWithLength:512/8];
139 CC_SHA512_Final(data.mutableBytes, &_ctxSHA512);
140 name = @"SHA512";
141 break;
142 default:
143 [self throwInvalidAlgo];
144 }
145 NSString* hash = [NSString stringWithFormat:@"%@:%@",
146 name, [data base64EncodedStringWithOptions:0]];
147
148 // _ctxSHA* was "emptied" by the call to CC_SHA*_Final,
149 // so require the client to call resetWithAlgo: before reuse.
150 self.algo = kTPHashAlgoUnknown;
151
152 return hash;
153 }
154
155 - (void)throwInvalidAlgo
156 {
157 NSException* ex = [NSException exceptionWithName:@"InvalidTPHashAlgo"
158 reason:@"Invalid TPHash algorithm"
159 userInfo:nil];
160 @throw ex;
161 }
162
163 + (NSString *)hashWithAlgo:(TPHashAlgo)algo ofData:(NSData *)data
164 {
165 return [TPHashBuilder hashWithAlgo:algo ofBytes:data.bytes len:data.length];
166 }
167
168 + (NSString *)hashWithAlgo:(TPHashAlgo)algo ofBytes:(const void *)data len:(size_t)len
169 {
170 TPHashBuilder *builder = [[TPHashBuilder alloc] initWithAlgo:algo];
171 [builder updateWithBytes:data len:len];
172 return [builder finalHash];
173 }
174
175 @end