34#include "gstrmacros.h"
48#if MBEDTLS_VERSION_MAJOR >= 3
49#define GET MBEDTLS_PRIVATE
50#if MBEDTLS_VERSION_MINOR >= 1
51#define GET_RAW(field) field
53#define GET_RAW MBEDTLS_PRIVATE
56#define GET(field) field
57#define GET_RAW(field) field
60#ifndef GCONFIG_HAVE_MBEDTLS_HASH_STATE
61#if MBEDTLS_VERSION_MAJOR >= 3
62#define GCONFIG_HAVE_MBEDTLS_HASH_STATE 0
64#define GCONFIG_HAVE_MBEDTLS_HASH_STATE 1
68GSsl::MbedTls::LibraryImp::LibraryImp(
G::StringArray & library_config , Library::LogFn log_fn ,
bool verbose ) :
70 m_config(library_config)
72 mbedtls_debug_set_threshold( verbose ? 3 : 1 ) ;
75GSsl::MbedTls::LibraryImp::~LibraryImp()
84 const std::string & key_file ,
const std::string & cert_file ,
const std::string & ca_file ,
85 const std::string & default_peer_certificate_name ,
const std::string & default_peer_host_name ,
86 const std::string & profile_config )
88 std::shared_ptr<ProfileImp> profile_ptr =
89 std::make_shared<ProfileImp>(*
this,is_server_profile,key_file,cert_file,ca_file,
90 default_peer_certificate_name,default_peer_host_name,profile_config) ;
91 m_profile_map.insert( Map::value_type(profile_name,profile_ptr) ) ;
96 auto p = m_profile_map.find( profile_name ) ;
97 return p != m_profile_map.end() ;
102 auto p = m_profile_map.find( profile_name ) ;
103 if( p == m_profile_map.end() )
throw Error(
"no such profile: [" + profile_name +
"]" ) ;
104 return *(*p).second ;
107GSsl::Library::LogFn GSsl::MbedTls::LibraryImp::log()
const
112std::string GSsl::MbedTls::LibraryImp::version()
114 std::vector<char> buffer( 100U ) ;
115 G_ASSERT( buffer.size() >= 9U ) ;
116 mbedtls_version_get_string( &buffer[0] ) ;
117 buffer[buffer.size()-1U] =
'\0' ;
121std::string GSsl::MbedTls::LibraryImp::sid()
123 std::vector<char> buffer( 100U ) ;
124 G_ASSERT( buffer.size() >= 18U ) ;
125 mbedtls_version_get_string_full( &buffer[0] ) ;
126 buffer[buffer.size()-1U] =
'\0' ;
140std::string GSsl::MbedTls::LibraryImp::credit(
const std::string & ,
const std::string & ,
const std::string & )
148 return {
"MD5" ,
"SHA1" ,
"SHA256" } ;
153 return Digester( std::make_unique<DigesterImp>(hash_type,state,need_state) ) ;
159 m_noverify(consume(config,
"noverify")),
160 m_clientnoverify(consume(config,
"clientnoverify")),
161 m_servernoverify(consume(config,
"servernoverify")),
166#ifdef MBEDTLS_SSL_MINOR_VERSION_0
167 static constexpr int SSL_v3 = MBEDTLS_SSL_MINOR_VERSION_0 ;
168 static_assert( SSL_v3 >= 0 ,
"" ) ;
169 if( consume(config,
"sslv3") ) m_min = SSL_v3 ;
170 if( consume(config,
"-sslv3") ) m_max = SSL_v3 ;
173#ifdef MBEDTLS_SSL_MINOR_VERSION_1
174 static constexpr int TLS_v1_0 = MBEDTLS_SSL_MINOR_VERSION_1 ;
175 static_assert( TLS_v1_0 >= 0 ,
"" ) ;
176 if( consume(config,
"tlsv1.0") ) m_min = TLS_v1_0 ;
177 if( consume(config,
"-tlsv1.0") ) m_max = TLS_v1_0 ;
180#ifdef MBEDTLS_SSL_MINOR_VERSION_2
181 static constexpr int TLS_v1_1 = MBEDTLS_SSL_MINOR_VERSION_2 ;
182 static_assert( TLS_v1_1 >= 0 ,
"" ) ;
183 if( consume(config,
"tlsv1.1") ) m_min = TLS_v1_1 ;
184 if( consume(config,
"-tlsv1.1") ) m_max = TLS_v1_1 ;
187#ifdef MBEDTLS_SSL_MINOR_VERSION_3
188 static constexpr int TLS_v1_2 = MBEDTLS_SSL_MINOR_VERSION_3 ;
189 static_assert( TLS_v1_2 >= 0 ,
"" ) ;
190 if( consume(config,
"tlsv1.2") ) m_min = TLS_v1_2 ;
191 if( consume(config,
"-tlsv1.2") ) m_max = TLS_v1_2 ;
194#ifdef MBEDTLS_SSL_MINOR_VERSION_4
195 static constexpr int TLS_v1_3 = MBEDTLS_SSL_MINOR_VERSION_4 ;
196 static_assert( TLS_v1_3 >= 0 ,
"" ) ;
197 if( consume(config,
"tlsv1.3") ) m_min = TLS_v1_3 ;
198 if( consume(config,
"-tlsv1.3") ) m_max = TLS_v1_3 ;
202int GSsl::MbedTls::Config::min_() const noexcept
207int GSsl::MbedTls::Config::max_() const noexcept
212bool GSsl::MbedTls::Config::noverify() const noexcept
217bool GSsl::MbedTls::Config::clientnoverify() const noexcept
219 return m_clientnoverify ;
222bool GSsl::MbedTls::Config::servernoverify() const noexcept
224 return m_servernoverify ;
229 return LibraryImp::consume( list , item ) ;
234GSsl::MbedTls::DigesterImp::DigesterImp(
const std::string & hash_name ,
const std::string & state ,
bool need_state )
236 bool have_state = !state.empty() ;
239 #if ! GCONFIG_HAVE_MBEDTLS_HASH_STATE
240 if( have_state || need_state )
242 throw Error( std::string(
"hash state resoration not implemented for ").append(hash_name) ) ;
245 GDEF_IGNORE_PARAM( need_state ) ;
248 if( hash_name ==
"MD5" )
250 m_hash_type = Type::Md5 ;
254 mbedtls_md5_init( &m_md5 ) ;
255 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
256 m_state_size = m_value_size + 4U ;
260 call( FN_RETv3(mbedtls_md5_starts) , &m_md5 ) ;
262 call( FN_RETv3(mbedtls_md5_starts) , &m_md5 ) ;
265 else if( hash_name ==
"SHA1" )
267 m_hash_type = Type::Sha1 ;
271 mbedtls_sha1_init( &m_sha1 ) ;
272 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
273 m_state_size = m_value_size + 4U ;
277 call( FN_RETv3(mbedtls_sha1_starts) , &m_sha1 ) ;
279 call( FN_RETv3(mbedtls_sha1_starts) , &m_sha1 ) ;
282 else if( hash_name ==
"SHA256" )
284 m_hash_type = Type::Sha256 ;
288 mbedtls_sha256_init( &m_sha256 ) ;
289 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
290 m_state_size = m_value_size + 4U ;
294 call( FN_RETv3(mbedtls_sha256_starts) , &m_sha256 , 0 ) ;
296 call( FN_RETv3(mbedtls_sha256_starts) , &m_sha256 , 0 ) ;
301 throw Error(
"invalid hash function" ) ;
305GSsl::MbedTls::DigesterImp::~DigesterImp()
307 if( m_hash_type == Type::Md5 )
308 mbedtls_md5_free( &m_md5 ) ;
309 else if( m_hash_type == Type::Sha1 )
310 mbedtls_sha1_free( &m_sha1 ) ;
311 else if( m_hash_type == Type::Sha256 )
312 mbedtls_sha256_free( &m_sha256 ) ;
317 if( m_hash_type == Type::Md5 )
318 call( FN_RETv3(mbedtls_md5_update) , &m_md5 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
319 else if( m_hash_type == Type::Sha1 )
320 call( FN_RETv3(mbedtls_sha1_update) , &m_sha1 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
321 else if( m_hash_type == Type::Sha256 )
322 call( FN_RETv3(mbedtls_sha256_update) , &m_sha256 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
327 if( m_hash_type == Type::Md5 )
329 std::array<unsigned char,16> buffer {} ;
330 call( FN_RETv3(mbedtls_md5_finish) , &m_md5 , &buffer[0] ) ;
331 return std::string(
reinterpret_cast<const char*
>(&buffer[0]) , buffer.size() ) ;
333 else if( m_hash_type == Type::Sha1 )
335 std::array<unsigned char,20> buffer {} ;
336 call( FN_RETv3(mbedtls_sha1_finish) , &m_sha1 , &buffer[0] ) ;
337 return std::string(
reinterpret_cast<const char*
>(&buffer[0]) , buffer.size() ) ;
339 else if( m_hash_type == Type::Sha256 )
341 std::array<unsigned char,32> buffer {} ;
342 call( FN_RETv3(mbedtls_sha256_finish) , &m_sha256 , &buffer[0] ) ;
343 return std::string(
reinterpret_cast<const char*
>(&buffer[0]) , buffer.size() ) ;
347 return std::string() ;
353 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
354 if( m_hash_type == Type::Md5 )
356 else if( m_hash_type == Type::Sha1 )
358 else if( m_hash_type == Type::Sha256 )
369 return m_block_size ;
374 return m_value_size ;
379 return m_state_size ;
384GSsl::MbedTls::ProfileImp::ProfileImp(
const LibraryImp & library_imp ,
bool is_server_profile ,
385 const std::string & key_file ,
const std::string & cert_file ,
const std::string & ca_path ,
386 const std::string & default_peer_certificate_name ,
const std::string & default_peer_host_name ,
387 const std::string & profile_config ) :
388 m_library_imp(library_imp) ,
389 m_default_peer_certificate_name(default_peer_certificate_name) ,
390 m_default_peer_host_name(default_peer_host_name) ,
394 mbedtls_ssl_config * cleanup_ptr = nullptr ;
395 G::ScopeExit cleanup( [&](){
if(cleanup_ptr) mbedtls_ssl_config_free(cleanup_ptr);} ) ;
398 Config extra_config = library_imp.config() ;
399 if( !profile_config.empty() )
402 extra_config = Config( profile_config_list ) ;
403 if( !profile_config_list.empty() )
404 G_WARNING(
"GSsl::MbedTls::ProfileImp::ctor: tls-config: tls " << (is_server_profile?
"server":
"client")
405 <<
" profile configuration ignored: [" <<
G::Str::join(
",",profile_config_list) <<
"]" ) ;
410 mbedtls_ssl_config_init( &m_config ) ;
411 cleanup_ptr = &m_config ;
412 int rc = mbedtls_ssl_config_defaults( &m_config ,
413 is_server_profile ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT ,
414 MBEDTLS_SSL_TRANSPORT_STREAM ,
415 MBEDTLS_SSL_PRESET_DEFAULT ) ;
416 if( rc )
throw Error(
"mbedtls_ssl_config_defaults" , rc ) ;
420 if( !key_file.empty() )
421 m_pk.load( key_file , library_imp.rng() ) ;
422 if( !cert_file.empty() )
423 m_certificate.load( cert_file ) ;
426 if( m_certificate.loaded() )
428 int rc = mbedtls_ssl_conf_own_cert( &m_config , m_certificate.ptr() , m_pk.ptr() ) ;
430 throw Error(
"mbedtls_ssl_conf_own_cert" , rc ) ;
435 if( ca_path.empty() )
438 m_authmode = MBEDTLS_SSL_VERIFY_OPTIONAL ;
441 if( is_server_profile && extra_config.servernoverify() )
442 m_authmode = MBEDTLS_SSL_VERIFY_NONE ;
443 else if( !is_server_profile && extra_config.clientnoverify() )
444 m_authmode = MBEDTLS_SSL_VERIFY_NONE ;
445 else if( mbedtls_version_get_number() <= 0x02040200 )
446 G_WARNING_ONCE(
"GSsl::MbedTls::LibraryImp::ctor: mbedtls library version " << LibraryImp::version() <<
" is deprecated" ) ;
448 else if( ca_path ==
"<none>" )
451 m_authmode = MBEDTLS_SSL_VERIFY_NONE ;
453 else if( ca_path ==
"<default>" )
456 std::string ca_path_default =
"/etc/ssl/certs/ca-certificates.crt" ;
457 m_ca_list.load( ca_path_default ) ;
458 bool no_verify = extra_config.noverify() ;
459 mbedtls_ssl_conf_ca_chain( &m_config , m_ca_list.ptr() , crl() ) ;
460 m_authmode = no_verify ? MBEDTLS_SSL_VERIFY_OPTIONAL : MBEDTLS_SSL_VERIFY_REQUIRED ;
465 m_ca_list.load( ca_path ) ;
466 bool no_verify = extra_config.noverify() ;
467 mbedtls_ssl_conf_ca_chain( &m_config , m_ca_list.ptr() , crl() ) ;
468 m_authmode = no_verify ? MBEDTLS_SSL_VERIFY_OPTIONAL : MBEDTLS_SSL_VERIFY_REQUIRED ;
470 mbedtls_ssl_conf_authmode( &m_config , m_authmode ) ;
475 if( extra_config.min_() >= 0 )
476 mbedtls_ssl_conf_min_version( &m_config , MBEDTLS_SSL_MAJOR_VERSION_3 , extra_config.min_() ) ;
477 if( extra_config.max_() >= 0 )
478 mbedtls_ssl_conf_max_version( &m_config , MBEDTLS_SSL_MAJOR_VERSION_3 , extra_config.max_() ) ;
483 mbedtls_ssl_conf_rng( &m_config , mbedtls_ctr_drbg_random , m_library_imp.rng().ptr() ) ;
484 mbedtls_ssl_conf_dbg( &m_config , onDebug ,
this ) ;
489 mbedtls_ssl_conf_renegotiation( &m_config , MBEDTLS_SSL_RENEGOTIATION_DISABLED ) ;
494GSsl::MbedTls::ProfileImp::~ProfileImp()
496 mbedtls_ssl_config_free( &m_config ) ;
500 const std::string & peer_host_name )
const
502 return std::make_unique<MbedTls::ProtocolImp>( *
this ,
503 peer_certificate_name.empty()?defaultPeerCertificateName():peer_certificate_name ,
504 peer_host_name.empty()?defaultPeerHostName():peer_host_name ) ;
507mbedtls_x509_crl * GSsl::MbedTls::ProfileImp::crl()
const
513const mbedtls_ssl_config * GSsl::MbedTls::ProfileImp::config()
const
518void GSsl::MbedTls::ProfileImp::onDebug(
void * This ,
int level_in ,
const char * file ,
int line ,
const char * message )
522 static_cast<ProfileImp*
>(This)->doDebug( level_in , file , line , message ) ;
529void GSsl::MbedTls::ProfileImp::doDebug(
int level_in ,
const char * file ,
int line ,
const char * message )
543 int level_out = level_in >= 4 ? 0 : ( level_in >= 2 ? 1 : 3 ) ;
544 if( m_library_imp.log() && level_out )
546 std::ostringstream ss ;
547 G::Path path( file ? std::string(file) : std::string() ) ;
548 ss << path.basename() <<
"(" << line <<
"): " << (message?message:
"") ;
549 logAt( level_out , ss.str() ) ;
553void GSsl::MbedTls::ProfileImp::logAt(
int level_out , std::string s )
const
555 Library::LogFn log_fn = m_library_imp.log() ;
560 (*log_fn)( level_out , s ) ;
564const std::string & GSsl::MbedTls::ProfileImp::defaultPeerCertificateName()
const
566 return m_default_peer_certificate_name ;
569const std::string & GSsl::MbedTls::ProfileImp::defaultPeerHostName()
const
571 return m_default_peer_host_name ;
574int GSsl::MbedTls::ProfileImp::authmode()
const
581GSsl::MbedTls::ProtocolImp::ProtocolImp(
const ProfileImp & profile ,
const std::string & required_peer_certificate_name ,
582 const std::string & target_peer_host_name ) :
585 m_ssl(profile.config()) ,
588 mbedtls_ssl_set_bio( m_ssl.ptr() ,
this , doSend , doRecv ,
nullptr ) ;
595 std::string name = target_peer_host_name.empty() ? required_peer_certificate_name : target_peer_host_name ;
597 mbedtls_ssl_set_hostname( m_ssl.ptr() , name.c_str() ) ;
600GSsl::MbedTls::ProtocolImp::~ProtocolImp()
605 int rc = mbedtls_ssl_read( m_ssl.ptr() ,
reinterpret_cast<unsigned char*
>(buffer) , buffer_size_in ) ;
606 data_size_out = rc < 0 ? 0 : rc ;
607 if( rc == 0 )
return Protocol::Result::error ;
608 std::size_t available = rc > 0 ? mbedtls_ssl_get_bytes_avail( m_ssl.ptr() ) : 0U ;
609 return convert(
"mbedtls_ssl_read" , rc , available > 0U ) ;
613 ssize_t & data_size_out )
615 const unsigned char * p =
reinterpret_cast<const unsigned char *
>(buffer_in) ;
616 ssize_t n =
static_cast<ssize_t
>(data_size_in) ; G_ASSERT( n >= 0 ) ;
619 int rc = mbedtls_ssl_write( m_ssl.ptr() , p , n ) ;
622 data_size_out =
static_cast<ssize_t
>(data_size_in) ;
623 return Protocol::Result::ok ;
632 return convert(
"mbedtls_ssl_write" , rc ) ;
639 int rc = mbedtls_ssl_close_notify( m_ssl.ptr() ) ;
640 return convert(
"mbedtls_ssl_close_notify" , rc ) ;
644int GSsl::MbedTls::ProtocolImp::doRecvTimeout(
void * This ,
unsigned char * p , std::size_t n , uint32_t )
648 return doRecv( This , p , n ) ;
652int GSsl::MbedTls::ProtocolImp::doRecv(
void * This ,
unsigned char * p , std::size_t n )
654 G::ReadWrite * io =
static_cast<ProtocolImp*
>(This)->m_io ;
655 G_ASSERT( io !=
nullptr ) ;
656 ssize_t rc = io->
read(
reinterpret_cast<char*
>(p) , n ) ;
657 if( rc < 0 && io->eWouldBlock() )
return MBEDTLS_ERR_SSL_WANT_READ ;
658 if( rc < 0 )
return MBEDTLS_ERR_NET_RECV_FAILED ;
659 return static_cast<int>(rc) ;
662int GSsl::MbedTls::ProtocolImp::doSend(
void * This ,
const unsigned char * p , std::size_t n )
664 G::ReadWrite * io =
static_cast<ProtocolImp*
>(This)->m_io ;
665 G_ASSERT( io !=
nullptr ) ;
666 ssize_t rc = io->
write(
reinterpret_cast<const char*
>(p) , n ) ;
667 if( rc < 0 && io->eWouldBlock() )
return MBEDTLS_ERR_SSL_WANT_WRITE ;
668 if( rc < 0 )
return MBEDTLS_ERR_NET_SEND_FAILED ;
669 return static_cast<int>(rc) ;
672GSsl::Protocol::Result GSsl::MbedTls::ProtocolImp::convert(
const char * fnname ,
int rc ,
bool more )
675 if( rc == MBEDTLS_ERR_SSL_WANT_READ )
return Protocol::Result::read ;
676 if( rc == MBEDTLS_ERR_SSL_WANT_WRITE )
return Protocol::Result::write ;
677 if( rc == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
return Protocol::Result::error ;
680 throw Error( fnname , rc , verifyResultString(rc) ) ;
682 return more ? Protocol::Result::more : Protocol::Result::ok ;
685std::string GSsl::MbedTls::ProtocolImp::verifyResultString(
int rc )
687 if( rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
689 auto verify_result = mbedtls_ssl_get_verify_result( m_ssl.ptr() ) ;
690 std::vector<char> buffer( 1024U ) ;
691 mbedtls_x509_crt_verify_info( &buffer[0] , buffer.size() ,
"" , verify_result ) ;
692 buffer.back() =
'\0' ;
697 return std::string() ;
713GSsl::Protocol::Result GSsl::MbedTls::ProtocolImp::handshake()
715 int rc = mbedtls_ssl_handshake( m_ssl.ptr() ) ;
716 Result result = convert(
"mbedtls_ssl_handshake" , rc ) ;
717 if( result == Protocol::Result::ok )
719 const char * vstr =
"" ;
720 if( m_profile.authmode() == MBEDTLS_SSL_VERIFY_NONE )
723 vstr =
"peer certificate not verified" ;
725 else if( m_profile.authmode() == MBEDTLS_SSL_VERIFY_OPTIONAL )
727 auto v = mbedtls_ssl_get_verify_result( m_ssl.ptr() ) ;
728 m_verified = v == 0 ;
730 vstr = v == 0 ?
"peer certificate verified" :
"peer certificate failed to verify" ;
731 if( v & MBEDTLS_X509_BADCERT_EXPIRED ) vstr =
"peer certificate has expired" ;
732 if( v & MBEDTLS_X509_BADCERT_REVOKED ) vstr =
"peer certificate has been revoked" ;
733 if( v & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) vstr =
"peer certificate not signed by a trusted ca" ;
734 if( v & MBEDTLS_X509_BADCERT_MISSING ) vstr =
"peer certificate missing" ;
735 if( v & MBEDTLS_X509_BADCERT_SKIP_VERIFY ) vstr =
"peer certificate verification was skipped" ;
740 vstr =
"peer certificate verified" ;
743 m_peer_certificate = getPeerCertificate() ;
744 m_peer_certificate_chain = m_peer_certificate ;
746 m_profile.logAt( 2 , std::string(
"certificate verification: [") + vstr +
"]" ) ;
753 const char * p = mbedtls_ssl_get_version( m_ssl.ptr() ) ;
759 const char * p = mbedtls_ssl_get_ciphersuite( m_ssl.ptr() ) ;
764const GSsl::Profile & GSsl::MbedTls::ProtocolImp::profile()
const
770std::string GSsl::MbedTls::ProtocolImp::getPeerCertificate()
773 const mbedtls_x509_crt * certificate = mbedtls_ssl_get_peer_cert( m_ssl.ptr() ) ;
774 if( certificate !=
nullptr )
776 const char * head =
"-----BEGIN CERTIFICATE-----\n" ;
777 const char * tail =
"-----END CERTIFICATE-----\n" ;
779 const unsigned char * raw_p = certificate->GET_RAW(raw).GET_RAW(p) ;
780 std::size_t raw_n = certificate->GET_RAW(raw).GET_RAW(len) ;
784 unsigned char c =
'\0' ;
785 int rc = mbedtls_pem_write_buffer( head , tail , raw_p , raw_n , &c , 0 , &n ) ;
786 if( n == 0U || rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL )
787 throw Error(
"certificate error" ) ;
791 std::vector<unsigned char> buffer( n ) ;
792 rc = mbedtls_pem_write_buffer( head , tail , raw_p , raw_n , &buffer[0] , buffer.size() , &n ) ;
793 if( n == 0 || rc != 0 )
794 throw Error(
"certificate error" ) ;
796 result = std::string(
reinterpret_cast<const char *
>(&buffer[0]) , n-1U ) ;
797 if( std::string(result.c_str()) != result || result.find(tail) == std::string::npos )
798 throw Error(
"certificate error" ) ;
805 return m_peer_certificate ;
810 return m_peer_certificate_chain ;
820GSsl::MbedTls::Context::Context(
const mbedtls_ssl_config * config_p ) :
823 mbedtls_ssl_init( &x ) ;
825 int rc = mbedtls_ssl_setup( &x , config_p ) ;
826 if( rc )
throw Error(
"mbedtls_ssl_setup" , rc ) ;
829GSsl::MbedTls::Context::~Context()
831 mbedtls_ssl_free( &x ) ;
834mbedtls_ssl_context * GSsl::MbedTls::Context::ptr()
839mbedtls_ssl_context * GSsl::MbedTls::Context::ptr()
const
841 return const_cast<mbedtls_ssl_context*
>(&x) ;
846GSsl::MbedTls::Rng::Rng() :
856 mbedtls_entropy_init( &entropy ) ;
858 mbedtls_ctr_drbg_init( &x ) ;
860 static constexpr std::array<unsigned char,33> extra {
"sdflkjsdlkjsdfkljxmvnxcvmxmncvxy" } ;
861 int rc = mbedtls_ctr_drbg_seed( &x , mbedtls_entropy_func , &entropy , &extra[0] , extra.size()-1U ) ;
864 mbedtls_entropy_free( &entropy ) ;
865 throw Error(
"mbedtls_ctr_drbg_init" , rc ) ;
869GSsl::MbedTls::Rng::~Rng()
871 mbedtls_ctr_drbg_free( &x ) ;
872 mbedtls_entropy_free( &entropy ) ;
876mbedtls_ctr_drbg_context * GSsl::MbedTls::Rng::ptr()
882mbedtls_ctr_drbg_context * GSsl::MbedTls::Rng::ptr()
const
884 return const_cast<mbedtls_ctr_drbg_context*
>(&x) ;
889std::size_t GSsl::MbedTls::SecureFile::fileSize( std::filebuf & fp )
891 std::streamoff pos = fp.pubseekoff( 0 , std::ios_base::end , std::ios_base::in ) ;
892 if( pos < 0 ||
static_cast<std::make_unsigned<std::streamoff>::type
>(pos) >= std::numeric_limits<std::size_t>::max() )
894 return static_cast<std::size_t
>( pos ) ;
897bool GSsl::MbedTls::SecureFile::fileRead( std::filebuf & fp ,
char * p , std::size_t n )
899 if( p ==
nullptr || n == 0U )
901 fp.pubseekpos( 0 , std::ios_base::in ) ;
902 auto rc = fp.sgetn( p , n ) ;
903 return rc > 0 &&
static_cast<std::size_t
>(rc) == n ;
906void GSsl::MbedTls::SecureFile::scrub(
char * p_in , std::size_t n )
noexcept
909 volatile char * p = p_in ;
914void GSsl::MbedTls::SecureFile::clear( std::vector<char> & buffer )
noexcept
916 static_assert(
noexcept(buffer.empty()) ,
"" ) ;
917 static_assert(
noexcept(buffer.clear()) ,
"" ) ;
918 if( !buffer.empty() )
920 scrub( &buffer[0] , buffer.size() ) ;
925GSsl::MbedTls::SecureFile::SecureFile(
const std::string & path ,
bool with_counted_nul )
931 if(
G::File::open( f , path , G::File::InOut::In ) == nullptr )
935 std::size_t n = fileSize( f ) ;
939 m_buffer.reserve( n+1U ) ;
940 m_buffer.resize( n ) ;
941 bool ok = fileRead( f , &m_buffer[0] , n ) ;
945 if( with_counted_nul )
946 m_buffer.push_back(
'\0' ) ;
951GSsl::MbedTls::SecureFile::~SecureFile()
956const char * GSsl::MbedTls::SecureFile::p()
const
958 static char c =
'\0' ;
959 return m_buffer.empty() ? &c : &m_buffer[0] ;
963const unsigned char * GSsl::MbedTls::SecureFile::pu()
const
965 return reinterpret_cast<const unsigned char*
>( p() ) ;
969unsigned char * GSsl::MbedTls::SecureFile::pu()
971 return const_cast<unsigned char*
>(
reinterpret_cast<const unsigned char*
>(p()) ) ;
974std::size_t GSsl::MbedTls::SecureFile::size()
const
976 return m_buffer.size() ;
979bool GSsl::MbedTls::SecureFile::empty()
const
981 return m_buffer.empty() ;
986GSsl::MbedTls::Key::Key() :
989 mbedtls_pk_init( &x ) ;
992GSsl::MbedTls::Key::~Key()
994 mbedtls_pk_free( &x ) ;
997void GSsl::MbedTls::Key::load(
const std::string & pem_file ,
const Rng & rng )
999 SecureFile file( pem_file ,
true ) ;
1001 throw Error(
"cannot load private key from " + pem_file ) ;
1003 int rc = call_fn( mbedtls_pk_parse_key , &x , file.pu() , file.size() ,
1004 nullptr , 0 , mbedtls_ctr_drbg_random , rng.ptr() ) ;
1007 throw Error(
"mbedtls_pk_parse_key" , rc ) ;
1012mbedtls_pk_context * GSsl::MbedTls::Key::ptr()
1018mbedtls_pk_context * GSsl::MbedTls::Key::ptr()
const
1020 return const_cast<mbedtls_pk_context*
>( &x ) ;
1026GSsl::MbedTls::Certificate::Certificate() :
1029 mbedtls_x509_crt_init( &x ) ;
1032GSsl::MbedTls::Certificate::~Certificate()
1034 mbedtls_x509_crt_free( &x ) ;
1037void GSsl::MbedTls::Certificate::load(
const std::string & path )
1039 SecureFile file( path ,
true ) ;
1041 throw Error(
"cannot load certificates from " + path ) ;
1043 int rc = mbedtls_x509_crt_parse( &x , file.pu() , file.size() ) ;
1045 throw Error(
"mbedtls_x509_crt_parse" , rc ) ;
1047 throw Error(
"mbedtls_x509_crt_parse" ) ;
1052bool GSsl::MbedTls::Certificate::loaded()
const
1057mbedtls_x509_crt * GSsl::MbedTls::Certificate::ptr()
1059 return loaded() ? &x : nullptr ;
1063mbedtls_x509_crt * GSsl::MbedTls::Certificate::ptr()
const
1066 return const_cast<mbedtls_x509_crt*
>( &x ) ;
1074GSsl::MbedTls::Error::Error(
const std::string & s ) :
1075 std::runtime_error(
"tls error: "+s)
1079GSsl::MbedTls::Error::Error(
const std::string & fnname ,
int rc ,
const std::string & more ) :
1080 std::runtime_error(format(fnname,rc,more))
1084std::string GSsl::MbedTls::Error::format(
const std::string & fnname ,
int rc ,
const std::string & more )
1086 std::vector<char> buffer( 200U ) ;
1088 mbedtls_strerror( rc , &buffer[0] , buffer.size() ) ;
1089 buffer.back() =
'\0' ;
1091 std::ostringstream ss ;
1092 ss <<
"tls error: " << fnname <<
"(): mbedtls [" <<
G::Str::printable(std::string(&buffer[0])) <<
"]" ;
1094 ss <<
" [" << more <<
"]" ;
virtual std::string state()=0
Implements Digester::state().
virtual std::size_t blocksize() const noexcept=0
Implements Digester::blocksize().
virtual std::size_t statesize() const noexcept=0
Implements Digester::statesize().
virtual std::size_t valuesize() const noexcept=0
Implements Digester::valuesize().
virtual std::string value()=0
Implements Digester::value().
virtual void add(G::string_view)=0
Implements Digester::add().
A class for objects that can perform a cryptographic hash.
virtual bool hasProfile(const std::string &profile_name) const =0
Implements Library::hasProfile().
virtual const Profile & profile(const std::string &profile_name) const =0
Implements Library::profile().
virtual Digester digester(const std::string &, const std::string &, bool) const =0
Implements Library::digester().
virtual std::string id() const =0
Implements Library::id().
virtual G::StringArray digesters(bool) const =0
Implements Library::digesters().
virtual void addProfile(const std::string &, bool, const std::string &, const std::string &, const std::string &, const std::string &, const std::string &, const std::string &)=0
Implements Library::addProfile().
Holds protocol version information, etc.
Holds a mbedtls_ctr_drbg_context structure.
A base interface for profile classes that work with concrete classes derived from GSsl::LibraryImpBas...
virtual std::unique_ptr< ProtocolImpBase > newProtocol(const std::string &, const std::string &) const =0
Factory method for a new Protocol object.
virtual bool verified() const =0
Implements Protocol::verified().
virtual std::string peerCertificate() const =0
Implements Protocol::peerCertificate().
virtual Protocol::Result connect(G::ReadWrite &)=0
Implements Protocol::connect().
virtual std::string cipher() const =0
Implements Protocol::cipher().
virtual Protocol::Result write(const char *, std::size_t, ssize_t &)=0
Implements Protocol::write().
virtual std::string protocol() const =0
Implements Protocol::protocol().
virtual Protocol::Result read(char *, std::size_t, ssize_t &)=0
Implements Protocol::read().
virtual std::string peerCertificateChain() const =0
Implements Protocol::peerCertificateChain().
virtual Protocol::Result accept(G::ReadWrite &)=0
Implements Protocol::accept().
virtual Protocol::Result shutdown()=0
Implements Protocol::shutdown().
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
static std::string encode(const uint_type *)
Returns the hash state as an N-character string of non-printing characters.
static void decode(const std::string &s, uint_type *values_out, size_type &size_out)
Converts an encode()d string back into a hash state of N/4 integers and a data size returned by refer...
A Path object represents a file system path.
An abstract interface for reading and writing from a non-blocking i/o channel.
virtual ssize_type write(const char *buf, size_type len)=0
Sends data.
virtual ssize_type read(char *buffer, size_type buffer_length)=0
Reads data.
A class which acquires the process's special privileges on construction and releases them on destruct...
A class that calls an exit function at the end of its scope.
static void splitIntoTokens(const std::string &in, StringArray &out, string_view ws, char esc='\0')
Splits the string into 'ws'-delimited tokens.
static std::string join(string_view sep, const StringArray &strings)
Concatenates an array of strings with separators.
static std::string printable(const std::string &in, char escape='\\')
Returns a printable representation of the given input string, using chacter code ranges 0x20 to 0x7e ...
static std::string trimmed(const std::string &s, string_view ws)
Returns a trim()med version of s.
static string_view ws() noexcept
Returns a string of standard whitespace characters.
A class like c++17's std::string_view.
An interface to an underlying TLS library.
std::vector< std::string > StringArray
A std::vector of std::strings.