Skip to content

extmod/modussl_mbedtls.c: Add missing args and constants to ssl module. #8252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

Carglglz
Copy link
Contributor

@Carglglz Carglglz commented Feb 2, 2022

This PR adds cert_reqs , ca_certs arguments to ssl.wrap_socket and
ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED constants to ssl module following documentation.

This enables mutual authentication (mTLS), so it possible to authenticate both servers and clients.

Also I'm aware there is a previous draft of this at #5998 however there the authentication mode is hard coded to optional (MBEDTLS_SSL_VERIFY_OPTIONAL) which may not be recommended

On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at the right time(s), which may not be obvious, while REQUIRED always perform the verification as soon as possible. For example, REQUIRED was protecting against the "triple handshake" attack even before it was found.

I'm not sure if these lines could be just one line or if it is better this way?

int certreq = (args->cert_reqs.u_int);
mbedtls_ssl_conf_authmode(&o->conf, certreq);

Also here

{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}

It may be better use MBEDTLS_SSL_VERIFY_NONE for clarity?

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Feb 2, 2022
@codecov-commenter
Copy link

codecov-commenter commented Feb 2, 2022

Codecov Report

Merging #8252 (3617428) into master (262f4a4) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master    #8252   +/-   ##
=======================================
  Coverage   98.33%   98.33%           
=======================================
  Files         157      157           
  Lines       20348    20348           
=======================================
  Hits        20010    20010           
  Misses        338      338           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 262f4a4...3617428. Read the comment docs.

@Carglglz Carglglz force-pushed the ssl-add-args branch 2 times, most recently from 9617569 to 723422d Compare February 3, 2022 14:31
@Carglglz Carglglz force-pushed the ssl-add-args branch 2 times, most recently from 0fef7d0 to aebd7f8 Compare July 8, 2022 15:36
@dpgeorge
Copy link
Member

It may be better use MBEDTLS_SSL_VERIFY_NONE for clarity?

Yes I think that would be good. Is that the same default that CPython has?

As mentioned in #8854, I'd prefer to merge this PR for the core ca_certs support. Are you able to add docs and tests for this new feature? Document the 2 new keyword args, and add a test similar to that in #5998.

@Carglglz
Copy link
Contributor Author

Carglglz commented Jul 12, 2022

Are you able to add docs and tests for this new feature? Document the 2 new keyword args, and add a test similar to that in #5998.

Docs I can for sure, tests I'm working on it.
So far self-signed key, cert works but certs from google.com or micropython.org fails with

Address infos: [(2, 1, 0, 'micropython.org', ('176.58.119.26', 443))]
Connect address: ('176.58.119.26', 443)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "http_ssl_test.py", line 60, in <module>
  File "http_ssl_test.py", line 49, in main
OSError: (-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED')

For self-signed key, cert I tested ECC and RSA:

ECC key, cert

$ openssl ecparam -out ec-cakey.pem -name prime256v1 -genkey
$ openssl req -new -x509 -days 3650 -key ec-cakey.pem -out ec-cacert.pem

Then I used a modified version of test/multi_net/ssl_data.py

ssl_ecc_auth.py

# Simple test creating an SSL connection and transferring some data
# This test won't run under CPython because it requires key/cert

try:
    import ubinascii as binascii, usocket as socket, ussl as ssl
except ImportError:
    print("SKIP")
    raise SystemExit

PORT = 8000

# This self-signed key/cert pair is randomly generated and to be used for
# testing/demonstration only.  You should always generate your own key/cert.
cert = b"""-----BEGIN CERTIFICATE-----
MIICSTCCAe+gAwIBAgIJAK7kDH3KW/pbMAoGCCqGSM49BAMCMIGAMQswCQYDVQQG
EwJBVTEMMAoGA1UECAwDRm9vMQwwCgYDVQQHDANCYXIxFDASBgNVBAoMC01pY3Jv
UHl0aG9uMQswCQYDVQQLDAJNUDEWMBQGA1UEAwwNZXNwaG9tZS5sb2NhbDEaMBgG
CSqGSIb3DQEJARYLZm9vQGJhci5jb20wHhcNMjIwNzEyMTcxOTU5WhcNMzIwNzA5
MTcxOTU5WjCBgDELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA0ZvbzEMMAoGA1UEBwwD
QmFyMRQwEgYDVQQKDAtNaWNyb1B5dGhvbjELMAkGA1UECwwCTVAxFjAUBgNVBAMM
DWVzcGhvbWUubG9jYWwxGjAYBgkqhkiG9w0BCQEWC2Zvb0BiYXIuY29tMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEmuTTWsQ44oUgEt/fpjm33x2JbS8FdiVnC2Cc
4QFUsr8AqVTOwCzqqDO6MvXask8WyBjmROV0NS1QAp8zM8CnlqNQME4wHQYDVR0O
BBYEFLS6piYUhW4Z3l6DSyNC6BuJetg9MB8GA1UdIwQYMBaAFLS6piYUhW4Z3l6D
SyNC6BuJetg9MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgaoRjizC+
AvvlQQjl6Jw3lFCxvuYrwy4YwNKgqJDyz8UCIQCFyMWi4kkniUZxhCZwuvJiPXl/
HFSxkQyQfayCKkApCA==
-----END CERTIFICATE-----"""

key = b"""-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEII9I4GhoeGqhgOz5Ybqh5NTEwLQmli1jIzvrr6/6clLSoAoGCCqGSM49
AwEHoUQDQgAEmuTTWsQ44oUgEt/fpjm33x2JbS8FdiVnC2Cc4QFUsr8AqVTOwCzq
qDO6MvXask8WyBjmROV0NS1QAp8zM8Cnlg==
-----END EC PRIVATE KEY-----"""


# Server
def instance0():

    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
    s.listen(1)

    s2, _ = s.accept()
    s2 = ssl.wrap_socket(s2, server_side=True, key=key, cert=cert)
    print(s2.read(16))
    s2.write(b"server to client")
    s2.close()
    s.close()


# Client
def instance1():

    s = socket.socket()
    s.connect(socket.getaddrinfo('esphome.local', PORT)[0][-1])
    s = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs=cert)
    s.write(b"client to server")
    print(s.read(16))
    s.close()

One of the esp32 is running instance0() (server with hostname esphome.local )
and the other instance1()

