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