2727#include <stdio.h>
2828#include <string.h>
2929
30+ #include "extmod/vfs.h"
3031#include "py/objtuple.h"
3132#include "py/objlist.h"
3233#include "py/objproperty.h"
@@ -52,6 +53,47 @@ STATIC mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args
5253 return MP_OBJ_FROM_PTR (s );
5354}
5455
56+ //| def load_cert_chain(self, certfile: str, keyfile: str) -> None:
57+ //| """Load a private key and the corresponding certificate.
58+ //|
59+ //| The certfile string must be the path to a single file in PEM format
60+ //| containing the certificate as well as any number of CA certificates
61+ //| needed to establish the certificate's authenticity. The keyfile string
62+ //| must point to a file containing the private key.
63+ //| """
64+
65+ STATIC void get_file_contents (mp_obj_t name_obj , mp_buffer_info_t * bufinfo ) {
66+ mp_obj_t file = mp_call_function_2 (MP_OBJ_FROM_PTR (& mp_builtin_open_obj ), name_obj , MP_OBJ_NEW_QSTR (MP_QSTR_rb ));
67+ mp_obj_t dest [2 ];
68+ mp_load_method (file , MP_QSTR_read , dest );
69+ mp_obj_t result = mp_call_method_n_kw (0 , 0 , dest );
70+ mp_get_buffer_raise (result , bufinfo , MP_BUFFER_READ );
71+ }
72+
73+ STATIC mp_obj_t ssl_sslcontext_load_cert_chain (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
74+ enum { ARG_certfile , ARG_keyfile };
75+ static const mp_arg_t allowed_args [] = {
76+ { MP_QSTR_certfile , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = mp_const_none } },
77+ { MP_QSTR_keyfile , MP_ARG_OBJ , {.u_obj = mp_const_none } },
78+ };
79+ ssl_sslcontext_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
80+
81+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
82+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
83+
84+ mp_buffer_info_t cert_buf , key_buf ;
85+ get_file_contents (args [ARG_certfile ].u_obj , & cert_buf );
86+ if (args [ARG_keyfile ].u_obj != mp_const_none ) {
87+ get_file_contents (args [ARG_keyfile ].u_obj , & key_buf );
88+ } else {
89+ key_buf = cert_buf ;
90+ }
91+
92+ common_hal_ssl_sslcontext_load_cert_chain (self , & cert_buf , & key_buf );
93+ return mp_const_none ;
94+ }
95+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (ssl_sslcontext_load_cert_chain_obj , 1 , ssl_sslcontext_load_cert_chain );
96+
5597//| def load_verify_locations(self, cadata: Optional[str] = None) -> None:
5698//| """Load a set of certification authority (CA) certificates used to validate
5799//| other peers' certificates."""
@@ -146,6 +188,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_wrap_socket_obj, 1, ssl_sslcont
146188
147189STATIC const mp_rom_map_elem_t ssl_sslcontext_locals_dict_table [] = {
148190 { MP_ROM_QSTR (MP_QSTR_wrap_socket ), MP_ROM_PTR (& ssl_sslcontext_wrap_socket_obj ) },
191+ { MP_ROM_QSTR (MP_QSTR_load_cert_chain ), MP_ROM_PTR (& ssl_sslcontext_load_cert_chain_obj ) },
149192 { MP_ROM_QSTR (MP_QSTR_load_verify_locations ), MP_ROM_PTR (& ssl_sslcontext_load_verify_locations_obj ) },
150193 { MP_ROM_QSTR (MP_QSTR_set_default_verify_paths ), MP_ROM_PTR (& ssl_sslcontext_set_default_verify_paths_obj ) },
151194 { MP_ROM_QSTR (MP_QSTR_check_hostname ), MP_ROM_PTR (& ssl_sslcontext_check_hostname_obj ) },
0 commit comments