1"""
2This module uses ctypes to bind a whole bunch of functions and constants from
3SecureTransport. The goal here is to provide the low-level API to
4SecureTransport. These are essentially the C-level functions and constants, and
5they're pretty gross to work with.
6
7This code is a bastardised version of the code found in Will Bond's oscrypto
8library. An enormous debt is owed to him for blazing this trail for us. For
9that reason, this code should be considered to be covered both by urllib3's
10license 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"""
32from __future__ import absolute_import
33
34import platform
35from 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)
49from ctypes.util import find_library
50
51from urllib3.packages.six import raise_from
52
53if platform.system() != "Darwin":
54    raise ImportError("Only macOS is supported")
55
56version = platform.mac_ver()[0]
57version_info = tuple(map(int, version.split(".")))
58if 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
65def 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
81Security = load_cdll(
82    "Security", "/System/Library/Frameworks/Security.framework/Security"
83)
84CoreFoundation = load_cdll(
85    "CoreFoundation",
86    "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
87)
88
89
90Boolean = c_bool
91CFIndex = c_long
92CFStringEncoding = c_uint32
93CFData = c_void_p
94CFString = c_void_p
95CFArray = c_void_p
96CFMutableArray = c_void_p
97CFDictionary = c_void_p
98CFError = c_void_p
99CFType = c_void_p
100CFTypeID = c_ulong
101
102CFTypeRef = POINTER(CFType)
103CFAllocatorRef = c_void_p
104
105OSStatus = c_int32
106
107CFDataRef = POINTER(CFData)
108CFStringRef = POINTER(CFString)
109CFArrayRef = POINTER(CFArray)
110CFMutableArrayRef = POINTER(CFMutableArray)
111CFDictionaryRef = POINTER(CFDictionary)
112CFArrayCallBacks = c_void_p
113CFDictionaryKeyCallBacks = c_void_p
114CFDictionaryValueCallBacks = c_void_p
115
116SecCertificateRef = POINTER(c_void_p)
117SecExternalFormat = c_uint32
118SecExternalItemType = c_uint32
119SecIdentityRef = POINTER(c_void_p)
120SecItemImportExportFlags = c_uint32
121SecItemImportExportKeyParameters = c_void_p
122SecKeychainRef = POINTER(c_void_p)
123SSLProtocol = c_uint32
124SSLCipherSuite = c_uint32
125SSLContextRef = POINTER(c_void_p)
126SecTrustRef = POINTER(c_void_p)
127SSLConnectionRef = c_uint32
128SecTrustResultType = c_uint32
129SecTrustOptionFlags = c_uint32
130SSLProtocolSide = c_uint32
131SSLConnectionType = c_uint32
132SSLSessionOption = c_uint32
133
134
135try:
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
419except (AttributeError):
420    raise ImportError("Error initializing ctypes")
421
422
423class 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
432class 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
520