Server

>>> from ssl_ecc_auth import instance0
>>> instance0()
b'client to server'
>>>

Client

>>> from ssl_ecc_auth import instance1
>>> instance1()
b'server to client'
>>>

This works too with RSA

RSA key, cert

$ openssl req -x509 -newkey rsa:4096 -keyout rsa_key.pem -out rsa_cert.pem -days 365 -node

The rest is the same I've just changed key, cert and named the test ssl_rsa_auth.py

@Carglglz
Copy link
Contributor Author

Carglglz commented Jul 12, 2022

Ok I figured out what I was doing wrong, I wasn't using the entire cert chain or at least the correct cert.

This works for micropython.org

I get the cert chain with

$ openssl s_client -showcerts -connect micropython.org:443 </dev/null 2>/dev/null
CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=dpgeorge.net
   i:/C=US/O=Let's Encrypt/CN=R3
-----BEGIN CERTIFICATE-----
MIIFHzCCBAegAwIBAgISBDNT3d/NtE1ppCrdRpyVve9rMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMjA1MjYwNzQ1MTJaFw0yMjA4MjQwNzQ1MTFaMBcxFTATBgNVBAMT
DGRwZ2VvcmdlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALt3
Kx60TijbUvhOSCgCY4BDwYcmTTKoBm9bpXrhaYoCJEX05lCXghnEuWvudjvRsfuK
paKo1i03lzCcdOoAorcqlwTVO09XKdEAtNi7bBpbr8ajqB7ptRm9aGLWi2p0lTGp
+uyNY6LUjNgCf/VJvFddPOS8q0TNhakdgG8BR31PDAxuWy3wA2YTv8Ppj089elEY
UmPhFIm1YSnMH3Owjtukwv0r3pe03AJ760Lgm4hHZO2S0H/qH0gyoWkHbq+e7Ba8
4gtursn7M6E2vWBNgFsV1fZTyIRmyWBRgIVSIxGU4ultzmfJQI/hRgD8cnOnZrrC
Ns3+1bwFMXSiuKIhBU0CAwEAAaOCAkgwggJEMA4GA1UdDwEB/wQEAwIFoDAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
FgQUHlWp/zVL6yP4hjPIT5MgkdnuU6wwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA
5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMu
by5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8w
FwYDVR0RBBAwDoIMZHBnZW9yZ2UubmV0MEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
cHQub3JnMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHcAKXm+8J45OSHwVnOfY6V3
5b5XfZxgCvj5TV0mXCVdx4QAAAGA/4qQPwAABAMASDBGAiEAlvSRyAAttg6WPIdn
hKh8ErL9qJBDq3OtcHntRxMCTAsCIQDhofbSXGUEyIe9pdavm+lMQUn3Pm5NjApj
sZC0klwBpgB2AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABgP+K
kb0AAAQDAEcwRQIhAK29v0DD0yJ+m9pTfmRl+7f81NBJhAoEOUIwP7reiCxFAiBU
+JL/eDTynJYoP4ApO0Fkld6K7NpssZQf8ORlwVs/STANBgkqhkiG9w0BAQsFAAOC
AQEAVBMxcjf0FdQrsLetAZBkWi6ONVQYzTA1YSOzP1WMuenmd6uQY+j50iJv7RPX
KW4tmI0qjIWU32xlFxZLrZyWiplUXt4Vq19YvEygWk9pzjR4QBr/lmsk5YPKfY9u
z7faFDn/r4UrUdgGtaqO4HpVoXSQ9TGs9hYwdXyJPfIvsX431g8K+Fw/Kd9g3vlQ
IVFcjsVN9dafdz3e5VvKCXrZOqct5WbhcYqkfm4ehl7/PA16D0Y8b/8uWzemWxut
T1laVGkPtQuPqd1ZdralR1Jsjk6CgxhGuEH60u4xY7QwyRcS83951z/6jJPIE5Ss
H3+JgRraIhzr2urkEQaedBPK/g==
-----END CERTIFICATE-----
 1 s:/C=US/O=Let's Encrypt/CN=R3
   i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----
 2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=dpgeorge.net
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4514 bytes and written 434 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: DD045EDAAF7B29104259EE8B6B3203EFA8860A4EA69127FC8752A59CA8F20147
    Session-ID-ctx:
    Master-Key: EC8F93A4BC345A8695D194DDBF066BC66B1A32A844DA775390B8F774B923A3F3AF65C53A2A17DE957BAD4F9CDCDA0614
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1657655555
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

Now http_ssl_auth_test.py works.

try:
    import usocket as _socket
except:
    import _socket
try:
    import ussl as ssl
except:
    import ssl


