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
68#ifndef GCONFIG_HAVE_MBEDTLS_PSA
69#if MBEDTLS_VERSION_MAJOR >= 3
70#define GCONFIG_HAVE_MBEDTLS_PSA 1
72#define GCONFIG_HAVE_MBEDTLS_PSA 0
76GSsl::MbedTls::LibraryImp::LibraryImp(
G::StringArray & library_config , Library::LogFn log_fn ,
bool verbose ) :
78 m_config(library_config)
80 mbedtls_debug_set_threshold( verbose ? 3 : 1 ) ;
84 #if GCONFIG_HAVE_MBEDTLS_PSA
85 call( FN_OK(PSA_SUCCESS,psa_crypto_init) ) ;
90GSsl::MbedTls::LibraryImp::~LibraryImp()
99 const std::string & key_file ,
const std::string & cert_file ,
const std::string & ca_file ,
100 const std::string & default_peer_certificate_name ,
const std::string & default_peer_host_name ,
101 const std::string & profile_config )
103 std::shared_ptr<ProfileImp> profile_ptr =
104 std::make_shared<ProfileImp>(*
this,is_server_profile,key_file,cert_file,ca_file,
105 default_peer_certificate_name,default_peer_host_name,profile_config) ;
106 m_profile_map.insert( Map::value_type(profile_name,profile_ptr) ) ;
111 auto p = m_profile_map.find( profile_name ) ;
112 return p != m_profile_map.end() ;
117 auto p = m_profile_map.find( profile_name ) ;
118 if( p == m_profile_map.end() )
throw Error(
"no such profile: [" + profile_name +
"]" ) ;
119 return *(*p).second ;
122GSsl::Library::LogFn GSsl::MbedTls::LibraryImp::log()
const
127std::string GSsl::MbedTls::LibraryImp::features()
129 if( 0 == mbedtls_version_check_feature(
"MBEDTLS_SSL_PROTO_TLS1_3" ) )
135std::string GSsl::MbedTls::LibraryImp::sid()
137 std::vector<char> buffer( 100U ) ;
138 G_ASSERT( buffer.size() >= 18U ) ;
139 mbedtls_version_get_string_full( buffer.data() ) ;
140 buffer[buffer.size()-1U] =
'\0' ;
154std::string GSsl::MbedTls::LibraryImp::credit(
const std::string & ,
const std::string & ,
const std::string & )
162 return {
"MD5" ,
"SHA1" ,
"SHA256" } ;
167 return Digester( std::make_unique<DigesterImp>(hash_type,state,need_state) ) ;
173 m_noverify(consume(config,
"noverify")),
174 m_noisy(consume(config,
"noisy"))
177#if defined(MBEDTLS_SSL_MINOR_VERSION_0) && defined(MBEDTLS_SSL_PROTO_SSL3)
178 static constexpr int SSL_v3 = MBEDTLS_SSL_MINOR_VERSION_0 ;
179 static_assert( SSL_v3 >= 0 ,
"" ) ;
180 if( consume(config,
"sslv3") ) m_min = SSL_v3 ;
181 if( consume(config,
"-sslv3") ) m_max = SSL_v3 ;
184#if defined(MBEDTLS_SSL_MINOR_VERSION_1) && defined(MBEDTLS_SSL_PROTO_TLS1)
185 static constexpr int TLS_v1_0 = MBEDTLS_SSL_MINOR_VERSION_1 ;
186 static_assert( TLS_v1_0 >= 0 ,
"" ) ;
187 if( consume(config,
"tlsv1.0") ) m_min = TLS_v1_0 ;
188 if( consume(config,
"-tlsv1.0") ) m_max = TLS_v1_0 ;
191#if defined(MBEDTLS_SSL_MINOR_VERSION_2) && defined(MBEDTLS_SSL_PROTO_TLS1_1)
192 static constexpr int TLS_v1_1 = MBEDTLS_SSL_MINOR_VERSION_2 ;
193 static_assert( TLS_v1_1 >= 0 ,
"" ) ;
194 if( consume(config,
"tlsv1.1") ) m_min = TLS_v1_1 ;
195 if( consume(config,
"-tlsv1.1") ) m_max = TLS_v1_1 ;
198#if defined(MBEDTLS_SSL_MINOR_VERSION_3) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
199 static constexpr int TLS_v1_2 = MBEDTLS_SSL_MINOR_VERSION_3 ;
200 static_assert( TLS_v1_2 >= 0 ,
"" ) ;
201 if( consume(config,
"tlsv1.2") ) m_min = TLS_v1_2 ;
202 if( consume(config,
"-tlsv1.2") ) m_max = TLS_v1_2 ;
205#if defined(MBEDTLS_SSL_MINOR_VERSION_4) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
206 static constexpr int TLS_v1_3 = MBEDTLS_SSL_MINOR_VERSION_4 ;
207 static_assert( TLS_v1_3 >= 0 ,
"" ) ;
208 if( consume(config,
"tlsv1.3") ) m_min = TLS_v1_3 ;
209 if( consume(config,
"-tlsv1.3") ) m_max = TLS_v1_3 ;
212#if GCONFIG_HAVE_MBEDTLS_PSA
213 if( consume(config,
"nopsa") )
218int GSsl::MbedTls::Config::min_() const noexcept
223int GSsl::MbedTls::Config::max_() const noexcept
228bool GSsl::MbedTls::Config::noverify() const noexcept
233bool GSsl::MbedTls::Config::psa() const noexcept
238bool GSsl::MbedTls::Config::noisy() const noexcept
243bool GSsl::MbedTls::Config::consume(
G::StringArray & list , std::string_view item )
245 return LibraryImp::consume( list , item ) ;
250GSsl::MbedTls::DigesterImp::DigesterImp(
const std::string & hash_name ,
const std::string & state ,
bool need_state ) :
253 bool have_state = !state.empty() ;
255 #if ! GCONFIG_HAVE_MBEDTLS_HASH_STATE
256 if( have_state || need_state )
258 throw Error( std::string(
"hash state restoration not implemented for ").append(hash_name) ) ;
261 GDEF_IGNORE_PARAM( need_state ) ;
264 if( hash_name ==
"MD5" )
266 m_hash_type = Type::Md5 ;
270 mbedtls_md5_init( &m_md5 ) ;
271 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
272 m_state_size = m_value_size + 4U ;
276 call( FN_RET(mbedtls_md5_starts) , &m_md5 ) ;
278 call( FN_RET(mbedtls_md5_starts) , &m_md5 ) ;
281 else if( hash_name ==
"SHA1" )
283 m_hash_type = Type::Sha1 ;
287 mbedtls_sha1_init( &m_sha1 ) ;
288 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
289 m_state_size = m_value_size + 4U ;
293 call( FN_RET(mbedtls_sha1_starts) , &m_sha1 ) ;
295 call( FN_RET(mbedtls_sha1_starts) , &m_sha1 ) ;
298 else if( hash_name ==
"SHA256" )
300 m_hash_type = Type::Sha256 ;
304 mbedtls_sha256_init( &m_sha256 ) ;
305 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
306 m_state_size = m_value_size + 4U ;
310 call( FN_RET(mbedtls_sha256_starts) , &m_sha256 , 0 ) ;
312 call( FN_RET(mbedtls_sha256_starts) , &m_sha256 , 0 ) ;
317 throw Error(
"invalid hash function" ) ;
321GSsl::MbedTls::DigesterImp::~DigesterImp()
323 if( m_hash_type == Type::Md5 )
324 mbedtls_md5_free( &m_md5 ) ;
325 else if( m_hash_type == Type::Sha1 )
326 mbedtls_sha1_free( &m_sha1 ) ;
327 else if( m_hash_type == Type::Sha256 )
328 mbedtls_sha256_free( &m_sha256 ) ;
333 if( m_hash_type == Type::Md5 )
334 call( FN_RET(mbedtls_md5_update) , &m_md5 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
335 else if( m_hash_type == Type::Sha1 )
336 call( FN_RET(mbedtls_sha1_update) , &m_sha1 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
337 else if( m_hash_type == Type::Sha256 )
338 call( FN_RET(mbedtls_sha256_update) , &m_sha256 ,
reinterpret_cast<const unsigned char*
>(sv.data()) , sv.size() ) ;
343 if( m_hash_type == Type::Md5 )
345 std::array<unsigned char,16> buffer {} ;
346 call( FN_RET(mbedtls_md5_finish) , &m_md5 , buffer.data() ) ;
347 return {
reinterpret_cast<const char*
>(buffer.data()) , buffer.size() } ;
349 else if( m_hash_type == Type::Sha1 )
351 std::array<unsigned char,20> buffer {} ;
352 call( FN_RET(mbedtls_sha1_finish) , &m_sha1 , buffer.data() ) ;
353 return {
reinterpret_cast<const char*
>(buffer.data()) , buffer.size() } ;
355 else if( m_hash_type == Type::Sha256 )
357 std::array<unsigned char,32> buffer {} ;
358 call( FN_RET(mbedtls_sha256_finish) , &m_sha256 , buffer.data() ) ;
359 return {
reinterpret_cast<const char*
>(buffer.data()) , buffer.size() } ;
369 #if GCONFIG_HAVE_MBEDTLS_HASH_STATE
370 if( m_hash_type == Type::Md5 )
372 else if( m_hash_type == Type::Sha1 )
374 else if( m_hash_type == Type::Sha256 )
385 return m_block_size ;
390 return m_value_size ;
395 return m_state_size ;
400GSsl::MbedTls::ProfileImp::ProfileImp(
const LibraryImp & library_imp ,
bool is_server_profile ,
401 const std::string & key_file ,
const std::string & cert_file ,
const std::string & ca_path ,
402 const std::string & default_peer_certificate_name ,
const std::string & default_peer_host_name ,
403 const std::string & profile_config ) :
404 m_library_imp(library_imp) ,
405 m_default_peer_certificate_name(default_peer_certificate_name) ,
406 m_default_peer_host_name(default_peer_host_name) ,
409 mbedtls_ssl_config * cleanup_ptr = nullptr ;
410 G::ScopeExit cleanup( [&](){
if(cleanup_ptr) mbedtls_ssl_config_free(cleanup_ptr);} ) ;
413 Config extra_config = library_imp.config() ;
414 if( !profile_config.empty() )
417 extra_config = Config( profile_config_list ) ;
418 if( !profile_config_list.empty() )
419 G_WARNING(
"GSsl::MbedTls::ProfileImp::ctor: tls-config: tls " << (is_server_profile?
"server":
"client")
420 <<
" profile configuration ignored: [" <<
G::Str::join(
",",profile_config_list) <<
"]" ) ;
422 m_noisy = extra_config.noisy() ;
426 mbedtls_ssl_config_init( &m_config ) ;
427 cleanup_ptr = &m_config ;
428 int rc = mbedtls_ssl_config_defaults( &m_config ,
429 is_server_profile ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT ,
430 MBEDTLS_SSL_TRANSPORT_STREAM ,
431 MBEDTLS_SSL_PRESET_DEFAULT ) ;
432 if( rc )
throw Error(
"mbedtls_ssl_config_defaults" , rc ) ;
436 if( !key_file.empty() )
437 m_pk.load( key_file , library_imp.rng() ) ;
438 if( !cert_file.empty() )
439 m_certificate.load( cert_file ) ;
442 if( m_certificate.loaded() )
444 int rc = mbedtls_ssl_conf_own_cert( &m_config , m_certificate.ptr() , m_pk.ptr() ) ;
446 throw Error(
"mbedtls_ssl_conf_own_cert" , rc ) ;
451 if( ca_path.empty() )
457 m_authmode = MBEDTLS_SSL_VERIFY_OPTIONAL ;
459 else if( ca_path ==
"<none>" )
462 m_authmode = MBEDTLS_SSL_VERIFY_NONE ;
464 else if( ca_path ==
"<default>" )
467 std::string ca_path_default =
"/etc/ssl/certs/ca-certificates.crt" ;
468 m_ca_list.load( ca_path_default ) ;
469 bool no_verify = extra_config.noverify() ;
470 mbedtls_ssl_conf_ca_chain( &m_config , m_ca_list.ptr() , crl() ) ;
471 m_authmode = no_verify ? MBEDTLS_SSL_VERIFY_OPTIONAL : MBEDTLS_SSL_VERIFY_REQUIRED ;
476 m_ca_list.load( ca_path ) ;
477 bool no_verify = extra_config.noverify() ;
478 mbedtls_ssl_conf_ca_chain( &m_config , m_ca_list.ptr() , crl() ) ;
479 m_authmode = no_verify ? MBEDTLS_SSL_VERIFY_OPTIONAL : MBEDTLS_SSL_VERIFY_REQUIRED ;
481 mbedtls_ssl_conf_authmode( &m_config , m_authmode ) ;
486 if( extra_config.min_() >= 0 )
487 mbedtls_ssl_conf_min_version( &m_config , MBEDTLS_SSL_MAJOR_VERSION_3 , extra_config.min_() ) ;
488 if( extra_config.max_() >= 0 )
489 mbedtls_ssl_conf_max_version( &m_config , MBEDTLS_SSL_MAJOR_VERSION_3 , extra_config.max_() ) ;
494 mbedtls_ssl_conf_rng( &m_config , mbedtls_ctr_drbg_random , m_library_imp.rng().ptr() ) ;
495 mbedtls_ssl_conf_dbg( &m_config , onDebug ,
this ) ;
500 mbedtls_ssl_conf_renegotiation( &m_config , MBEDTLS_SSL_RENEGOTIATION_DISABLED ) ;
505GSsl::MbedTls::ProfileImp::~ProfileImp()
507 mbedtls_ssl_config_free( &m_config ) ;
511 const std::string & peer_host_name )
const
513 return std::make_unique<MbedTls::ProtocolImp>( *
this ,
514 peer_certificate_name.empty()?defaultPeerCertificateName():peer_certificate_name ,
515 peer_host_name.empty()?defaultPeerHostName():peer_host_name ) ;
518mbedtls_x509_crl * GSsl::MbedTls::ProfileImp::crl()
const
524const mbedtls_ssl_config * GSsl::MbedTls::ProfileImp::config()
const
529void GSsl::MbedTls::ProfileImp::onDebug(
void * This ,
int level_in ,
const char * file ,
int line ,
const char * message )
533 static_cast<ProfileImp*
>(This)->doDebug( level_in , file , line , message ) ;
540void GSsl::MbedTls::ProfileImp::doDebug(
int level_in ,
const char * file ,
int line ,
const char * message )
555 int level_out = level_in >= 4 ? 0 : ( level_in >= 2 ? 1 : 3 ) ;
556 if( m_library_imp.log() && level_out )
558 std::ostringstream ss ;
559 G::Path path( file ? std::string(file) : std::string() ) ;
560 ss << path.basename() <<
"(" << line <<
"): " << (message?message:
"") ;
561 logAt( level_out , ss.str() ) ;
565void GSsl::MbedTls::ProfileImp::logAt(
int level_out , std::string s )
const
567 Library::LogFn log_fn = m_library_imp.log() ;
572 (*log_fn)( level_out , s ) ;
576const std::string & GSsl::MbedTls::ProfileImp::defaultPeerCertificateName()
const
578 return m_default_peer_certificate_name ;
581const std::string & GSsl::MbedTls::ProfileImp::defaultPeerHostName()
const
583 return m_default_peer_host_name ;
586int GSsl::MbedTls::ProfileImp::authmode()
const
593GSsl::MbedTls::ProtocolImp::ProtocolImp(
const ProfileImp & profile ,
const std::string & required_peer_certificate_name ,
594 const std::string & target_peer_host_name ) :
596 m_ssl(profile.config())
598 mbedtls_ssl_set_bio( m_ssl.ptr() ,
this , doSend , doRecv ,
nullptr ) ;
605 std::string name = target_peer_host_name.empty() ? required_peer_certificate_name : target_peer_host_name ;
607 mbedtls_ssl_set_hostname( m_ssl.ptr() , name.c_str() ) ;
610GSsl::MbedTls::ProtocolImp::~ProtocolImp()
615 int rc = mbedtls_ssl_read( m_ssl.ptr() ,
reinterpret_cast<unsigned char*
>(buffer) , buffer_size_in ) ;
616 data_size_out = rc < 0 ? 0 : rc ;
617 if( rc == 0 )
return Protocol::Result::error ;
618 std::size_t available = rc > 0 ? mbedtls_ssl_get_bytes_avail( m_ssl.ptr() ) : 0U ;
619 return convert(
"mbedtls_ssl_read" , rc , available > 0U ) ;
623 ssize_t & data_size_out )
625 const unsigned char * p =
reinterpret_cast<const unsigned char *
>(buffer_in) ;
626 ssize_t n =
static_cast<ssize_t
>(data_size_in) ; G_ASSERT( n >= 0 ) ;
629 int rc = mbedtls_ssl_write( m_ssl.ptr() , p , n ) ;
632 data_size_out =
static_cast<ssize_t
>(data_size_in) ;
633 return Protocol::Result::ok ;
642 return convert(
"mbedtls_ssl_write" , rc ) ;
649 int rc = mbedtls_ssl_close_notify( m_ssl.ptr() ) ;
650 return convert(
"mbedtls_ssl_close_notify" , rc ) ;
654int GSsl::MbedTls::ProtocolImp::doRecvTimeout(
void * This ,
unsigned char * p , std::size_t n , uint32_t )
658 return doRecv( This , p , n ) ;
662int GSsl::MbedTls::ProtocolImp::doRecv(
void * This ,
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->
read(
reinterpret_cast<char*
>(p) , n ) ;
667 if( rc < 0 && io->eWouldBlock() )
return MBEDTLS_ERR_SSL_WANT_READ ;
668 if( rc < 0 )
return MBEDTLS_ERR_NET_RECV_FAILED ;
669 return static_cast<int>(rc) ;
672int GSsl::MbedTls::ProtocolImp::doSend(
void * This ,
const unsigned char * p , std::size_t n )
674 G::ReadWrite * io =
static_cast<ProtocolImp*
>(This)->m_io ;
675 G_ASSERT( io !=
nullptr ) ;
676 ssize_t rc = io->
write(
reinterpret_cast<const char*
>(p) , n ) ;
677 if( rc < 0 && io->eWouldBlock() )
return MBEDTLS_ERR_SSL_WANT_WRITE ;
678 if( rc < 0 )
return MBEDTLS_ERR_NET_SEND_FAILED ;
679 return static_cast<int>(rc) ;
682GSsl::Protocol::Result GSsl::MbedTls::ProtocolImp::convert(
const char * fnname ,
int rc ,
bool more )
685 if( rc == MBEDTLS_ERR_SSL_WANT_READ )
return Protocol::Result::read ;
686 if( rc == MBEDTLS_ERR_SSL_WANT_WRITE )
return Protocol::Result::write ;
687 if( rc == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
return Protocol::Result::error ;
690 throw Error( fnname , rc , verifyResultString(rc) ) ;
692 return more ? Protocol::Result::more : Protocol::Result::ok ;
695std::string GSsl::MbedTls::ProtocolImp::verifyResultString(
int rc )
697 if( rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
699 auto verify_result = mbedtls_ssl_get_verify_result( m_ssl.ptr() ) ;
700 std::vector<char> buffer( 1024U ) ;
701 mbedtls_x509_crt_verify_info( buffer.data() , buffer.size() ,
"" , verify_result ) ;
702 buffer.back() =
'\0' ;
723GSsl::Protocol::Result GSsl::MbedTls::ProtocolImp::handshake()
725 int rc = mbedtls_ssl_handshake( m_ssl.ptr() ) ;
726 Result result = convert(
"mbedtls_ssl_handshake" , rc ) ;
727 if( result == Protocol::Result::ok )
729 const char * vstr =
"" ;
730 if( m_profile.authmode() == MBEDTLS_SSL_VERIFY_NONE )
733 vstr =
"peer certificate not verified" ;
735 else if( m_profile.authmode() == MBEDTLS_SSL_VERIFY_OPTIONAL )
737 auto v = mbedtls_ssl_get_verify_result( m_ssl.ptr() ) ;
738 m_verified = v == 0 ;
740 vstr = v == 0 ?
"peer certificate verified" :
"peer certificate failed to verify" ;
741 if( v & MBEDTLS_X509_BADCERT_EXPIRED ) vstr =
"peer certificate has expired" ;
742 if( v & MBEDTLS_X509_BADCERT_REVOKED ) vstr =
"peer certificate has been revoked" ;
743 if( v & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) vstr =
"peer certificate not signed by a trusted ca" ;
744 if( v & MBEDTLS_X509_BADCERT_MISSING ) vstr =
"peer certificate missing" ;
745 if( v & MBEDTLS_X509_BADCERT_SKIP_VERIFY ) vstr =
"peer certificate verification was skipped" ;
750 vstr =
"peer certificate verified" ;
753 m_peer_certificate = getPeerCertificate() ;
754 m_peer_certificate_chain = m_peer_certificate ;
756 m_profile.logAt( 2 , std::string(
"certificate verification: [") + vstr +
"]" ) ;
763 const char * p = mbedtls_ssl_get_version( m_ssl.ptr() ) ;
769 const char * p = mbedtls_ssl_get_ciphersuite( m_ssl.ptr() ) ;
774const GSsl::Profile & GSsl::MbedTls::ProtocolImp::profile()
const
780std::string GSsl::MbedTls::ProtocolImp::getPeerCertificate()
783 const mbedtls_x509_crt * certificate = mbedtls_ssl_get_peer_cert( m_ssl.ptr() ) ;
784 if( certificate !=
nullptr )
786 const char * head =
"-----BEGIN CERTIFICATE-----\n" ;
787 const char * tail =
"-----END CERTIFICATE-----\n" ;
789 const unsigned char * raw_p = certificate->GET_RAW(raw).GET_RAW(p) ;
790 std::size_t raw_n = certificate->GET_RAW(raw).GET_RAW(len) ;
794 unsigned char c =
'\0' ;
795 int rc = mbedtls_pem_write_buffer( head , tail , raw_p , raw_n , &c , 0 , &n ) ;
796 if( n == 0U || rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL )
797 throw Error(
"certificate error" ) ;
801 std::vector<unsigned char> buffer( n ) ;
802 rc = mbedtls_pem_write_buffer( head , tail , raw_p , raw_n , buffer.data() , buffer.size() , &n ) ;
803 if( n == 0 || rc != 0 )
804 throw Error(
"certificate error" ) ;
806 result = std::string(
reinterpret_cast<const char *
>(buffer.data()) , n-1U ) ;
807 if( std::string(result.c_str()) != result || result.find(tail) == std::string::npos )
808 throw Error(
"certificate error" ) ;
815 return m_peer_certificate ;
820 return m_peer_certificate_chain ;
830GSsl::MbedTls::Context::Context(
const mbedtls_ssl_config * config_p ) :
833 mbedtls_ssl_init( &x ) ;
835 int rc = mbedtls_ssl_setup( &x , config_p ) ;
836 if( rc )
throw Error(
"mbedtls_ssl_setup" , rc ) ;
839GSsl::MbedTls::Context::~Context()
841 mbedtls_ssl_free( &x ) ;
844mbedtls_ssl_context * GSsl::MbedTls::Context::ptr()
849mbedtls_ssl_context * GSsl::MbedTls::Context::ptr()
const
851 return const_cast<mbedtls_ssl_context*
>(&x) ;
856GSsl::MbedTls::Rng::Rng() :
866 mbedtls_entropy_init( &entropy ) ;
868 mbedtls_ctr_drbg_init( &x ) ;
870 static constexpr std::array<unsigned char,33> extra {
"sdflkjsdlkjsdfkljxmvnxcvmxmncvxy" } ;
871 int rc = mbedtls_ctr_drbg_seed( &x , mbedtls_entropy_func , &entropy , extra.data() , extra.size()-1U ) ;
874 mbedtls_entropy_free( &entropy ) ;
875 throw Error(
"mbedtls_ctr_drbg_init" , rc ) ;
879GSsl::MbedTls::Rng::~Rng()
881 mbedtls_ctr_drbg_free( &x ) ;
882 mbedtls_entropy_free( &entropy ) ;
886mbedtls_ctr_drbg_context * GSsl::MbedTls::Rng::ptr()
892mbedtls_ctr_drbg_context * GSsl::MbedTls::Rng::ptr()
const
894 return const_cast<mbedtls_ctr_drbg_context*
>(&x) ;
899std::size_t GSsl::MbedTls::SecureFile::fileSize( std::filebuf & fp )
901 std::streamoff pos = fp.pubseekoff( 0 , std::ios_base::end , std::ios_base::in ) ;
902 if( pos < 0 ||
static_cast<std::make_unsigned<std::streamoff>::type
>(pos) >= std::numeric_limits<std::size_t>::max() )
904 return static_cast<std::size_t
>( pos ) ;
907bool GSsl::MbedTls::SecureFile::fileRead( std::filebuf & fp ,
char * p , std::size_t n )
909 if( p ==
nullptr || n == 0U )
911 fp.pubseekpos( 0 , std::ios_base::in ) ;
912 auto rc = fp.sgetn( p , n ) ;
913 return rc > 0 &&
static_cast<std::size_t
>(rc) == n ;
916void GSsl::MbedTls::SecureFile::scrub(
char * p_in , std::size_t n )
noexcept
919 volatile char * p = p_in ;
924void GSsl::MbedTls::SecureFile::clear( std::vector<char> & buffer )
noexcept
926 static_assert(
noexcept(buffer.empty()) ,
"" ) ;
927 static_assert(
noexcept(buffer.clear()) ,
"" ) ;
928 if( !buffer.empty() )
930 scrub( buffer.data() , buffer.size() ) ;
935GSsl::MbedTls::SecureFile::SecureFile(
const G::Path & path ,
bool with_counted_nul )
941 if(
G::File::open( f , path , G::File::InOut::In ) == nullptr )
945 std::size_t n = fileSize( f ) ;
949 m_buffer.reserve( n+1U ) ;
950 m_buffer.resize( n ) ;
951 bool ok = fileRead( f , m_buffer.data() , n ) ;
955 if( with_counted_nul )
956 m_buffer.push_back(
'\0' ) ;
961GSsl::MbedTls::SecureFile::~SecureFile()
966const char * GSsl::MbedTls::SecureFile::p()
const
968 static char c =
'\0' ;
969 return m_buffer.empty() ? &c : m_buffer.data() ;
973const unsigned char * GSsl::MbedTls::SecureFile::pu()
const
975 return reinterpret_cast<const unsigned char*
>( p() ) ;
979unsigned char * GSsl::MbedTls::SecureFile::pu()
981 return const_cast<unsigned char*
>(
reinterpret_cast<const unsigned char*
>(p()) ) ;
984std::size_t GSsl::MbedTls::SecureFile::size()
const
986 return m_buffer.size() ;
989bool GSsl::MbedTls::SecureFile::empty()
const
991 return m_buffer.empty() ;
996GSsl::MbedTls::Key::Key() :
999 mbedtls_pk_init( &x ) ;
1002GSsl::MbedTls::Key::~Key()
1004 mbedtls_pk_free( &x ) ;
1007void GSsl::MbedTls::Key::load(
const std::string & pem_file ,
const Rng & rng )
1009 SecureFile file( pem_file ,
true ) ;
1011 throw Error(
"cannot load private key from " + pem_file ) ;
1013 int rc = call_fn( mbedtls_pk_parse_key , &x , file.pu() , file.size() ,
1014 nullptr , 0 , mbedtls_ctr_drbg_random , rng.ptr() ) ;
1017 throw Error(
"mbedtls_pk_parse_key" , rc ) ;
1022mbedtls_pk_context * GSsl::MbedTls::Key::ptr()
1028mbedtls_pk_context * GSsl::MbedTls::Key::ptr()
const
1030 return const_cast<mbedtls_pk_context*
>( &x ) ;
1036GSsl::MbedTls::Certificate::Certificate() :
1039 mbedtls_x509_crt_init( &x ) ;
1042GSsl::MbedTls::Certificate::~Certificate()
1044 mbedtls_x509_crt_free( &x ) ;
1047void GSsl::MbedTls::Certificate::load(
const std::string & path )
1049 SecureFile file( path ,
true ) ;
1051 throw Error(
"cannot load certificates from " + path ) ;
1053 int rc = mbedtls_x509_crt_parse( &x , file.pu() , file.size() ) ;
1055 throw Error(
"mbedtls_x509_crt_parse" , rc ) ;
1057 throw Error(
"mbedtls_x509_crt_parse" ) ;
1062bool GSsl::MbedTls::Certificate::loaded()
const
1067mbedtls_x509_crt * GSsl::MbedTls::Certificate::ptr()
1069 return loaded() ? &x : nullptr ;
1073mbedtls_x509_crt * GSsl::MbedTls::Certificate::ptr()
const
1076 return const_cast<mbedtls_x509_crt*
>( &x ) ;
1084GSsl::MbedTls::Error::Error(
const std::string & s ) :
1085 std::runtime_error(
"tls error: "+s)
1089GSsl::MbedTls::Error::Error(
const std::string & fnname ,
int rc ,
const std::string & more ) :
1090 std::runtime_error(format(fnname,rc,more))
1094std::string GSsl::MbedTls::Error::format(
const std::string & fnname ,
int rc ,
const std::string & more )
1096 std::vector<char> buffer( 200U ) ;
1098 mbedtls_strerror( rc , buffer.data() , buffer.size() ) ;
1099 buffer.back() =
'\0' ;
1101 std::ostringstream ss ;
1102 ss <<
"tls error: " << fnname <<
"(): mbedtls [" <<
G::Str::printable(std::string(buffer.data())) <<
"]" ;
1104 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(std::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, std::string_view ws, char esc='\0')
Splits the string into 'ws'-delimited tokens.
static std::string join(std::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_view ws() noexcept
Returns a string of standard whitespace characters.
static std::string trimmed(const std::string &s, std::string_view ws)
Returns a trim()med version of s.
An interface to an underlying TLS library.
std::vector< std::string > StringArray
A std::vector of std::strings.