264d564dbda676b52f446c0d25433a15939a78a3
[subu] /
1 """
2 This module uses ctypes to bind a whole bunch of functions and constants from
3 SecureTransport. The goal here is to provide the low-level API to
4 SecureTransport. These are essentially the C-level functions and constants, and
5 they're pretty gross to work with.
6
7 This code is a bastardised version of the code found in Will Bond's oscrypto
8 library. An enormous debt is owed to him for blazing this trail for us. For
9 that reason, this code should be considered to be covered both by urllib3's
10 license and by oscrypto's:
11
12     Copyright (c) 2015-2016 Will Bond <will@wbond.net>
13
14     Permission is hereby granted, free of charge, to any person obtaining a
15     copy of this software and associated documentation files (the "Software"),
16     to deal in the Software without restriction, including without limitation
17     the rights to use, copy, modify, merge, publish, distribute, sublicense,
18     and/or sell copies of the Software, and to permit persons to whom the
19     Software is furnished to do so, subject to the following conditions:
20
21     The above copyright notice and this permission notice shall be included in
22     all copies or substantial portions of the Software.
23
24     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30     DEALINGS IN THE SOFTWARE.
31 """
32 from __future__ import absolute_import
33
34 import platform
35 from ctypes import (
36     CDLL,
37     CFUNCTYPE,
38     POINTER,
39     c_bool,
40     c_byte,
41     c_char_p,
42     c_int32,
43     c_long,
44     c_size_t,
45     c_uint32,
46     c_ulong,
47     c_void_p,
48 )
49 from ctypes.util import find_library
50
51 from ...packages.six import raise_from
52
53 if platform.system() != "Darwin":
54     raise ImportError("Only macOS is supported")
55
56 version = platform.mac_ver()[0]
57 version_info = tuple(map(int, version.split(".")))
58 if version_info < (10, 8):
59     raise OSError(
60         "Only OS X 10.8 and newer are supported, not %s.%s"
61         % (version_info[0], version_info[1])
62     )
63
64
65 def load_cdll(name, macos10_16_path):
66     """Loads a CDLL by name, falling back to known path on 10.16+"""
67     try:
68         # Big Sur is technically 11 but we use 10.16 due to the Big Sur
69         # beta being labeled as 10.16.
70         if version_info >= (10, 16):
71             path = macos10_16_path
72         else:
73             path = find_library(name)
74         if not path:
75             raise OSError  # Caught and reraised as 'ImportError'
76         return CDLL(path, use_errno=True)
77     except OSError:
78         raise_from(ImportError("The library %s failed to load" % name), None)
79
80
81 Security = load_cdll(
82     "Security", "/System/Library/Frameworks/Security.framework/Security"
83 )
84 CoreFoundation = load_cdll(
85     "CoreFoundation",
86     "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
87 )
88
89
90 Boolean = c_bool
91 CFIndex = c_long
92 CFStringEncoding = c_uint32
93 CFData = c_void_p
94 CFString = c_void_p
95 CFArray = c_void_p
96 CFMutableArray = c_void_p
97 CFDictionary = c_void_p
98 CFError = c_void_p
99 CFType = c_void_p
100 CFTypeID = c_ulong
101
102 CFTypeRef = POINTER(CFType)
103 CFAllocatorRef = c_void_p
104
105 OSStatus = c_int32
106
107 CFDataRef = POINTER(CFData)
108 CFStringRef = POINTER(CFString)
109 CFArrayRef = POINTER(CFArray)
110 CFMutableArrayRef = POINTER(CFMutableArray)
111 CFDictionaryRef = POINTER(CFDictionary)
112 CFArrayCallBacks = c_void_p
113 CFDictionaryKeyCallBacks = c_void_p
114 CFDictionaryValueCallBacks = c_void_p
115
116 SecCertificateRef = POINTER(c_void_p)
117 SecExternalFormat = c_uint32
118 SecExternalItemType = c_uint32
119 SecIdentityRef = POINTER(c_void_p)
120 SecItemImportExportFlags = c_uint32
121 SecItemImportExportKeyParameters = c_void_p
122 SecKeychainRef = POINTER(c_void_p)
123 SSLProtocol = c_uint32
124 SSLCipherSuite = c_uint32
125 SSLContextRef = POINTER(c_void_p)
126 SecTrustRef = POINTER(c_void_p)
127 SSLConnectionRef = c_uint32
128 SecTrustResultType = c_uint32
129 SecTrustOptionFlags = c_uint32
130 SSLProtocolSide = c_uint32
131 SSLConnectionType = c_uint32
132 SSLSessionOption = c_uint32
133
134
135 try:
136     Security.SecItemImport.argtypes = [
137         CFDataRef,
138         CFStringRef,
139         POINTER(SecExternalFormat),
140         POINTER(SecExternalItemType),
141         SecItemImportExportFlags,
142         POINTER(SecItemImportExportKeyParameters),
143         SecKeychainRef,
144         POINTER(CFArrayRef),
145     ]
146     Security.SecItemImport.restype = OSStatus
147
148     Security.SecCertificateGetTypeID.argtypes = []
149     Security.SecCertificateGetTypeID.restype = CFTypeID
150
151     Security.SecIdentityGetTypeID.argtypes = []
152     Security.SecIdentityGetTypeID.restype = CFTypeID
153
154     Security.SecKeyGetTypeID.argtypes = []
155     Security.SecKeyGetTypeID.restype = CFTypeID
156
157     Security.SecCertificateCreateWithData.argtypes = [CFAllocatorRef, CFDataRef]
158     Security.SecCertificateCreateWithData.restype = SecCertificateRef
159
160     Security.SecCertificateCopyData.argtypes = [SecCertificateRef]
161     Security.SecCertificateCopyData.restype = CFDataRef
162
163     Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p]
164     Security.SecCopyErrorMessageString.restype = CFStringRef
165
166     Security.SecIdentityCreateWithCertificate.argtypes = [
167         CFTypeRef,
168         SecCertificateRef,
169         POINTER(SecIdentityRef),
170     ]
171     Security.SecIdentityCreateWithCertificate.restype = OSStatus
172
173     Security.SecKeychainCreate.argtypes = [
174         c_char_p,
175         c_uint32,
176         c_void_p,
177         Boolean,
178         c_void_p,
179         POINTER(SecKeychainRef),
180     ]
181     Security.SecKeychainCreate.restype = OSStatus
182
183     Security.SecKeychainDelete.argtypes = [SecKeychainRef]
184     Security.SecKeychainDelete.restype = OSStatus
185
186     Security.SecPKCS12Import.argtypes = [
187         CFDataRef,
188         CFDictionaryRef,
189         POINTER(CFArrayRef),
190     ]
191     Security.SecPKCS12Import.restype = OSStatus
192
193     SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t))
194     SSLWriteFunc = CFUNCTYPE(
195         OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)
196     )
197
198     Security.SSLSetIOFuncs.argtypes = [SSLContextRef, SSLReadFunc, SSLWriteFunc]
199     Security.SSLSetIOFuncs.restype = OSStatus
200
201     Security.SSLSetPeerID.argtypes = [SSLContextRef, c_char_p, c_size_t]
202     Security.SSLSetPeerID.restype = OSStatus
203
204     Security.SSLSetCertificate.argtypes = [SSLContextRef, CFArrayRef]
205     Security.SSLSetCertificate.restype = OSStatus
206
207     Security.SSLSetCertificateAuthorities.argtypes = [SSLContextRef, CFTypeRef, Boolean]
208     Security.SSLSetCertificateAuthorities.restype = OSStatus
209
210     Security.SSLSetConnection.argtypes = [SSLContextRef, SSLConnectionRef]
211     Security.SSLSetConnection.restype = OSStatus
212
213     Security.SSLSetPeerDomainName.argtypes = [SSLContextRef, c_char_p, c_size_t]
214     Security.SSLSetPeerDomainName.restype = OSStatus
215
216     Security.SSLHandshake.argtypes = [SSLContextRef]
217     Security.SSLHandshake.restype = OSStatus
218
219     Security.SSLRead.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)]
220     Security.SSLRead.restype = OSStatus
221
222     Security.SSLWrite.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)]
223     Security.SSLWrite.restype = OSStatus
224
225     Security.SSLClose.argtypes = [SSLContextRef]
226     Security.SSLClose.restype = OSStatus
227
228     Security.SSLGetNumberSupportedCiphers.argtypes = [SSLContextRef, POINTER(c_size_t)]
229     Security.SSLGetNumberSupportedCiphers.restype = OSStatus
230
231     Security.SSLGetSupportedCiphers.argtypes = [
232         SSLContextRef,
233         POINTER(SSLCipherSuite),
234         POINTER(c_size_t),
235     ]
236     Security.SSLGetSupportedCiphers.restype = OSStatus
237
238     Security.SSLSetEnabledCiphers.argtypes = [
239         SSLContextRef,
240         POINTER(SSLCipherSuite),
241         c_size_t,
242     ]
243     Security.SSLSetEnabledCiphers.restype = OSStatus
244
245     Security.SSLGetNumberEnabledCiphers.argtype = [SSLContextRef, POINTER(c_size_t)]
246     Security.SSLGetNumberEnabledCiphers.restype = OSStatus
247
248     Security.SSLGetEnabledCiphers.argtypes = [
249         SSLContextRef,
250         POINTER(SSLCipherSuite),
251         POINTER(c_size_t),
252     ]
253     Security.SSLGetEnabledCiphers.restype = OSStatus
254
255     Security.SSLGetNegotiatedCipher.argtypes = [SSLContextRef, POINTER(SSLCipherSuite)]
256     Security.SSLGetNegotiatedCipher.restype = OSStatus
257
258     Security.SSLGetNegotiatedProtocolVersion.argtypes = [
259         SSLContextRef,
260         POINTER(SSLProtocol),
261     ]
262     Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus
263
264     Security.SSLCopyPeerTrust.argtypes = [SSLContextRef, POINTER(SecTrustRef)]
265     Security.SSLCopyPeerTrust.restype = OSStatus
266
267     Security.SecTrustSetAnchorCertificates.argtypes = [SecTrustRef, CFArrayRef]
268     Security.SecTrustSetAnchorCertificates.restype = OSStatus
269
270     Security.SecTrustSetAnchorCertificatesOnly.argstypes = [SecTrustRef, Boolean]
271     Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus
272
273     Security.SecTrustEvaluate.argtypes = [SecTrustRef, POINTER(SecTrustResultType)]
274     Security.SecTrustEvaluate.restype = OSStatus
275
276     Security.SecTrustGetCertificateCount.argtypes = [SecTrustRef]
277     Security.SecTrustGetCertificateCount.restype = CFIndex
278
279     Security.SecTrustGetCertificateAtIndex.argtypes = [SecTrustRef, CFIndex]
280     Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef
281
282     Security.SSLCreateContext.argtypes = [
283         CFAllocatorRef,
284         SSLProtocolSide,
285         SSLConnectionType,
286     ]
287     Security.SSLCreateContext.restype = SSLContextRef
288
289     Security.SSLSetSessionOption.argtypes = [SSLContextRef, SSLSessionOption, Boolean]
290     Security.SSLSetSessionOption.restype = OSStatus
291
292     Security.SSLSetProtocolVersionMin.argtypes = [SSLContextRef, SSLProtocol]
293     Security.SSLSetProtocolVersionMin.restype = OSStatus
294
295     Security.SSLSetProtocolVersionMax.argtypes = [SSLContextRef, SSLProtocol]
296     Security.SSLSetProtocolVersionMax.restype = OSStatus
297
298     try:
299         Security.SSLSetALPNProtocols.argtypes = [SSLContextRef, CFArrayRef]
300         Security.SSLSetALPNProtocols.restype = OSStatus
301     except AttributeError:
302         # Supported only in 10.12+
303         pass
304
305     Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p]
306     Security.SecCopyErrorMessageString.restype = CFStringRef
307
308     Security.SSLReadFunc = SSLReadFunc
309     Security.SSLWriteFunc = SSLWriteFunc
310     Security.SSLContextRef = SSLContextRef
311     Security.SSLProtocol = SSLProtocol
312     Security.SSLCipherSuite = SSLCipherSuite
313     Security.SecIdentityRef = SecIdentityRef
314     Security.SecKeychainRef = SecKeychainRef
315     Security.SecTrustRef = SecTrustRef
316     Security.SecTrustResultType = SecTrustResultType
317     Security.SecExternalFormat = SecExternalFormat
318     Security.OSStatus = OSStatus
319
320     Security.kSecImportExportPassphrase = CFStringRef.in_dll(
321         Security, "kSecImportExportPassphrase"
322     )
323     Security.kSecImportItemIdentity = CFStringRef.in_dll(
324         Security, "kSecImportItemIdentity"
325     )
326
327     # CoreFoundation time!
328     CoreFoundation.CFRetain.argtypes = [CFTypeRef]
329     CoreFoundation.CFRetain.restype = CFTypeRef
330
331     CoreFoundation.CFRelease.argtypes = [CFTypeRef]
332     CoreFoundation.CFRelease.restype = None
333
334     CoreFoundation.CFGetTypeID.argtypes = [CFTypeRef]
335     CoreFoundation.CFGetTypeID.restype = CFTypeID
336
337     CoreFoundation.CFStringCreateWithCString.argtypes = [
338         CFAllocatorRef,
339         c_char_p,
340         CFStringEncoding,
341     ]
342     CoreFoundation.CFStringCreateWithCString.restype = CFStringRef
343
344     CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding]
345     CoreFoundation.CFStringGetCStringPtr.restype = c_char_p
346
347     CoreFoundation.CFStringGetCString.argtypes = [
348         CFStringRef,
349         c_char_p,
350         CFIndex,
351         CFStringEncoding,
352     ]
353     CoreFoundation.CFStringGetCString.restype = c_bool
354
355     CoreFoundation.CFDataCreate.argtypes = [CFAllocatorRef, c_char_p, CFIndex]
356     CoreFoundation.CFDataCreate.restype = CFDataRef
357
358     CoreFoundation.CFDataGetLength.argtypes = [CFDataRef]
359     CoreFoundation.CFDataGetLength.restype = CFIndex
360
361     CoreFoundation.CFDataGetBytePtr.argtypes = [CFDataRef]
362     CoreFoundation.CFDataGetBytePtr.restype = c_void_p
363
364     CoreFoundation.CFDictionaryCreate.argtypes = [
365         CFAllocatorRef,
366         POINTER(CFTypeRef),
367         POINTER(CFTypeRef),
368         CFIndex,
369         CFDictionaryKeyCallBacks,
370         CFDictionaryValueCallBacks,
371     ]
372     CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef
373
374     CoreFoundation.CFDictionaryGetValue.argtypes = [CFDictionaryRef, CFTypeRef]
375     CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef
376
377     CoreFoundation.CFArrayCreate.argtypes = [
378         CFAllocatorRef,
379         POINTER(CFTypeRef),
380         CFIndex,
381         CFArrayCallBacks,
382     ]
383     CoreFoundation.CFArrayCreate.restype = CFArrayRef
384
385     CoreFoundation.CFArrayCreateMutable.argtypes = [
386         CFAllocatorRef,
387         CFIndex,
388         CFArrayCallBacks,
389     ]
390     CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef
391
392     CoreFoundation.CFArrayAppendValue.argtypes = [CFMutableArrayRef, c_void_p]
393     CoreFoundation.CFArrayAppendValue.restype = None
394
395     CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef]
396     CoreFoundation.CFArrayGetCount.restype = CFIndex
397
398     CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex]
399     CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p
400
401     CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll(
402         CoreFoundation, "kCFAllocatorDefault"
403     )
404     CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll(
405         CoreFoundation, "kCFTypeArrayCallBacks"
406     )
407     CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll(
408         CoreFoundation, "kCFTypeDictionaryKeyCallBacks"
409     )
410     CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll(
411         CoreFoundation, "kCFTypeDictionaryValueCallBacks"
412     )
413
414     CoreFoundation.CFTypeRef = CFTypeRef
415     CoreFoundation.CFArrayRef = CFArrayRef
416     CoreFoundation.CFStringRef = CFStringRef
417     CoreFoundation.CFDictionaryRef = CFDictionaryRef
418
419 except (AttributeError):
420     raise ImportError("Error initializing ctypes")
421
422
423 class CFConst(object):
424     """
425     A class object that acts as essentially a namespace for CoreFoundation
426     constants.
427     """
428
429     kCFStringEncodingUTF8 = CFStringEncoding(0x08000100)
430
431
432 class SecurityConst(object):
433     """
434     A class object that acts as essentially a namespace for Security constants.
435     """
436
437     kSSLSessionOptionBreakOnServerAuth = 0
438
439     kSSLProtocol2 = 1
440     kSSLProtocol3 = 2
441     kTLSProtocol1 = 4
442     kTLSProtocol11 = 7
443     kTLSProtocol12 = 8
444     # SecureTransport does not support TLS 1.3 even if there's a constant for it
445     kTLSProtocol13 = 10
446     kTLSProtocolMaxSupported = 999
447
448     kSSLClientSide = 1
449     kSSLStreamType = 0
450
451     kSecFormatPEMSequence = 10
452
453     kSecTrustResultInvalid = 0
454     kSecTrustResultProceed = 1
455     # This gap is present on purpose: this was kSecTrustResultConfirm, which
456     # is deprecated.
457     kSecTrustResultDeny = 3
458     kSecTrustResultUnspecified = 4
459     kSecTrustResultRecoverableTrustFailure = 5
460     kSecTrustResultFatalTrustFailure = 6
461     kSecTrustResultOtherError = 7
462
463     errSSLProtocol = -9800
464     errSSLWouldBlock = -9803
465     errSSLClosedGraceful = -9805
466     errSSLClosedNoNotify = -9816
467     errSSLClosedAbort = -9806
468
469     errSSLXCertChainInvalid = -9807
470     errSSLCrypto = -9809
471     errSSLInternal = -9810
472     errSSLCertExpired = -9814
473     errSSLCertNotYetValid = -9815
474     errSSLUnknownRootCert = -9812
475     errSSLNoRootCert = -9813
476     errSSLHostNameMismatch = -9843
477     errSSLPeerHandshakeFail = -9824
478     errSSLPeerUserCancelled = -9839
479     errSSLWeakPeerEphemeralDHKey = -9850
480     errSSLServerAuthCompleted = -9841
481     errSSLRecordOverflow = -9847
482
483     errSecVerifyFailed = -67808
484     errSecNoTrustSettings = -25263
485     errSecItemNotFound = -25300
486     errSecInvalidTrustSettings = -25262
487
488     # Cipher suites. We only pick the ones our default cipher string allows.
489     # Source: https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values
490     TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C
491     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030
492     TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B
493     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F
494     TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9
495     TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8
496     TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F
497     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
498     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024
499     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028
500     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A
501     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014
502     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
503     TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
504     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023
505     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027
506     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009
507     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013
508     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
509     TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
510     TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D
511     TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
512     TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
513     TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
514     TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
515     TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F
516     TLS_AES_128_GCM_SHA256 = 0x1301
517     TLS_AES_256_GCM_SHA384 = 0x1302
518     TLS_AES_128_CCM_8_SHA256 = 0x1305
519     TLS_AES_128_CCM_SHA256 = 0x1304