ca_cert_chain = b"""-----BEGIN CERTIFICATE-----
MIIFHzCCBAegAwIBAgISBDNT3d/NtE1ppCrdRpyVve9rMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMjA1MjYwNzQ1MTJaFw0yMjA4MjQwNzQ1MTFaMBcxFTATBgNVBAMT
DGRwZ2VvcmdlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALt3
Kx60TijbUvhOSCgCY4BDwYcmTTKoBm9bpXrhaYoCJEX05lCXghnEuWvudjvRsfuK
paKo1i03lzCcdOoAorcqlwTVO09XKdEAtNi7bBpbr8ajqB7ptRm9aGLWi2p0lTGp
+uyNY6LUjNgCf/VJvFddPOS8q0TNhakdgG8BR31PDAxuWy3wA2YTv8Ppj089elEY
UmPhFIm1YSnMH3Owjtukwv0r3pe03AJ760Lgm4hHZO2S0H/qH0gyoWkHbq+e7Ba8
4gtursn7M6E2vWBNgFsV1fZTyIRmyWBRgIVSIxGU4ultzmfJQI/hRgD8cnOnZrrC
Ns3+1bwFMXSiuKIhBU0CAwEAAaOCAkgwggJEMA4GA1UdDwEB/wQEAwIFoDAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
FgQUHlWp/zVL6yP4hjPIT5MgkdnuU6wwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA
5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMu
by5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8w
FwYDVR0RBBAwDoIMZHBnZW9yZ2UubmV0MEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcG
CysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5
cHQub3JnMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHcAKXm+8J45OSHwVnOfY6V3
5b5XfZxgCvj5TV0mXCVdx4QAAAGA/4qQPwAABAMASDBGAiEAlvSRyAAttg6WPIdn
hKh8ErL9qJBDq3OtcHntRxMCTAsCIQDhofbSXGUEyIe9pdavm+lMQUn3Pm5NjApj
sZC0klwBpgB2AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABgP+K
kb0AAAQDAEcwRQIhAK29v0DD0yJ+m9pTfmRl+7f81NBJhAoEOUIwP7reiCxFAiBU
+JL/eDTynJYoP4ApO0Fkld6K7NpssZQf8ORlwVs/STANBgkqhkiG9w0BAQsFAAOC
AQEAVBMxcjf0FdQrsLetAZBkWi6ONVQYzTA1YSOzP1WMuenmd6uQY+j50iJv7RPX
KW4tmI0qjIWU32xlFxZLrZyWiplUXt4Vq19YvEygWk9pzjR4QBr/lmsk5YPKfY9u
z7faFDn/r4UrUdgGtaqO4HpVoXSQ9TGs9hYwdXyJPfIvsX431g8K+Fw/Kd9g3vlQ
IVFcjsVN9dafdz3e5VvKCXrZOqct5WbhcYqkfm4ehl7/PA16D0Y8b/8uWzemWxut
T1laVGkPtQuPqd1ZdralR1Jsjk6CgxhGuEH60u4xY7QwyRcS83951z/6jJPIE5Ss
H3+JgRraIhzr2urkEQaedBPK/g==
-----END CERTIFICATE-----
 1 s:/C=US/O=Let's Encrypt/CN=R3
   i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----
 2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
-----END CERTIFICATE-----"""

def main(use_stream=True):
    s = _socket.socket()
    ai = _socket.getaddrinfo('micropython.org', 443)
    print('Address infos:', ai)
    addr = ai[0][-1]
    print('Connect address:', addr)
    s.connect(addr)
    s = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_cert_chain)
    print(s)
    s.close()
    return True
main()
>>> import http_ssl_auth_test
Address infos: [(2, 1, 0, 'micropython.org', ('176.58.119.26', 443))]
Connect address: ('176.58.119.26', 443)
<_SSLSocket 3ffc6540>

I guess both tests work now. Although not sure how to integrate these tests in multitest suite or where exactly put them.

Also for http_ssl_auth.py I guess the cert-chain should be updated before expiration date? 🤔

TLDR

So my doubts are which test to add to the test suite:

Self-signed key, cert tests:

  • ssl_ecc_auth.py
  • ssl_rsa_auth.py
    (This needs two esp32 to run as server/client)

Verify example web server (micropython.org):

  • http_ssl_auth.py
    Only one device is needed but cert-chain should (probably) be updated from time to time.

How do I add these to the test suite?

@Carglglz
Copy link
Contributor Author

Yes I think that would be good. Is that the same default that CPython has?

I think so

New in version 3.4.

ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_TLS, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None)

Although this is deprecated since 3.7 by
ssl.create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)
But in CPython is easier to set security by default since it falls back to system’s default CA certificates.

For esp-idf there is https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html
that may be worth looking into...

So I guess MBEDTLS_SSL_VERIFY_NONE as default is OK for now.

@dpgeorge
Copy link
Member

How do I add these to the test suite?

I think it would be good to add them all. The multitests in tests/multi_net/ssl_cert_ecc.py and tests/multi_net/ssl_cert_rsa.py. And then the other one in tests/net_inet/ssl_cert.py (feel free to adjust the test names).

@Carglglz Carglglz force-pushed the ssl-add-args branch 6 times, most recently from dc15983 to c620881 Compare July 14, 2022 15:06
@Carglglz
Copy link
Contributor Author

It looks like tests/multi_net/ssl_cert_ecc.py and tests/multi_net/ssl_cert_rsa.py are failing in some unix ports, has it anything to do with the fact that unix port uses axtls instead of mbedtls ?

Other than that I see no reason why these tests would fail 🤔. The only difference with tests/multi_net/ssl_data.py apart from the key/cert is this line:

 # Server
 def instance0():
@@ -60,7 +58,7 @@ def instance1():
     multitest.next()
     s = socket.socket()
     s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
-    s = ssl.wrap_socket(s)
+    s = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs=cert)
     s.write(b"client to server")
     print(s.read(16))
     s.close()

Anyway, let me know if I should fix it and how and I will work on it 👍🏼

And related to the docs let me know if I should explain the new features in more detail.

Apart from that I think this PR is good to go.

@Carglglz Carglglz force-pushed the ssl-add-args branch 3 times, most recently from a202206 to d1d4462 Compare July 15, 2022 23:53
@dpgeorge
Copy link
Member

I realised that this PR is not CPython compatible, because in CPython the ca_certs argument takes a filename.

