iOS web browser with a focus on security and privacy
1/*
2 * Endless
3 * Copyright (c) 2015 joshua stein <jcs@jcs.org>
4 *
5 * See LICENSE file for redistribution terms.
6 */
7
8#import "SSLCertificate.h"
9
10#import "NSData+DTCrypto.h"
11#import "DTASN1Serialization.h"
12
13@implementation SSLCertificate
14
15static NSMutableDictionary <NSData *, NSMutableDictionary *> *certCache = nil;
16
17#define CERT_CACHE_SIZE 25
18#define CERT_CACHE_KEY_CERT @"key"
19#define CERT_CACHE_KEY_TIME @"time"
20
21- (id)init {
22 if (!(self = [super init]))
23 return nil;
24
25 _isEV = false;
26
27 if (!certCache)
28 certCache = [[NSMutableDictionary alloc] initWithCapacity:CERT_CACHE_SIZE];
29
30 return self;
31}
32
33- (id)initWithSecTrustRef:(SecTrustRef)secTrustRef
34{
35 SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrustRef, 0);
36 NSData *data = (__bridge_transfer NSData *)SecCertificateCopyData(cert);
37
38 if (!(self = [self initWithData:data]))
39 return nil;
40
41 /*
42 * Detecting EV means checking for a whole bunch of OIDs, since each vendor uses a different one.
43 * iOS already knows this and is updated with new ones, so just let it determine EV for us.
44 */
45 NSDictionary *trust = (__bridge_transfer NSDictionary *)SecTrustCopyResult(secTrustRef);
46 id ev = [trust objectForKey:(__bridge NSString *)kSecTrustExtendedValidation];
47 if (ev != nil && (__bridge CFBooleanRef)ev == kCFBooleanTrue) {
48 _isEV = true;
49 _evOrgName = (NSString *)[trust objectForKey:(__bridge NSString *)kSecTrustOrganizationName];
50 }
51
52 return self;
53}
54
55- (id)initWithData:(NSData *)data
56{
57 /* x509 cert structure:
58
59 Certificate
60 Data
61 Version
62 Serial Number
63 Signature Algorithm ID
64 Issuer
65 Validity
66 Not Before
67 Not After
68 Subject
69 Subject Public Key Info
70 Public Key Algorithm
71 Subject Public Key
72 Issuer Unique Identifier (optional)
73 Subject Unique Identifier (optional)
74 Extensions (optional)
75 ...
76 Certificate Signature Algorithm
77 Certificate Signature
78
79 */
80
81 if (!(self = [self init]))
82 return nil;
83
84 NSData *certHash = [data dataWithSHA1Hash];
85
86 NSMutableDictionary *ocdef = [certCache objectForKey:certHash];
87 if (ocdef) {
88 SSLCertificate *oc = [ocdef objectForKey:CERT_CACHE_KEY_CERT];
89#ifdef TRACE
90 NSLog(@"[SSLCertificate] certificate for %@ cached", [[oc subject] objectForKey:X509_KEY_CN]);
91#endif
92 [ocdef setValue:[NSDate date] forKey:CERT_CACHE_KEY_TIME];
93 return oc;
94 }
95
96 NSArray *oidtree;
97 NSObject *t = [DTASN1Serialization objectWithData:data];
98 if (t == nil || ![t isKindOfClass:[NSArray class]]) {
99 NSLog(@"[SSLCertificate] OID tree fetching failed, returned %@", t);
100 return nil;
101 }
102 else
103 oidtree = (NSArray *)t;
104
105 NSArray *cert = [self safeFetchFromArray:oidtree atIndex:0 withType:[NSArray class]];
106 if (cert == nil)
107 return nil;
108
109 NSArray *cData = [self safeFetchFromArray:cert atIndex:0 withType:[NSArray class]];
110 if (cData == nil)
111 return nil;
112
113 /* X.509 version (0-based - https://tools.ietf.org/html/rfc2459#section-4.1) */
114 NSNumber *tver = [self safeFetchFromArray:cData atIndex:0 withType:[NSNumber class]];
115 if (tver == nil)
116 return nil;
117 if ([tver intValue] == 0x0)
118 _version = @1;
119 else if ([tver intValue] == 0x1)
120 _version = @2;
121 else if ([tver intValue] == 0x2)
122 _version = @3;
123
124 /* certificate serial number (string of hex bytes) */
125 NSObject *tt = [self safeFetchFromArray:cert atIndex:1 withType:nil];
126 NSMutableArray *tserial = [[NSMutableArray alloc] initWithCapacity:16];
127 if (tt != nil && [tt isKindOfClass:[NSNumber class]]) {
128 long ttn = [(NSNumber *)tt longValue];
129 while (ttn > 0) {
130 [tserial addObject:[NSString stringWithFormat:@"%02lx", (ttn & 0xff)]];
131 ttn >>= 8;
132 }
133 tserial = [[NSMutableArray alloc] initWithArray:[[tserial reverseObjectEnumerator] allObjects]];
134 }
135 else if (tt != nil && [tt isKindOfClass:[NSData class]]) {
136 u_char *tbytes = (u_char *)[(NSData *)tt bytes];
137 for (int i = 0; i < [(NSData *)tt length]; i++)
138 [tserial addObject:[NSString stringWithFormat:@"%02x", tbytes[i]]];
139 }
140 _serialNumber = [tserial componentsJoinedByString:@":"];
141
142 /* signature algorithm (string representation - https://tools.ietf.org/html/rfc7427#page-12) */
143 NSArray *sigAlgTree = [self safeFetchFromArray:cert atIndex:2 withType:[NSArray class]];
144 if (sigAlgTree == nil)
145 return nil;
146 NSString *sigAlgOID = [self safeFetchFromArray:sigAlgTree atIndex:0 withType:[NSString class]];
147 if (sigAlgOID == nil)
148 return nil;
149 if ([sigAlgOID isEqualToString:@"1.2.840.113549.1.1.5"])
150 _signatureAlgorithm = @"sha1WithRSAEncryption";
151 else if ([sigAlgOID isEqualToString:@"1.2.840.113549.1.1.11"])
152 _signatureAlgorithm = @"sha256WithRSAEncryption";
153 else if ([sigAlgOID isEqualToString:@"1.2.840.113549.1.1.12"])
154 _signatureAlgorithm = @"sha384WithRSAEncryption";
155 else if ([sigAlgOID isEqualToString:@"1.2.840.113549.1.1.13"])
156 _signatureAlgorithm = @"sha512WithRSAEncryption";
157 else if ([sigAlgOID isEqualToString:@"1.2.840.10040.4.3"])
158 _signatureAlgorithm = @"dsa-with-sha1";
159 else if ([sigAlgOID isEqualToString:@"2.16.840.1.101.3.4.3.2"])
160 _signatureAlgorithm = @"dsa-with-sha256";
161 else if ([sigAlgOID isEqualToString:@"1.2.840.10045.4.1"])
162 _signatureAlgorithm = @"ecdsa-with-sha1";
163 else if ([sigAlgOID isEqualToString:@"1.2.840.10045.4.3.2"])
164 _signatureAlgorithm = @"ecdsa-with-sha256";
165 else if ([sigAlgOID isEqualToString:@"1.2.840.10045.4.3.3"])
166 _signatureAlgorithm = @"ecdsa-with-sha384";
167 else if ([sigAlgOID isEqualToString:@"1.2.840.10045.4.3.4"])
168 _signatureAlgorithm = @"ecdsa-with-sha512";
169 else
170 _signatureAlgorithm = [NSString stringWithFormat:@"Unknown (%@)", sigAlgOID];
171
172 /* cert issuer (hash of assorted keys like locale, org, etc.) */
173 NSArray *issuerData = [self safeFetchFromArray:cert atIndex:3 withType:[NSArray class]];
174 if (issuerData == nil)
175 return nil;
176 NSMutableDictionary *tissuer = [@{} mutableCopy];
177 for (int i = 0; i < [issuerData count]; i++) {
178 NSArray *pairA = [self safeFetchFromArray:issuerData atIndex:i withType:[NSArray class]];
179 if (pairA == nil)
180 continue;
181
182 for (int j = 0; j < [pairA count]; j++) {
183 NSArray *oidPair = [self safeFetchFromArray:pairA atIndex:j withType:[NSArray class]];
184 if (oidPair == nil)
185 return nil;
186
187 NSString *oid = [self safeFetchFromArray:oidPair atIndex:0 withType:[NSString class]];
188 if (oid == nil)
189 continue;
190 NSString *val = [self safeFetchFromArray:oidPair atIndex:1 withType:[NSString class]];
191 if (val == nil)
192 continue;
193
194 [self setOid:oid toValue:val inDictionary:tissuer];
195 }
196 }
197 _issuer = tissuer;
198
199 NSArray *validityPeriod = [self safeFetchFromArray:cert atIndex:4 withType:[NSArray class]];
200 if (validityPeriod == nil)
201 return nil;
202 _validityNotBefore = [self safeFetchFromArray:validityPeriod atIndex:0 withType:[NSDate class]];
203 if (_validityNotBefore == nil)
204 return nil;
205 _validityNotAfter = [self safeFetchFromArray:validityPeriod atIndex:1 withType:[NSDate class]];
206 if (_validityNotAfter == nil)
207 return nil;
208
209 NSMutableDictionary *tsubject = [@{} mutableCopy];
210 NSArray *tsubjectData = [self safeFetchFromArray:cert atIndex:5 withType:[NSArray class]];
211 if (tsubjectData == nil)
212 return nil;
213 for (int i = 0; i < [tsubjectData count]; i++) {
214 NSArray *pairA = [self safeFetchFromArray:tsubjectData atIndex:i withType:[NSArray class]];
215 if (pairA == nil)
216 continue;
217
218 for (int j = 0; j < [pairA count]; j++) {
219 NSArray *oidPair = [self safeFetchFromArray:pairA atIndex:j withType:[NSArray class]];
220 if (oidPair == nil)
221 return nil;
222
223 NSString *oid = [self safeFetchFromArray:oidPair atIndex:0 withType:[NSString class]];
224 if (oid == nil)
225 continue;
226 NSString *val = [self safeFetchFromArray:oidPair atIndex:1 withType:[NSString class]];
227 if (val == nil)
228 continue;
229
230 [self setOid:oid toValue:val inDictionary:tsubject];
231 }
232 }
233 _subject = tsubject;
234
235#ifdef TRACE
236 NSLog(@"[SSLCertificate] parsed certificate for %@: version=%@, serial=%@, sigalg=%@, issuer=%@, valid=%@ to %@", [_subject objectForKey:X509_KEY_CN], _version, _serialNumber, _signatureAlgorithm, [_issuer objectForKey:X509_KEY_CN], _validityNotBefore, _validityNotAfter);
237#endif
238
239 if ([certCache count] >= CERT_CACHE_SIZE) {
240 NSArray *sortedCerts = [[certCache allKeys] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
241 NSDate *da = [[certCache objectForKey:a] objectForKey:CERT_CACHE_KEY_TIME];
242 NSDate *db = [[certCache objectForKey:b] objectForKey:CERT_CACHE_KEY_TIME];
243 return [da compare:db];
244 }];
245
246 for (int i = 0; i < ([certCache count] - (CERT_CACHE_SIZE / 2)); i++)
247 [certCache removeObjectForKey:[sortedCerts objectAtIndex:i]];
248 }
249
250 ocdef = [[NSMutableDictionary alloc] initWithObjectsAndKeys:self, CERT_CACHE_KEY_CERT, [NSDate date], CERT_CACHE_KEY_TIME, nil];
251 [certCache setObject:ocdef forKey:certHash];
252
253 return self;
254}
255
256- (BOOL)isExpired
257{
258 return ([self validityNotAfter] > [NSDate date]);
259}
260
261- (BOOL)hasWeakSignatureAlgorithm
262{
263 return ([self signatureAlgorithm] != nil && [[[self signatureAlgorithm] lowercaseString] containsString:@"sha1"]);
264}
265
266- (id)safeFetchFromArray:(NSArray *)arr atIndex:(NSInteger)index withType:(Class)cType
267{
268 if (arr == nil) {
269 NSLog(@"[SSLCertificate] array is nil");
270 return nil;
271 }
272
273 if (index > ([arr count] - 1)) {
274 NSLog(@"[SSLCertificate] array count is %lu, need index %lu", (unsigned long)[arr count], (long)index);
275 return nil;
276 }
277
278 NSObject *ret;
279 @try {
280 ret = [arr objectAtIndex:index];
281 if (ret == nil) {
282 NSLog(@"[SSLCertificate] array object at index %lu is nil", (long)index);
283 return nil;
284 }
285 }
286 @catch(NSException *e) {
287 NSLog(@"[SSLCertificate] failed fetching object %lu from array: %@", (long)index, e);
288 return nil;
289 }
290
291 if (cType != nil && ![ret isKindOfClass:cType]) {
292 NSLog(@"[SSLCertificate] array object at index %lu is type %@, not %@", (long)index, NSStringFromClass([ret class]), cType);
293 return nil;
294 }
295
296 return ret;
297}
298
299- (void)setOid:(NSString *)oid toValue:(id)val inDictionary:(NSMutableDictionary *)dict
300{
301 /* TODO: what to do about conflicts? some certs have two OUs */
302
303 if ([oid isEqualToString:@"2.5.4.3"])
304 [dict setObject:val forKey:X509_KEY_CN]; /* CN=commonName */
305 else if ([oid isEqualToString:@"2.5.4.4"])
306 [dict setObject:val forKey:X509_KEY_SN]; /* SN=serial */
307 else if ([oid isEqualToString:@"2.5.4.5"])
308 [dict setObject:val forKey:X509_KEY_SERIAL]; /* SERIALNUMBER */
309 else if ([oid isEqualToString:@"2.5.4.6"])
310 [dict setObject:val forKey:X509_KEY_C]; /* C=country */
311 else if ([oid isEqualToString:@"2.5.4.7"])
312 [dict setObject:val forKey:X509_KEY_L]; /* L=locality */
313 else if ([oid isEqualToString:@"2.5.4.8"])
314 [dict setObject:val forKey:X509_KEY_ST]; /* ST=state/province */
315 else if ([oid isEqualToString:@"2.5.4.9"])
316 [dict setObject:val forKey:X509_KEY_STREET]; /* ST=state/province */
317 else if ([oid isEqualToString:@"2.5.4.10"])
318 [dict setObject:val forKey:X509_KEY_O]; /* O=organization */
319 else if ([oid isEqualToString:@"2.5.4.11"])
320 [dict setObject:val forKey:X509_KEY_OU]; /* OU=org unit */
321 else if ([oid isEqualToString:@"2.5.4.15"])
322 [dict setObject:val forKey:X509_KEY_BUSCAT];
323 else if ([oid isEqualToString:@"2.5.4.17"])
324 [dict setObject:val forKey:X509_KEY_ZIP];
325
326 else if (![dict objectForKey:oid])
327 [dict setObject:val forKey:[NSString stringWithFormat:@"Object Identifier %@", oid]];
328
329 return;
330}
331
332- (NSString *)negotiatedProtocolString
333{
334 switch ([self negotiatedProtocol]) {
335 case kSSLProtocol2:
336 return @"SSL 2.0";
337 case kSSLProtocol3:
338 return @"SSL 3.0";
339 case kTLSProtocol1:
340 return @"TLS 1.0";
341 case kTLSProtocol11:
342 return @"TLS 1.1";
343 case kTLSProtocol12:
344 return @"TLS 1.2";
345 case kTLSProtocol13:
346 return @"TLS 1.3";
347 default:
348 return [NSString stringWithFormat:@"Unknown (%d)", [self negotiatedProtocol]];
349 }
350}
351
352- (NSString *)negotiatedCipherString
353{
354 switch ([self negotiatedCipher]) {
355 case SSL_NULL_WITH_NULL_NULL:
356 return @"SSL_NULL_WITH_NULL_NULL";
357 case SSL_RSA_WITH_NULL_MD5:
358 return @"SSL_RSA_WITH_NULL_MD5";
359 case SSL_RSA_WITH_NULL_SHA:
360 return @"SSL_RSA_WITH_NULL_SHA";
361 case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
362 return @"SSL_RSA_EXPORT_WITH_RC4_40_MD5";
363 case SSL_RSA_WITH_RC4_128_MD5:
364 return @"SSL_RSA_WITH_RC4_128_MD5";
365 case SSL_RSA_WITH_RC4_128_SHA:
366 return @"SSL_RSA_WITH_RC4_128_SHA";
367 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
368 return @"SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
369 case SSL_RSA_WITH_IDEA_CBC_SHA:
370 return @"SSL_RSA_WITH_IDEA_CBC_SHA";
371 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
372 return @"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
373 case SSL_RSA_WITH_DES_CBC_SHA:
374 return @"SSL_RSA_WITH_DES_CBC_SHA";
375 case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
376 return @"SSL_RSA_WITH_3DES_EDE_CBC_SHA";
377 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
378 return @"SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
379 case SSL_DH_DSS_WITH_DES_CBC_SHA:
380 return @"SSL_DH_DSS_WITH_DES_CBC_SHA";
381 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
382 return @"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
383 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
384 return @"SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
385 case SSL_DH_RSA_WITH_DES_CBC_SHA:
386 return @"SSL_DH_RSA_WITH_DES_CBC_SHA";
387 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
388 return @"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
389 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
390 return @"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
391 case SSL_DHE_DSS_WITH_DES_CBC_SHA:
392 return @"SSL_DHE_DSS_WITH_DES_CBC_SHA";
393 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
394 return @"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
395 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
396 return @"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
397 case SSL_DHE_RSA_WITH_DES_CBC_SHA:
398 return @"SSL_DHE_RSA_WITH_DES_CBC_SHA";
399 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
400 return @"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
401 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
402 return @"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
403 case SSL_DH_anon_WITH_RC4_128_MD5:
404 return @"SSL_DH_anon_WITH_RC4_128_MD5";
405 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
406 return @"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
407 case SSL_DH_anon_WITH_DES_CBC_SHA:
408 return @"SSL_DH_anon_WITH_DES_CBC_SHA";
409 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
410 return @"SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
411 case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
412 return @"SSL_FORTEZZA_DMS_WITH_NULL_SHA";
413 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
414 return @"SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
415 case TLS_RSA_WITH_AES_128_CBC_SHA:
416 return @"TLS_RSA_WITH_AES_128_CBC_SHA";
417 case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
418 return @"TLS_DH_DSS_WITH_AES_128_CBC_SHA";
419 case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
420 return @"TLS_DH_RSA_WITH_AES_128_CBC_SHA";
421 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
422 return @"TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
423 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
424 return @"TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
425 case TLS_DH_anon_WITH_AES_128_CBC_SHA:
426 return @"TLS_DH_anon_WITH_AES_128_CBC_SHA";
427 case TLS_RSA_WITH_AES_256_CBC_SHA:
428 return @"TLS_RSA_WITH_AES_256_CBC_SHA";
429 case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
430 return @"TLS_DH_DSS_WITH_AES_256_CBC_SHA";
431 case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
432 return @"TLS_DH_RSA_WITH_AES_256_CBC_SHA";
433 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
434 return @"TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
435 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
436 return @"TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
437 case TLS_DH_anon_WITH_AES_256_CBC_SHA:
438 return @"TLS_DH_anon_WITH_AES_256_CBC_SHA";
439 case TLS_ECDH_ECDSA_WITH_NULL_SHA:
440 return @"TLS_ECDH_ECDSA_WITH_NULL_SHA";
441 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
442 return @"TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
443 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
444 return @"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
445 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
446 return @"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
447 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
448 return @"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
449 case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
450 return @"TLS_ECDHE_ECDSA_WITH_NULL_SHA";
451 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
452 return @"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
453 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
454 return @"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
455 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
456 return @"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
457 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
458 return @"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
459 case TLS_ECDH_RSA_WITH_NULL_SHA:
460 return @"TLS_ECDH_RSA_WITH_NULL_SHA";
461 case TLS_ECDH_RSA_WITH_RC4_128_SHA:
462 return @"TLS_ECDH_RSA_WITH_RC4_128_SHA";
463 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
464 return @"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
465 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
466 return @"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
467 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
468 return @"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
469 case TLS_ECDHE_RSA_WITH_NULL_SHA:
470 return @"TLS_ECDHE_RSA_WITH_NULL_SHA";
471 case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
472 return @"TLS_ECDHE_RSA_WITH_RC4_128_SHA";
473 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
474 return @"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
475 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
476 return @"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
477 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
478 return @"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
479 case TLS_ECDH_anon_WITH_NULL_SHA:
480 return @"TLS_ECDH_anon_WITH_NULL_SHA";
481 case TLS_ECDH_anon_WITH_RC4_128_SHA:
482 return @"TLS_ECDH_anon_WITH_RC4_128_SHA";
483 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
484 return @"TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
485 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
486 return @"TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
487 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
488 return @"TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
489#if 0
490 case TLS_NULL_WITH_NULL_NULL:
491 return @"TLS_NULL_WITH_NULL_NULL";
492 case TLS_RSA_WITH_NULL_MD5:
493 return @"TLS_RSA_WITH_NULL_MD5";
494 case TLS_RSA_WITH_NULL_SHA:
495 return @"TLS_RSA_WITH_NULL_SHA";
496 case TLS_RSA_WITH_RC4_128_MD5:
497 return @"TLS_RSA_WITH_RC4_128_MD5";
498 case TLS_RSA_WITH_RC4_128_SHA:
499 return @"TLS_RSA_WITH_RC4_128_SHA";
500 case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
501 return @"TLS_RSA_WITH_3DES_EDE_CBC_SHA";
502#endif
503 case TLS_RSA_WITH_NULL_SHA256:
504 return @"TLS_RSA_WITH_NULL_SHA256";
505 case TLS_RSA_WITH_AES_128_CBC_SHA256:
506 return @"TLS_RSA_WITH_AES_128_CBC_SHA256";
507 case TLS_RSA_WITH_AES_256_CBC_SHA256:
508 return @"TLS_RSA_WITH_AES_256_CBC_SHA256";
509#if 0
510 case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
511 return @"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
512 case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
513 return @"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
514 case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
515 return @"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
516 case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
517 return @"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
518#endif
519 case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
520 return @"TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
521 case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
522 return @"TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
523 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
524 return @"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
525 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
526 return @"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
527 case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
528 return @"TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
529 case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
530 return @"TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
531 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
532 return @"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
533 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
534 return @"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
535#if 0
536 case TLS_DH_anon_WITH_RC4_128_MD5:
537 return @"TLS_DH_anon_WITH_RC4_128_MD5";
538 case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
539 return @"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
540#endif
541 case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
542 return @"TLS_DH_anon_WITH_AES_128_CBC_SHA256";
543 case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
544 return @"TLS_DH_anon_WITH_AES_256_CBC_SHA256";
545 case TLS_PSK_WITH_RC4_128_SHA:
546 return @"TLS_PSK_WITH_RC4_128_SHA";
547 case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
548 return @"TLS_PSK_WITH_3DES_EDE_CBC_SHA";
549 case TLS_PSK_WITH_AES_128_CBC_SHA:
550 return @"TLS_PSK_WITH_AES_128_CBC_SHA";
551 case TLS_PSK_WITH_AES_256_CBC_SHA:
552 return @"TLS_PSK_WITH_AES_256_CBC_SHA";
553 case TLS_DHE_PSK_WITH_RC4_128_SHA:
554 return @"TLS_DHE_PSK_WITH_RC4_128_SHA";
555 case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
556 return @"TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
557 case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
558 return @"TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
559 case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
560 return @"TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
561 case TLS_RSA_PSK_WITH_RC4_128_SHA:
562 return @"TLS_RSA_PSK_WITH_RC4_128_SHA";
563 case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
564 return @"TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
565 case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
566 return @"TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
567 case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
568 return @"TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
569 case TLS_PSK_WITH_NULL_SHA:
570 return @"TLS_PSK_WITH_NULL_SHA";
571 case TLS_DHE_PSK_WITH_NULL_SHA:
572 return @"TLS_DHE_PSK_WITH_NULL_SHA";
573 case TLS_RSA_PSK_WITH_NULL_SHA:
574 return @"TLS_RSA_PSK_WITH_NULL_SHA";
575 case TLS_RSA_WITH_AES_128_GCM_SHA256:
576 return @"TLS_RSA_WITH_AES_128_GCM_SHA256";
577 case TLS_RSA_WITH_AES_256_GCM_SHA384:
578 return @"TLS_RSA_WITH_AES_256_GCM_SHA384";
579 case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
580 return @"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
581 case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
582 return @"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
583 case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
584 return @"TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
585 case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
586 return @"TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
587 case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
588 return @"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
589 case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
590 return @"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
591 case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
592 return @"TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
593 case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
594 return @"TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
595 case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
596 return @"TLS_DH_anon_WITH_AES_128_GCM_SHA256";
597 case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
598 return @"TLS_DH_anon_WITH_AES_256_GCM_SHA384";
599 case TLS_PSK_WITH_AES_128_GCM_SHA256:
600 return @"TLS_PSK_WITH_AES_128_GCM_SHA256";
601 case TLS_PSK_WITH_AES_256_GCM_SHA384:
602 return @"TLS_PSK_WITH_AES_256_GCM_SHA384";
603 case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
604 return @"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
605 case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
606 return @"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
607 case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
608 return @"TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
609 case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
610 return @"TLS_RSA_PSK_WITH_AES_256_GCM_SHA384";
611 case TLS_PSK_WITH_AES_128_CBC_SHA256:
612 return @"TLS_PSK_WITH_AES_128_CBC_SHA256";
613 case TLS_PSK_WITH_AES_256_CBC_SHA384:
614 return @"TLS_PSK_WITH_AES_256_CBC_SHA384";
615 case TLS_PSK_WITH_NULL_SHA256:
616 return @"TLS_PSK_WITH_NULL_SHA256";
617 case TLS_PSK_WITH_NULL_SHA384:
618 return @"TLS_PSK_WITH_NULL_SHA384";
619 case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
620 return @"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
621 case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
622 return @"TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
623 case TLS_DHE_PSK_WITH_NULL_SHA256:
624 return @"TLS_DHE_PSK_WITH_NULL_SHA256";
625 case TLS_DHE_PSK_WITH_NULL_SHA384:
626 return @"TLS_DHE_PSK_WITH_NULL_SHA384";
627 case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
628 return @"TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
629 case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
630 return @"TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
631 case TLS_RSA_PSK_WITH_NULL_SHA256:
632 return @"TLS_RSA_PSK_WITH_NULL_SHA256";
633 case TLS_RSA_PSK_WITH_NULL_SHA384:
634 return @"TLS_RSA_PSK_WITH_NULL_SHA384";
635 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
636 return @"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
637 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
638 return @"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
639 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
640 return @"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
641 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
642 return @"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
643 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
644 return @"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
645 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
646 return @"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
647 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
648 return @"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
649 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
650 return @"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
651 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
652 return @"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
653 case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
654 return @"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
655 case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
656 return @"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
657 case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
658 return @"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
659 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
660 return @"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
661 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
662 return @"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
663 case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
664 return @"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
665 case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
666 return @"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
667 case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
668 return @"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
669 case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
670 return @"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
671 case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
672 return @"TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
673 case SSL_RSA_WITH_RC2_CBC_MD5:
674 return @"SSL_RSA_WITH_RC2_CBC_MD5";
675 case SSL_RSA_WITH_IDEA_CBC_MD5:
676 return @"SSL_RSA_WITH_IDEA_CBC_MD5";
677 case SSL_RSA_WITH_DES_CBC_MD5:
678 return @"SSL_RSA_WITH_DES_CBC_MD5";
679 case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
680 return @"SSL_RSA_WITH_3DES_EDE_CBC_MD5";
681 case SSL_NO_SUCH_CIPHERSUITE:
682 return @"SSL_NO_SUCH_CIPHERSUITE";
683 default:
684 return [NSString stringWithFormat:@"Unknown (%d)", [self negotiatedCipher]];
685 }
686}
687
688@end