E-MailRelay
gssl_mbedtls.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gssl_mbedtls.h
19///
20
21#ifndef G_SSL_MBEDTLS_H
22#define G_SSL_MBEDTLS_H
23
24#include "gdef.h"
25#include "gssl.h"
27#include "gstringview.h"
28#include "gpath.h"
29#include <memory>
30#include <stdexcept>
31#include <vector>
32#include <map>
33
34namespace GSsl
35{
36 namespace MbedTls /// A namespace for implementing the GSsl interface using the mbedtls library.
37 {
38 class Certificate ;
39 class Rng ;
40 class Key ;
41 class Context ;
42 class Error ;
43 class SecureFile ;
44 class LibraryImp ;
45 class ProfileImp ;
46 class ProtocolImp ;
47 class DigesterImp ;
48 class Config ;
49 }
50}
51
52//| \class GSsl::MbedTls::Certificate
53/// Holds a mbedtls_x509_crt structure.
54///
56{
57public:
58 Certificate() ;
59 ~Certificate() ;
60 void load( const std::string & file ) ;
61 bool loaded() const ;
62 mbedtls_x509_crt * ptr() ;
63 mbedtls_x509_crt * ptr() const ;
64
65public:
66 Certificate( const Certificate & ) = delete ;
67 Certificate( Certificate && ) = delete ;
68 Certificate & operator=( const Certificate & ) = delete ;
69 Certificate & operator=( Certificate && ) = delete ;
70
71private:
72 bool m_loaded{false} ;
73 mbedtls_x509_crt x ;
74} ;
75
76//| \class GSsl::MbedTls::Rng
77/// Holds a mbedtls_ctr_drbg_context structure.
78///
80{
81public:
82 Rng() ;
83 ~Rng() ;
84 mbedtls_ctr_drbg_context * ptr() ;
85 mbedtls_ctr_drbg_context * ptr() const ;
86
87public:
88 Rng( const Rng & ) = delete ;
89 Rng( Rng && ) = delete ;
90 Rng & operator=( const Rng & ) = delete ;
91 Rng & operator=( Rng && ) = delete ;
92
93private:
94 mbedtls_ctr_drbg_context x ; // "counter-mode deterministic random byte generator"
95 mbedtls_entropy_context entropy ;
96} ;
97
98//| \class GSsl::MbedTls::Key
99/// Holds a mbedtls_pk_context structure.
100///
102{
103public:
104 Key() ;
105 ~Key() ;
106 void load( const std::string & file , const Rng & ) ;
107 mbedtls_pk_context * ptr() ;
108 mbedtls_pk_context * ptr() const ;
109
110public:
111 Key( const Key & ) = delete ;
112 Key( Key && ) = delete ;
113 Key & operator=( const Key & ) = delete ;
114 Key & operator=( Key && ) = delete ;
115
116private:
117 mbedtls_pk_context x ;
118} ;
119
120//| \class GSsl::MbedTls::Context
121/// Holds a mbedtls_ssl_context structure.
122///
124{
125public:
126 explicit Context( const mbedtls_ssl_config * ) ;
127 ~Context() ;
128 mbedtls_ssl_context * ptr() ;
129 mbedtls_ssl_context * ptr() const ;
130
131public:
132 Context( const Context & ) = delete ;
133 Context( Context && ) = delete ;
134 Context & operator=( const Context & ) = delete ;
135 Context & operator=( Context && ) = delete ;
136
137private:
138 mbedtls_ssl_context x ;
139} ;
140
141//| \class GSsl::MbedTls::Error
142/// An exception class for GSsl::MbedTls classes.
143///
144class GSsl::MbedTls::Error : public std::runtime_error
145{
146public:
147 explicit Error( const std::string & ) ;
148 Error( const std::string & , int rc , const std::string & more = {} ) ;
149
150private:
151 static std::string format( const std::string & , int , const std::string & ) ;
152} ;
153
154//| \class GSsl::MbedTls::SecureFile
155/// An interface for reading a sensitive file and then overwriting
156/// its contents in memory.
157///
159{
160public:
161 SecureFile( const G::Path & path , bool with_counted_nul ) ;
162 ~SecureFile() ;
163 const char * p() const ;
164 const unsigned char * pu() const ;
165 unsigned char * pu() ;
166 std::size_t size() const ;
167 bool empty() const ;
168
169public:
170 SecureFile( const SecureFile & ) = delete ;
171 SecureFile( SecureFile && ) = delete ;
172 SecureFile & operator=( const SecureFile & ) = delete ;
173 SecureFile & operator=( SecureFile && ) = delete ;
174
175private:
176 static std::size_t fileSize( std::filebuf & ) ;
177 static bool fileRead( std::filebuf & , char * , std::size_t ) ;
178 static void scrub( char * , std::size_t ) noexcept ;
179 static void clear( std::vector<char> & ) noexcept ;
180
181private:
182 std::vector<char> m_buffer ;
183} ;
184
185//| \class GSsl::MbedTls::Config
186/// Holds protocol version information, etc.
187///
189{
190public:
191 explicit Config( G::StringArray & config ) ;
192 int min_() const noexcept ;
193 int max_() const noexcept ;
194 bool noverify() const noexcept ;
195 bool noisy() const noexcept ;
196 bool psa() const noexcept ;
197
198private:
199 static bool consume( G::StringArray & , std::string_view ) ;
200
201private:
202 bool m_noverify ;
203 bool m_noisy ;
204 int m_min {-1} ;
205 int m_max {-1} ;
206 bool m_psa {true} ;
207} ;
208
209//| \class GSsl::MbedTls::LibraryImp
210/// An implementation of the GSsl::LibraryImpBase interface for mbedtls.
211///
212class GSsl::MbedTls::LibraryImp : public LibraryImpBase
213{
214public:
215 using Rng = MbedTls::Rng ;
216
217 LibraryImp( G::StringArray & , Library::LogFn , bool verbose ) ;
218 ~LibraryImp() override ;
219 const Rng & rng() const ;
220 Library::LogFn log() const ;
221 Config config() const ;
222 static std::string credit( const std::string & , const std::string & , const std::string & ) ;
223 static std::string sid() ;
224 static std::string features() ;
225
226private: // overrides
227 void addProfile( const std::string & profile_name , bool is_server_profile ,
228 const std::string & key_file , const std::string & cert_file , const std::string & ca_file ,
229 const std::string & default_peer_certificate_name , const std::string & default_peer_host_name ,
230 const std::string & profile_config ) override ;
231 bool hasProfile( const std::string & profile_name ) const override ;
232 const Profile & profile( const std::string & profile_name ) const override ;
233 std::string id() const override ;
234 G::StringArray digesters( bool ) const override ;
235 Digester digester( const std::string & , const std::string & , bool ) const override ;
236
237public:
238 LibraryImp( const LibraryImp & ) = delete ;
239 LibraryImp( LibraryImp && ) = delete ;
240 LibraryImp & operator=( const LibraryImp & ) = delete ;
241 LibraryImp & operator=( LibraryImp && ) = delete ;
242
243private:
244 static int minVersionFrom( G::StringArray & ) ;
245 static int maxVersionFrom( G::StringArray & ) ;
246
247private:
248 using Map = std::map<std::string,std::shared_ptr<ProfileImp>> ;
249 Library::LogFn m_log_fn ;
250 Config m_config ;
251 Map m_profile_map ;
252 Rng m_rng ;
253} ;
254
255//| \class GSsl::MbedTls::ProfileImp
256/// An implementation of the GSsl::Profile interface for mbedtls.
257///
258class GSsl::MbedTls::ProfileImp : public Profile
259{
260public:
261 using Key = MbedTls::Key ;
262 using Error = MbedTls::Error ;
263 using Certificate = MbedTls::Certificate ;
264
265 ProfileImp( const LibraryImp & library_imp , bool is_server , const std::string & key_file ,
266 const std::string & cert_file , const std::string & ca_file ,
267 const std::string & default_peer_certificate_name , const std::string & default_peer_host_name ,
268 const std::string & profile_config ) ;
269 ~ProfileImp() override ;
270 const mbedtls_ssl_config * config() const ;
271 mbedtls_x509_crl * crl() const ;
272 void logAt( int level_out , std::string ) const ;
273 const std::string & defaultPeerCertificateName() const ;
274 const std::string & defaultPeerHostName() const ;
275 int authmode() const ;
276
277private: // overrides
278 std::unique_ptr<ProtocolImpBase> newProtocol( const std::string & , const std::string & ) const override ;
279
280public:
281 ProfileImp( const ProfileImp & ) = delete ;
282 ProfileImp( ProfileImp && ) = delete ;
283 ProfileImp & operator=( const ProfileImp & ) = delete ;
284 ProfileImp & operator=( ProfileImp && ) = delete ;
285
286private:
287 static void onDebug( void * , int , const char * , int , const char * ) ;
288 void doDebug( int , const char * , int , const char * ) ;
289
290private:
291 const LibraryImp & m_library_imp ;
292 const std::string m_default_peer_certificate_name ;
293 const std::string m_default_peer_host_name ;
294 mbedtls_ssl_config m_config ;
295 Key m_pk ;
296 Certificate m_certificate ;
297 Certificate m_ca_list ;
298 int m_authmode {0} ;
299 bool m_noisy {false} ;
300} ;
301
302//| \class GSsl::MbedTls::ProtocolImp
303/// An implementation of the GSsl::ProtocolImpBase interface for mbedtls.
304///
305class GSsl::MbedTls::ProtocolImp : public ProtocolImpBase
306{
307public:
308 using Result = Protocol::Result ;
309 using Context = MbedTls::Context ;
310 using Error = MbedTls::Error ;
311
312 ProtocolImp( const ProfileImp & , const std::string & , const std::string & ) ;
313 ~ProtocolImp() override ;
314
315 static int doSend( void * , const unsigned char * , std::size_t ) ;
316 static int doRecv( void * , unsigned char * , std::size_t ) ;
317 static int doRecvTimeout( void * , unsigned char * , std::size_t , uint32_t ) ;
318 const Profile & profile() const ;
319
320private: // overrides
321 Result connect( G::ReadWrite & ) override ;
322 Result accept( G::ReadWrite & ) override ;
323 Result read( char * buffer , std::size_t buffer_size_in , ssize_t & data_size_out ) override ;
324 Result write( const char * buffer , std::size_t data_size_in , ssize_t & data_size_out ) override ;
325 Result shutdown() override ;
326 std::string peerCertificate() const override ;
327 std::string peerCertificateChain() const override ;
328 std::string protocol() const override ;
329 std::string cipher() const override ;
330 bool verified() const override ;
331
332public:
333 ProtocolImp( const ProtocolImp & ) = delete ;
334 ProtocolImp( ProtocolImp && ) = delete ;
335 ProtocolImp & operator=( const ProtocolImp & ) = delete ;
336 ProtocolImp & operator=( ProtocolImp && ) = delete ;
337
338private:
339 Result convert( const char * , int , bool more = false ) ;
340 Result handshake() ;
341 std::string getPeerCertificate() ;
342 std::string verifyResultString( int ) ;
343
344private:
345 const ProfileImp & m_profile ;
346 G::ReadWrite * m_io {nullptr} ;
347 Context m_ssl ;
348 std::string m_peer_certificate ;
349 std::string m_peer_certificate_chain ;
350 bool m_verified {false} ;
351} ;
352
353//| \class GSsl::MbedTls::DigesterImp
354/// An implementation of the GSsl::DigesterImpBase interface for MbedTls.
355///
356class GSsl::MbedTls::DigesterImp : public GSsl::DigesterImpBase
357{
358public:
359 using Error = MbedTls::Error ;
360 DigesterImp( const std::string & , const std::string & , bool ) ;
361 ~DigesterImp() override ;
362
363private: // overrides
364 void add( std::string_view ) override ;
365 std::string value() override ;
366 std::string state() override ;
367 std::size_t blocksize() const noexcept override ;
368 std::size_t valuesize() const noexcept override ;
369 std::size_t statesize() const noexcept override ;
370
371public:
372 DigesterImp( const DigesterImp & ) = delete ;
373 DigesterImp( DigesterImp && ) = delete ;
374 DigesterImp & operator=( const DigesterImp & ) = delete ;
375 DigesterImp & operator=( DigesterImp && ) = delete ;
376
377private:
378 static void check_ret( int , const char * ) ;
379
380private:
381 enum class Type { Md5 , Sha1 , Sha256 } ;
382 Type m_hash_type{Type::Md5} ;
383 mbedtls_md5_context m_md5{} ;
384 mbedtls_sha1_context m_sha1{} ;
385 mbedtls_sha256_context m_sha256{} ;
386 std::size_t m_block_size{64U} ;
387 std::size_t m_value_size{16U} ;
388 std::size_t m_state_size{20U} ;
389} ;
390
391#endif
A base interface for GSsl::Digester pimple classes.
Definition: gssl.h:472
virtual std::string state()=0
Implements Digester::state().
virtual std::size_t blocksize() const noexcept=0
Implements Digester::blocksize().
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.
Definition: gssl.h:215
A base interface for GSsl::Library pimple classes.
Definition: gssl.h:385
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 a mbedtls_x509_crt structure.
Definition: gssl_mbedtls.h:56
Holds protocol version information, etc.
Definition: gssl_mbedtls.h:189
Holds a mbedtls_ssl_context structure.
Definition: gssl_mbedtls.h:124
An exception class for GSsl::MbedTls classes.
Definition: gssl_mbedtls.h:145
Holds a mbedtls_pk_context structure.
Definition: gssl_mbedtls.h:102
Holds a mbedtls_ctr_drbg_context structure.
Definition: gssl_mbedtls.h:80
An interface for reading a sensitive file and then overwriting its contents in memory.
Definition: gssl_mbedtls.h:159
A base interface for profile classes that work with concrete classes derived from GSsl::LibraryImpBas...
Definition: gssl.h:419
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().
A Path object represents a file system path.
Definition: gpath.h:82
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:50
An interface to an underlying TLS library.
TLS/SSL transport layer security classes.
Definition: gssl.h:36
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
STL namespace.