I think we should implement SSLContext first (see #8915) and then this PR can be added as SSLContext.load_verify_locations().

@Carglglz
Copy link
Contributor Author

Carglglz commented Jul 18, 2022

I realised that this PR is not CPython compatible, because in CPython the ca_certs argument takes a filename.

True, but there is also some keyword args missing and some have different names 🤔

I agree, we should implement SSLContext and make ussl CPython compatible, since one of the best features is to be able to write code that runs both in CPython and in MicroPython, which is nice for tests too.

However, I think it makes more sense to merge this PR first (probably #8916 should go first so tests/multi_net can pass properly) as the last "not CPython compatible" and then implement SSLContext.

Probably it would be better to implement it in MicroPython and extend functionality in C.

For reference I've been reviewing Python TLS/SSL docs, Python ssl.py
and CPython _ssl.c

and I think this is what could be implemented now in MicroPython:

  • PROTOCOL_TLS_CLIENT / PROTOCOL_TLS_SERVER
  • SSLContext.load_cert_chain
  • SSLContext.load_verify_locations
  • SSLContext.wrap_socket
  • SSLContext.protocol
  • SSLContext.verify_mode

Then enhancements in C could be:

  • SSLContext.check_hostname (already implemented)

MBEDTLS_SSL_SERVER_NAME_INDICATION in mbedtls_config.h maybe?

(optional)

  • SSLContext.get_ciphers()
  • SSLContext.set_ciphers(ciphers)

mbedtls ciphersuites

Finally there is also create_default_context and _create_unverified_context which is probably the closest to current MicroPython ssl.wrap_socket.

@dpgeorge
Copy link
Member

However, I think it makes more sense to merge this PR first (probably #8916 should go first so tests/multi_net can pass properly) as the last "not CPython compatible" and then implement SSLContext.

Yes I'd be happy to do that.

and I think this is what could be implemented now in MicroPython:

Please add that info to #8915 and we can discuss it there.

For this PR: I'd suggest renaming the ca_certs keyword arg to something else that doesn't clash with the CPython name, because it takes a different value. Maybe call it cadata to match the argument of SSLContext.load_verify_locations().

Also we need to get the tests working on this PR, after #8916 is merged.

@dpgeorge
Copy link
Member

#8916 (switch unix to mbedtls) is now merged.

@Carglglz Carglglz force-pushed the ssl-add-args branch 5 times, most recently from 26fab75 to b90e94c Compare July 18, 2022 22:06
@Carglglz
Copy link
Contributor Author

Also we need to get the tests working on this PR, after #8916 is merged.

Well, now seems all tests are passing (I had to leave out ssl_cert_ecc.py and switch key, cert to .der format to match unix mbedtls configuration)

For this PR: I'd suggest renaming the ca_certs keyword arg to something else that doesn't clash with the CPython name, because it takes a different value. Maybe call it cadata to match the argument of SSLContext.load_verify_locations()

Done in b90e94c

Please add that info to #8915 and we can discuss it there.

Sure!

#8916 (switch unix to mbedtls) is now merged.

Then this PR is ready to be merged, so we can focus on SSLContext implementation 👍🏼 .

addr = ai[0][-1]
print("Connect address:", addr)
s.connect(addr)
s = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_cert_chain)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn't verify micropython.org. You need to specify server_hostname to do that.

Also, in the set of certs above, you don't need the micropython.org cert. (And we wouldn't want to include micropython.org's cert in a test anyway because it expires every 3 months).

Furthermore, with the default mbedtls behavior, you don't actually need the root cert either. This is a minor CPython inconsistency -- you'd need to add ssl.VERIFY_X509_PARTIAL_CHAIN to SSLContext::verify_flags to get this behavior, otherwise by default in CPython, you need both the intermediate and the root.

Copy link
Contributor Author

@Carglglz Carglglz Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn't verify micropython.org. You need to specify server_hostname to do that.

(I just wanted to test cert validation with a web server other than my own self-signed certs.)

True, for that we need to implement SSLContext.check_hostname.

My bad, it looks like server_hostname is actually implemented but not documented 🙄.

This only validates that the certificate presented by the server matches the certificate chain in ca_certs,

(Also I see now that I forgot to update the kwarg to cadata, and I see this is not run by the test suite in CI, so probably I should leave this out too or move it to examples/network)

Also, in the set of certs above, you don't need the micropython.org cert. (And we wouldn't want to include micropython.org's cert in a test anyway because it expires every 3 months).

Yes that was my concern 👀 (see my TLDR above)

Furthermore, with the default mbedtls behavior, you don't actually need the root cert either. This is a minor CPython inconsistency -- you'd need to add ssl.VERIFY_X509_PARTIAL_CHAIN to SSLContext::verify_flags to get this behavior, otherwise by default in CPython, you need both the intermediate and the root.

Then probably ssl_cert.py fits better as an example after SSLContext implementation. 👍🏼

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, for that we need to implement SSLContext.check_hostname.

wrap_socket already supports the server_hostname kwarg (although it isn't documented...).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to put this test back. It's not run as part of CI but it is useful to run on bare-metal to make sure things work (and also of course run on the unix port, so it needs to pass on that as well).

)
cert = b"0\x82\x05\xd70\x82\x03\xbf\xa0\x03\x02\x01\x02\x02\t\x00\xbcc\xb4\x8ap\x0c=I0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000\x81\x811\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x0c0\n\x06\x03U\x04\x08\x0c\x03Foo1\x0c0\n\x06\x03U\x04\x07\x0c\x03Bar1\x140\x12\x06\x03U\x04\n\x0c\x0bMicroPython1\x0c0\n\x06\x03U\x04\x0b\x0c\x03foo1\x160\x14\x06\x03U\x04\x03\x0c\resphome.local1\x1a0\x18\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x0bfoo@bar.com0\x1e\x17\r220712180013Z\x17\r230712180013Z0\x81\x811\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x0c0\n\x06\x03U\x04\x08\x0c\x03Foo1\x0c0\n\x06\x03U\x04\x07\x0c\x03Bar1\x140\x12\x06\x03U\x04\n\x0c\x0bMicroPython1\x0c0\n\x06\x03U\x04\x0b\x0c\x03foo1\x160\x14\x06\x03U\x04\x03\x0c\resphome.local1\x1a0\x18\x06\t*\x86H\x86\xf7\r\x01\t\x01\x16\x0bfoo@bar.com0\x82\x02\"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\xce<\x0fs\n\xb3D2\xce`Z\xb4MJ\xc0\xaa\xfd\x8abC\x13>\xab\r\xcc\x9dDJ\xb7\xd9\xfff\xa6\x81Z\x10\x1d-<\xbdr\x14\n\xfc4\xf8\xc3\xca\xed\xce\x16\xe9R\x83P\xf3\xe0\xe5cC\xf2HP}\x82\xe4\x1bQ\xab\xb5\x15\xcb\xf6\x0eZa\x9f-\xbc\xa8hM\x17L;\tQ\xe2\xc7\xbaWl\x7f\xb0dS\xa3YwU\x81\njLE\xeb\t%\xc8U\xabSw\x85\xdfF\xbf)\x14Xq3\x0f\xf0d\x1a\x10\x1a$\xf0\x83\x0c \xba\xe8e\xba\x8b\xb3&\x06\xca\xacEU\x81*\xcf\x19\xf5\x95S4\x9c\xe7\x0f\xb7\xffcQ/\x04D\xf8\xf4\x1b\x971\x83\xea\xbf\x96y\x900\x87\xc6\xcdi\xdc:\xdc\xbeuM\xd0 ~\xa5|P\xe9-\x80\x0b\xcebX\xd1a\x8b\xb7I\xd3\xfc\x01#\x9bm\x1a\xf6\xd3\xf9\xca\xda:\xcb\xb3\x12\xa1\xd8ZY\xcf\xab\xd2\x8b.W,V\xa4\x81\x8c\xe1p\xca+x\x1a\x04t\x9cb9 ld\xad\x9e\x05t\x84\x14:LR\xbd\xefa\x89\xc4d\x05\xc1\xa9d$\x89\xcbd\n\x93z\xdf\xc2hux\xdf\xa2\xb4\x0e\xba\xfa\x05!6B\xa1\xcc\xbc&UW\xcd@\xdeS2L\xff\x1b\xfb\xa6\xf5\xc2\x15\xf6W\xb8\xf9\xf2&\n\xb6)6%\xd0\xe2\x03\xbb\xa9u\xbcz\xc6\xdf\xf3\xe6\x04\xc9\xb0\xd2\xa2\xa4\xbaYA\xc0\xdc\x8d.\x0e\x949\xc5dG\xb4\x04\x8c\x0el\xfb\x03QwB\xffo|!@\xa0YT\xaa\x1e)$}\x1a\xe8\xbf\xd7\xdb\r\xb8\xddE\xd0\x95q\x0f\xb7\x82\x84\xed\xe2\x85\x0f\xc0\xc2\x125@j\xf8>`D\xad\xdf\x93\x851d\x03\xe2\xa2TB\xb9\xff\xbf\xc7\xb0\x1cl\x92\x92\xe5\xa3S\x1ejHIl\x01m\xe1734\xa5/\x01\xb7\xc6\xa0\xec\xe1&\x196x\x8d!a\xc5:\x89\x85\xa0\x94mm1\x92%\xb20\xd9m\x05^\xa4i/\xebq\xfd\xafKwZ\xc9\xfb\xc3\x8e\x1b\x94>f\x17\xcfa\xd3>\x93\n\xb2\x88\xa3\xeaG0\xb4\xf2xJ\x80\x18\xe0\xdf\xc8\xa1\x1es\x02\x03\x01\x00\x01\xa3P0N0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14\xbc`H\xfe<\xd2x%~\x8b|\x90\xde\xdb\xbc\xe86\x9b \xb80\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xbc`H\xfe<\xd2x%~\x8b|\x90\xde\xdb\xbc\xe86\x9b \xb80\x0c\x06\x03U\x1d\x13\x04\x050\x03\x01\x01\xff0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x02\x01\x00\t#\x83T\xb43y\xa3\xd2\xb5n\x92\x8c\xac\x8e\xa2\x8e,\x01\xcf\x81H\xe5L\x0b\xbd@U\xe2\xe5}W\x86\x97\xd1\xe2\xc3\x92\xf1\xfe;\xc9!\x1dO'\xed\x1b\xe61\xe7Tzc\x90\xd7\xf1!\xa9\xe2\n\x19_\xdd\xa7?uQ\x88\xb1l\xf3\x97\x14\x92J\x96\x86\xdd|\xc7IB\x135\x03\x8c\x06@\xc2\xc6\xb1]\xf4Mt\xd9J\x97(^\xe2\xa7\xb0u\xcc\xc9\xd9\xd62\xe2\xa5\x90`0\xcfY\xbd\xe1J\xb1\x06`\xb7\xcfG\xec\x9dz\xe2\xf3YcEOvsZ=\xac\x12\xa4\xa4\xc9\x07\x18>\x9c\xcf>\x07\xd5\x94\x84\xc1\x82\xe6~\xdc|5\xce\x15\xc7\xe1\x07/\xae\x8c\x99e\xa1&\x1a\x1f1\x14}J\xf8\xd1\xeb\xf8\xee|\x14+\xad\xfeg\xe3\x1f\xb3$\xa7\x9a)\xbc\x94\xe8\x93p\xb7\r\x8c\xf7\xcd+*\xa4'\xa4\x9fw\x84\x98\x91\xe7\xc4\xd5\x91\x1fo\xdaRs:<\x16\x9b\x01\x88\xc2\xd9\x91\x8f)m\xd8\xe24\xf8\x96/\r\xb5\xe4|aYD\x80EN-\x9aXP\xd4\xc6\x96\xa0\xfb;fSJE\x91\xc4\x9d\xda\x8c\xc6\xf1\xb0\x00\x8cbZ\xa5\xe0\t\x1e\xcf\xbdQ\xd9q\\`\xb8^N\x89\xd4\xa6\xcf\xab\xb2\xac\xdf\x81Q\x8e\xb6\x14\x03\xb8\xf8v|\\\x00!os\x0e\x08\xf2)Y\xdf\xf6\x95\xa0\x81\xccrlJ\xb3Z\xe3\xf6S\x8a#\x1f\x83\x1an\x91 o;i\x1a\x94\xbd\xf9SC\xec\x02\xefz\xacB\xda*p\x84l\xd5\xf1=\xd2\x95Z_\x177\xa4\xc3\xc6\xc0;\x04\x1d3L\x1d\xad\xd1\xe3\x05\xf0|\x83\xb4\xb4\xe0P\x9e\xc1\xd2>\x95\xf8 )\tB\xea\xaf\x8b\xea0L\xd5\xa5\x05\x8f\xc0\xd4bO\xf1\xff\xe14\x8e{\xc5Luj\x12\xac\xb2X\xeb^t&\xfb\x06*\x82\xb8\x8e\xc2t\xc9\xc1;>\xff\x8b\x01\tGb\xe1f\xf4\x90\xcd%\xb1Nv-\xb7\x08xXY\xa37\xd8\xfd\x00\x08\xfe`*\x90\xe2\x93<\xde\xd35\x9e\x98\xce?\xbc\x04\x12\x08f\xbdM\x96\xd6\xb6\xf7\xf5=\xef\x85M@\x02\x11\x96\xb7\xa0k"

key = b"0\x82\t)\x02\x01\x00\x02\x82\x02\x01\x00\xce<\x0fs\n\xb3D2\xce`Z\xb4MJ\xc0\xaa\xfd\x8abC\x13>\xab\r\xcc\x9dDJ\xb7\xd9\xfff\xa6\x81Z\x10\x1d-<\xbdr\x14\n\xfc4\xf8\xc3\xca\xed\xce\x16\xe9R\x83P\xf3\xe0\xe5cC\xf2HP}\x82\xe4\x1bQ\xab\xb5\x15\xcb\xf6\x0eZa\x9f-\xbc\xa8hM\x17L;\tQ\xe2\xc7\xbaWl\x7f\xb0dS\xa3YwU\x81\njLE\xeb\t%\xc8U\xabSw\x85\xdfF\xbf)\x14Xq3\x0f\xf0d\x1a\x10\x1a$\xf0\x83\x0c \xba\xe8e\xba\x8b\xb3&\x06\xca\xacEU\x81*\xcf\x19\xf5\x95S4\x9c\xe7\x0f\xb7\xffcQ/\x04D\xf8\xf4\x1b\x971\x83\xea\xbf\x96y\x900\x87\xc6\xcdi\xdc:\xdc\xbeuM\xd0 ~\xa5|P\xe9-\x80\x0b\xcebX\xd1a\x8b\xb7I\xd3\xfc\x01#\x9bm\x1a\xf6\xd3\xf9\xca\xda:\xcb\xb3\x12\xa1\xd8ZY\xcf\xab\xd2\x8b.W,V\xa4\x81\x8c\xe1p\xca+x\x1a\x04t\x9cb9 ld\xad\x9e\x05t\x84\x14:LR\xbd\xefa\x89\xc4d\x05\xc1\xa9d$\x89\xcbd\n\x93z\xdf\xc2hux\xdf\xa2\xb4\x0e\xba\xfa\x05!6B\xa1\xcc\xbc&UW\xcd@\xdeS2L\xff\x1b\xfb\xa6\xf5\xc2\x15\xf6W\xb8\xf9\xf2&\n\xb6)6%\xd0\xe2\x03\xbb\xa9u\xbcz\xc6\xdf\xf3\xe6\x04\xc9\xb0\xd2\xa2\xa4\xbaYA\xc0\xdc\x8d.\x0e\x949\xc5dG\xb4\x04\x8c\x0el\xfb\x03QwB\xffo|!@\xa0YT\xaa\x1e)$}\x1a\xe8\xbf\xd7\xdb\r\xb8\xddE\xd0\x95q\x0f\xb7\x82\x84\xed\xe2\x85\x0f\xc0\xc2\x125@j\xf8>`D\xad\xdf\x93\x851d\x03\xe2\xa2TB\xb9\xff\xbf\xc7\xb0\x1cl\x92\x92\xe5\xa3S\x1ejHIl\x01m\xe1734\xa5/\x01\xb7\xc6\xa0\xec\xe1&\x196x\x8d!a\xc5:\x89\x85\xa0\x94mm1\x92%\xb20\xd9m\x05^\xa4i/\xebq\xfd\xafKwZ\xc9\xfb\xc3\x8e\x1b\x94>f\x17\xcfa\xd3>\x93\n\xb2\x88\xa3\xeaG0\xb4\xf2xJ\x80\x18\xe0\xdf\xc8\xa1\x1es\x02\x03\x01\x00\x01\x02\x82\x02\x01\x00\x8e\xfa\x0e\x8f\xe8\x1c.,\xb6\xed\x10\x15-\xfc\xa4$'PX\x1d>kT\xf5e$\xa6\xa2\xd2a<\xf2r~\xfc\xecl\xfd\xde\xbdL(_\x11H\xbc*)6\xc2\x89\x19\xcb\r\xa5\x02\xde\xa8\xc9/\xe2\xf9\x85k\xeea\xac\x1a\xeb\xda\xc88\xb5\xe6o||y\x9d\xf0w\x16\xf3\x0e\xf3b\xdb\xb5HX\x84\xa1\x80\xc8\xceU9\xcb\x1d\xb3V\x99\xdc\xe5\xf2\x17')]\x81\x1f\x1c\xe7\xa1\x15\x11\x1c\x18#\xb5\xc9\x0c\xe8\x80\xf55(r\xa7\xa7b\x82\xf6\xf1\xfd\x8a\x01Q6\xab'L=0x=\xebj\xd7\tn3\xd8&\xea\xfd\xf7\xc7\x03\x98\xd5\xea\xb4\xd2\x8f\x91\xcd9\x13\xc6\x9czz\xde\x9e\xf6\x92\xb9\xf8))Y\xbed\xde\xc4j\xb2\xc2\x91\xb4\x1add\x00K]\xddK\x93\xbf\xe4\x1b7\xee\xde\xefK\xa2\xd1m\xcb\xb9\xc2\x8b\x96\xf5\x7f\xb9l \xedJ\x94q\xff\xaed;%O\x10\x0f\x8c\x97\x02\xb5\xf6z\xf66\x9e\x8d\x88\x7f(^]R\x0cZ\xa5\xd3\xa7\x9e]\xe9d2\xe6\xd2\xe3\xde\xa6\x8eX \x8c\x07_\xb1\x19\xc6\xd3\xd4\x14\x9b~\x12G \x8dk3|p'+\xef\xc4\x1dW\xf2xa\x8f\x1a\x82\xde3qs4m\xc15M\x80\xa7\xc9\x07Z\xf9\x9d\xbb*\x14s<\x06\xb7\x16\x00\xc6gzk\xb2\x8c\x0eO\xc6=\xb6\"\"\x80G\xa2\xcbtt\xdc\x81A\xc3_:Y|>+\xca\x99\x11\xd2\x8e\xb9\xfd\x1a\x0c\x91^\x9f\x9c\x1c\xfdd=O\xd8\xca\xc8g\xf2\x158\x01h\xec7\xb8\xcf\xa2\x85d\xe6(\x8a\xb0J}g\xcaD\xb4\xc87R\x14\xa7\xff\xaa\x1ek\xe9,K\x13\x8f\xcf\xd6\xbe\xab\xa2Q\xb3\x1aP\xa6\xe2\xef$\x1c\x95T\xa1\xdcq\x0bJ\xcbc\xe7I\xf5\x84\x9eS\xd3\xf4\x91\\n\xb2\xa9\xa0\t\xba\xb0N\x93(A\xab4\xae)\xeb\x00\n\x08w}c\x99\x16\x9c-\xc3\xd7\x95-\xf5\xbc-\x06\xe9\n2\x13\x9cj'\x93\xd3\x81~O\xea\xda\xc2\xcc\xacUM8:\x8dAV\x91@\xc2\x91h\x89\"\r:^A\x02\x82\x01\x01\x00\xfd`=\x18\xfe\xefz\xaca\xbd\xa3\xb6t\xa5z\xb3\x87H\xbc\xde\\>\xfd\xba\"yc\x8f\x8e\xa4\x13\xcc&\xb9\xdd\xa07\\\x11j\x87\x98\xa2\x95\xb2\xc2\x83\xaa\xaa\xd7\xcc\xa0\xdb\xd9\xbb3\"\xa9\xa8\x15\xf6\xd0\xaa_\xc4\xf9\xaf\xf8\xfb\xda\x8f\xf9\x14\t\x1e\xdez\xef\xdb\x07\xa1\x19\xc9\xb2\xe2\xb2\xbd\xa7v\xacIp`\xb8\xe8\x8a\x82\xeb \xc6/&\xf3CVf\x97rnq\xaaF\xfdN\xfa\xd6\xf4/\xc8\xa4x\x85c$\xd7,\xbf^\xb3\x91\x83\x17\x16-o\xc2\xcf\xd7u\x96\x9a wu\x9f\xa2\xc8\"\r\xac\xdc.\xbb\x03\xec9\xfe\xed?+ATI\xcb\xf4\nq&\xbc\xf0\x1d\x10h\xe3\xa4^\xc0\x11\x81\xf2\xc6\x8d~\x05\xb4r\x0b\xfeJ0\x8e\x16H\x12<\x91!J_\x8d\xfc\xe5\x87'\xc4\xcd\x93\x96\xa8\xb4\x03\xb73\xa7\x17D\x9b/\x19p\xdb\x97\xa3\xb8Frq\xff\xa6\xe8\xc7\xcc\x9e.\x1c\x0fx\x92\x84\xae\x9e\xfew\xea\xac\x01\x13\x14c\xc9\xc12\x9a\x1b\xa3S\x02\x82\x01\x01\x00\xd0^\xd6\xab\x9b\x9f\xbd\xf7\xa0\xf5\xf9\x1fh\xdc;\xacW\x893-n\xceF\x10?\xb1\xef\x10\x9f\xc9r\xfd\xc9\x9e\xdf1\x07\xa2=f\xd1\xcd\xfek\xdd\xdf\xd1\xbb9R\xcc\xd1\x0b\\ \xad\x1b>\n\xa6\xa5\x12q\xec\xf3\xa7\xef*e\xe0)\xf5\xd7\x7f#\x8d\x125\xb5*\x9d\xca4Q\xc1e\xd7\n\x99\xcb\xae\xa5\xc6\x10\xe5EYyim\xb7i\x19\x1e|\xf2\xdb!\xf6A\x95\x9eK\xa1\xc5\xc0\xaa\xe2`\xc7$\x96+j\xc2b\x1d\x92\xe9\xdfz\xde\xb8+R-7\xb4,\xb4T\x00;\xbe`\xd9\x91[\xf7sz\xec\xcf\x88\xc7\xed\x12c\xa2/C\x1asNa\xfeqs\xa97\xdd\xf7j\xd2\xa7\x99\x94\xc0R8\xde\xfc\x15\xf6\x84hX\xe9\xed\xf2z\xe2\xa5g\xc7\xc5\xc75\xea]/\xbe\xf6Z!\x95\xbc\x05\xd8,\xbf\x06\xa4w\xb2\x9c\x84\xc9.\x80T\xc2\xbb%\xd8\xc6\xf1\x9dC\xef_\xd1\xfc\xe1<,\xdb\xc3a\xc3\x9b\xae\xc3{9\x92\x00\xb3-Jg\x98\xba\x0bTa\x02\x82\x01\x01\x00\x8eAI,N}\xaf\xf76\x8d\x1dld\x03@g\xa9M\xcaTa\xa00\x1e \x1a\xdd.\r\\\xcb\x8c\xb45h[\xfa\x98\xe3bW,\xf8#j\x10\xd1\x91\xb1\x87\xa5h\xae\xe6\x88\xb6\xc6\x00P\xd1\xbc\x18\x1d\x7f\xd5|\x863\x19[\xf5\xb7Wkc|o\xb3X\xda\xe8\xb5,\xcc\x15\x81Z\xff\xb9\x9e3A7\xdc\xb9\x1a\x834u\xdb/@\x04\x16K] ,l\x1b\xbf\tJP\xdc~p\xec\x9f\x0e\xd0g\xbbiD\xb1\xe7\xe3\xc8\x97\xaa\xec\xfcS\x98J\xdd\x1cO\xf5\xb5%\x03L\xf3\xca\x95\xe8\xa0\x9a\xeb\xa8\x04\xf1\xc7\xe0+\xe3\x91\xb2\xbcd\x11f\xc3\xe6T\xee\xf5\xe7-\xba7\xd9\x8f@o?\xa5 \xe4\x1f.\xa1\x0fUt\xacY\x84\xf7QE7\x8f\xef\xbf\xac\x1d\x07\xff\xf3\xf24\xfe\xc6\x98\xd5^tk\x1d\xa1\x8fo}\xe2N\xc8N\xd7\xcbDmB\x88 \xbe\xf3<\x00i>j\x0e\xf1\x14\xb5\xd6n\x9f\xef\xa8\xee\x05\x928\xdf\x1a\xc3|\x87\xe7\x84\x1a\xe7\x02\x82\x01\x00\x07!\xa7\xd19\xc3N\xda!\xcd)X\x94\xdb,\xc3\xaa?L\xdc\x1a5\xbf\x1a!C\xf2\xbd\xab\xeaV /}[\x80/\x15\xb3jHu\xf7f3\xb2\xccW\xcf\x0fqi\x1a-n\x04\xde\xb0\xd1\xe6\x801\xd0j^\xb0y\xb4\x06\xc6\x94I\x10\xb6\x0e>n\xc8\x1d\xca6\x9aL\x0e\x1cCc\x07\xbe\xd9\xc4\xc1q\xb4\xf4S\xdaK\x18{\xa3\xd2Z\x04\xbc\x1c\x07\xb9\xf2\xd6\xad\xcb<%nB8\xd7\x04\x9e\xec6\xa3\x87\xc4\xdd\\\xcb\xc1k_\xa6-\xc1u\xcf\x8c_\x83D,\xb7\xd1S\xa3\xb6\xee\x8d\xaa;n\x92\x9aK\xc1#\xf1\x04-\xf1\xd6'\x1a\x99-+k0\x9d3\x07J\xc7\x82,0Jr\x06\x9ea\xabY\t\x15\xe1\x08b\x01=\xd2L\xdd\x82^\xc8\xfb\x17rL\xfc,Y\xfc\x1d\xb8%6A\xfe\xce\x0e\xe9$\x1b\x9d\xd5\xc1\x98\xf0\xd5u\xd0\xb7\xeb\xe2k4\x89\xb5\xb0\x9e\xdc;\xcd6o\xd3\x11\x0e\x83\xce\x88l8=1\xfe\xef\xe6\xe3\x02\xcc#E!\x02\x82\x01\x00\x08\xf7z3\xd0\x08\x1e\x9b\xe3\xc1\xb1\xac\x8b\x8e\x0e\xeb\xb7-\xf2\xebi\xb9].\xd7I5\xb9\xda\xb8\xe1p#\xcc8FST\x02<Q\x83\xb5\x1aj (\x8f\xbb!\x81\x17+\xe1\xc2\xfd\xb8\xb4DA\x94T\xe5\xb3\x7f\x7f;\xdf\x11\xe2\x8c\xf4tk%SN\xb6/~\x87\xbb\xbf(\xed\xa3p$6\x8b8\x97\xfb\xc6a\xb4\n\x93\xe0J\x18=\xb9!\x9c\x04\xa8vC\xed\xf5\xd8\xb5\xdb\xfe=BN\x91\xd5X\xd5\xe3\xe2\xfa\x02\xce\x19\x84\xeei\xfb\x85\x18G\x0e\xee.}\xb0\xe1\xdfZ\xc4W\x1fx\xa7\xa2R\x9b\xc1\xfe\xf5\xe3-F\x99Hi\xa8\xd8\xccG\x86\x9e\x17M\x84\xe7\x97k\xe8\xeb\xb8\x8f,\xcbq\xa6\x03\xa8\xbd\xb0j\xf3\xeb-\xdb\xd6 \x82\xf4\ry\x87\xe4\x7f.2\x1e\xb5\xeb*(\xfe\xfa\xb2c@\x9f\x89\xdc\x97\xeb\xc7#\xa1\xb7QA\x8c\xdd>\xa6\x84\xba\x8b\x17\xa30\xa3\x06\xa6\xfb\xcfQ\xba\x83V:\xed\x85\xa4\xf8\x86\xff\xf1\xa2$#t\x8d\x83y\x8c"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you need to change these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test suite fails otherwise

I had to leave out ssl_cert_ecc.py and switch key, cert to .der format to match unix mbedtls configuration

unix port needs changes to allow EC keys/certs and PEM format parsing see my diff comment in #8916
(This is enabled by default in esp-idf)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are in DER format already (right?). And this test does currently pass on unix-to-unix, so I don't understand why it needs to change.

Test suite fails otherwise

Can you explain exactly what fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry I misunderstood, I was having problems with ssl_data.py old RSA key/cert on my local test suite, mbedtls raising RSA_BAD_FORMAT or something like that (I don't remember exactly the message) and decided to change it to see if it worked. But now testing again original RSA keys works. Not sure what exactly happened.
I'm sorry 😞 , reverting changes now...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a problem. I was also seeing RSA errors on unix with mbedtls and needed to disable MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED to get it working. So that's why it's now working for you with the original RSA keys.

We can get to the bottom of that at some later date.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also seeing RSA errors on unix with mbedtls and needed to disable MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED to get it working

I guess that was it

We can get to the bottom of that at some later date.

Yes, I'm curious too 👀

@Carglglz Carglglz force-pushed the ssl-add-args branch 2 times, most recently from 357980f to 6b93551 Compare July 19, 2022 05:31
size_t cacert_len;
const byte *cacert = (const byte *)mp_obj_str_get_data(args->cadata.u_obj, &cacert_len);
// len should include terminating null
ret = mbedtls_x509_crt_parse(&o->cacert, cacert, cacert_len + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently only DER format is supported. And in such a case I think this function only parses the first DER in the buffer and will ignore anything after that.

To support a chain of DERs we would need to have a custom DER parser, or at least one that could tell the length of a DER so it could call mbedtls_x509_crt_parse_der() multiple times, once for each DER in the chain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I've just checked out mbedtls_x509_crt_parse() documentation:

Parse one DER-encoded or one or more concatenated PEM-encoded certificates and add them to the chained list.
....
The buffer holding the certificate data in PEM or DER format. For certificates in PEM encoding, this may be a concatenation of multiple certificates; for DER encoding, the buffer must comprise exactly one certificate.

And mbedtls_x509_crt_parse_der():

Parse a single DER formatted certificate and add it to the end of the provided chained list.

Which seems like a concatenated DER-encoded certificates file does not exist.

custom DER parser, or at least one that could tell the length of a DER so it could call mbedtls_x509_crt_parse_der() multiple times, once for each DER in the chain

I guess you could parse multiple files/buffers calling mbedtls_x509_crt_parse_der() multiple times, but from a single file I don't think is possible, you would need to add a header with the sizes or some delimiters like PEM.

Probably is better to support PEM-encoding or make it multiple files/list of buffers than a single "chain DER file".
In any case I think this fits better in SSLContext.load_verify_locations, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's solve this problem later on, as part of SSLContext. For now what is done in this PR is a good start, and a subset of what we could eventually support (either PEM or list/tuple/concat'd DER).

Add cert_reqs and ca_certs kwargs to ssl.wrap_socket and
ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED options
to allow certificate validation.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
Rename ca_certs kwarg in ssl.wrap_socket to cadata
to avoid name clash with CPython ca_certs.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
@dpgeorge
Copy link
Member

Rebased, squashed and merged in b41cfea, with some minor tweaks to the docs.

Thank you to all involved!

@dpgeorge dpgeorge closed this Jul 20, 2022
@Carglglz Carglglz deleted the ssl-add-args branch July 20, 2022 14:09
tannewt pushed a commit to tannewt/circuitpython that referenced this pull request Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants