1 /**
2 * openssl.cpp
3 * This file is part of the YATE Project http://YATE.null.ro
4 *
5 * OpenSSL based SSL/TLS socket support
6 *
7 * Yet Another Telephony Engine - a fully featured software PBX and IVR
8 * Copyright (C) 2004-2014 Null Team
9 *
10 * This software is distributed under multiple licenses;
11 * see the COPYING file in the main directory for licensing
12 * information for this specific distribution.
13 *
14 * This use of this software may be subject to additional restrictions.
15 * See the LEGAL file in the main directory for details.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #include <yatephone.h>
23
24 #include <string.h>
25
26 #include <openssl/opensslconf.h>
27 #include <openssl/ssl.h>
28 #include <openssl/rand.h>
29 #include <openssl/err.h>
30
31 #ifndef OPENSSL_NO_AES
32 #include <openssl/aes.h>
33 #ifdef NO_AESCTR
34 #include <openssl/modes.h>
35 #define AES_ctr128_encrypt(in,out,len,key,ivec,ecount,num) \
36 CRYPTO_ctr128_encrypt(in,out,len,key,ivec,ecount,num,(block128_f)AES_encrypt)
37 #endif
38 #endif
39
40 #ifndef OPENSSL_NO_DES
41 #include <openssl/des.h>
42 #endif
43
44 #ifdef USE_TLS_METHOD
45 #define CTX_METHOD ::TLS_method()
46 #else
47 #define CTX_METHOD ::SSLv23_method()
48 #endif
49
50 using namespace TelEngine;
51 namespace { // anonymous
52
53 #define MAKE_ERR(x) { #x, X509_V_ERR_##x }
54 static TokenDict s_verifyCodes[] = {
55 MAKE_ERR(UNABLE_TO_GET_ISSUER_CERT),
56 MAKE_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE),
57 MAKE_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY),
58 MAKE_ERR(CERT_SIGNATURE_FAILURE),
59 MAKE_ERR(CERT_NOT_YET_VALID),
60 MAKE_ERR(CERT_HAS_EXPIRED),
61 MAKE_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD),
62 MAKE_ERR(DEPTH_ZERO_SELF_SIGNED_CERT),
63 MAKE_ERR(SELF_SIGNED_CERT_IN_CHAIN),
64 MAKE_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY),
65 MAKE_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE),
66 MAKE_ERR(INVALID_CA),
67 MAKE_ERR(PATH_LENGTH_EXCEEDED),
68 MAKE_ERR(INVALID_PURPOSE),
69 MAKE_ERR(CERT_UNTRUSTED),
70 MAKE_ERR(CERT_REJECTED),
71 { 0, 0 }
72 };
73 #undef MAKE_ERR
74
75 static TokenDict s_verifyMode[] = {
76 // don't ask for a certificate, don't stop if verification fails
77 { "none", SSL_VERIFY_NONE },
78 // certificate is verified only if provided (a server always provides one)
79 { "peer", SSL_VERIFY_PEER },
80 // server only - verify client certificate only if provided and only once
81 { "only", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE },
82 // server only - client must provide a certificate at every (re)negotiation
83 { "must", SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT },
84 // server only - client must provide a certificate only at first negotiation
85 { "once", SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE },
86 { 0, 0 }
87 };
88
89 class SslContext : public String
90 {
91 public:
92 // Constructor. Build the context
93 SslContext(const char* name);
94 // Initialize certificate, key and domains. Check the key
95 // Return false on failure
96 bool init(const NamedList& params);
97 // Load a certificate and key. Check the key
98 bool loadCertificate(const String& cert, const String& key);
99 // Check if this context can be used for server sockets in a given domain
100 bool hasDomain(const String& domain);
101 // Add a comma separated list of domains to a buffer
102 void addDomains(String& buf);
103 // Release memory, free the context
104 virtual void destruct();
operator SSL_CTX*()105 inline operator SSL_CTX*()
106 { return m_context; }
107 protected:
108 SSL_CTX* m_context;
109 ObjList m_domains;
110 };
111
112 class SslSocket : public Socket, public Mutex
113 {
114 public:
115 SslSocket(SOCKET handle, bool server, int verify, SslContext* context = 0);
116 virtual ~SslSocket();
117 virtual bool terminate();
118 virtual bool valid();
119 virtual int writeData(const void* buffer, int length);
120 virtual int readData(void* buffer, int length);
121 void onInfo(int where, int retVal);
ssl() const122 inline SSL* ssl() const
123 { return m_ssl; }
124 private:
125 int sslError(int retcode);
126 SSL* m_ssl;
127 };
128
129 #ifndef OPENSSL_NO_AES
130 // AES Counter Mode
131 class AesCtrCipher : public Cipher
132 {
133 public:
134 AesCtrCipher();
135 virtual ~AesCtrCipher();
blockSize() const136 virtual unsigned int blockSize() const
137 { return AES_BLOCK_SIZE; }
initVectorSize() const138 virtual unsigned int initVectorSize() const
139 { return AES_BLOCK_SIZE; }
140 virtual bool setKey(const void* key, unsigned int len, Direction dir);
141 virtual bool initVector(const void* vect, unsigned int len, Direction dir);
142 virtual bool encrypt(void* outData, unsigned int len, const void* inpData);
143 virtual bool decrypt(void* outData, unsigned int len, const void* inpData);
144 protected:
145 AES_KEY* m_key;
146 unsigned char m_initVector[AES_BLOCK_SIZE];
147 };
148
149 //AES - Cipher Feedback Mode
150 class AesCfbCipher : public AesCtrCipher
151 {
152 public:
153 AesCfbCipher();
154 virtual ~AesCfbCipher();
155 virtual bool encrypt(void* outData, unsigned int len, const void* inpData);
156 virtual bool decrypt(void* outData, unsigned int len, const void* inpData);
157 };
158
159 #endif
160
161 #ifndef OPENSSL_NO_DES
162 // CBC-DES Cipher - Cipher-Block Chaining Mode
163 class DesCtrCipher : public Cipher
164 {
165 public:
166 enum {
167 Des,
168 Des3_2,
169 Des3_3
170 };
171 DesCtrCipher(const char* type);
172 virtual ~DesCtrCipher();
blockSize() const173 virtual unsigned int blockSize() const
174 { return DES_KEY_SZ; }
initVectorSize() const175 virtual unsigned int initVectorSize() const
176 { return DES_KEY_SZ; }
177 virtual bool setKey(const void* key, unsigned int len, Direction dir);
178 virtual bool initVector(const void* vect, unsigned int len, Direction dir);
179 virtual bool encrypt(void* outData, unsigned int len, const void* inpData);
180 virtual bool decrypt(void* outData, unsigned int len, const void* inpData);
181 static bool initKey(const void* key,DES_key_schedule& k);
182 private:
183 DES_key_schedule m_key1;
184 DES_key_schedule m_key2;
185 DES_key_schedule m_key3;
186 unsigned char m_initVector[DES_KEY_SZ];
187 int m_type;
188 bool m_keysSet;
189 static const TokenDict s_des[];
190 };
191 #endif
192
193 class CipherHandler : public MessageHandler
194 {
195 public:
CipherHandler()196 inline CipherHandler()
197 : MessageHandler("engine.cipher")
198 { }
199 virtual bool received(Message& msg);
200 };
201
202 class SslHandler;
203
204 class OpenSSL : public Module
205 {
206 public:
207 OpenSSL();
208 ~OpenSSL();
209 virtual void initialize();
210 // Find a context by name or domain
211 // This method is not thread safe. The caller must lock the plugin
212 // until the returned context is not used anymore
213 SslContext* findContext(const String& token, bool byDomain = false) const;
214 // Find a context from 'context' or 'domain' parameters
215 // This method is not thread safe
216 SslContext* findContext(Message& msg) const;
217 protected:
218 virtual void statusParams(String& str);
219 virtual void statusDetail(String& str);
220
221 SslHandler* m_handler;
222 ObjList m_contexts; // Server contexts list
223 String m_statusCmd; // Module status command
224 };
225
226
227 static int s_index = -1;
228 static SSL_CTX* s_context = 0;
229 static OpenSSL __plugin;
230
231 #ifndef OPENSSL_NO_DES
232 const TokenDict DesCtrCipher::s_des[] = {
233 { "des", Des },
234 { "des3_2", Des3_2 },
235 { "des3_3", Des3_3 },
236 { 0, 0 }
237 };
238 #endif
239
240 class SslHandler : public MessageHandler
241 {
242 public:
SslHandler()243 inline SslHandler()
244 : MessageHandler("socket.ssl",100,__plugin.name())
245 { }
246 virtual bool received(Message& msg);
247 };
248
249
250 // Attempt to add randomness from system time when called
addRand(u_int64_t usec)251 static void addRand(u_int64_t usec)
252 {
253 // a rough estimation of 2 bytes of entropy
254 ::RAND_add(&usec,sizeof(usec),2);
255 }
256
257 // Retrieve SslSocket from SSL structure
sslSocket(const SSL * ssl)258 static inline SslSocket* sslSocket(const SSL* ssl)
259 {
260 if (ssl && s_index >= 0)
261 return static_cast<SslSocket*>(::SSL_get_ex_data(const_cast<SSL*>(ssl),s_index));
262 return 0;
263 }
264
265 // Callback function called from OpenSSL for state changes and alerts
infoCallback(const SSL * ssl,int where,int retVal)266 void infoCallback(const SSL* ssl, int where, int retVal)
267 {
268 SslSocket* sock = sslSocket(ssl);
269 if (sock) {
270 if (sock->ssl() == ssl)
271 sock->onInfo(where,retVal);
272 else
273 Debug(&__plugin,DebugFail,"Mismatched session %p [%p]",ssl,sock);
274 }
275 }
276
277 #ifdef DEBUG
278 // Callback function called from OpenSSL for protocol messages
msgCallback(int write,int version,int content_type,const void * buf,size_t len,SSL * ssl,void * arg)279 void msgCallback(int write, int version, int content_type, const void* buf,
280 size_t len, SSL* ssl, void* arg)
281 {
282 SslSocket* sock = sslSocket(ssl);
283 if (!sock)
284 return;
285 if (sock->ssl() == ssl)
286 Debug(&__plugin,DebugAll,
287 "%s SSL message: version=%d content_type=%d buf=%p len=%u [%p]",
288 write ? "Sent" : "Received",version,content_type,buf,(unsigned int)len,
289 sock);
290 else
291 Debug(&__plugin,DebugFail,"msgCallback: Mismatched session %p [%p]",ssl,sock);
292 }
293 #endif
294
295
SslContext(const char * name)296 SslContext::SslContext(const char* name)
297 : String(name),
298 m_context(0)
299 {
300 m_context = ::SSL_CTX_new(CTX_METHOD);
301 SSL_CTX_set_info_callback(m_context,infoCallback);
302 #ifdef DEBUG
303 SSL_CTX_set_msg_callback(m_context,msgCallback);
304 #endif
305 }
306
307 // Initialize certificate, key and domains. Check the key
308 // Return false on failure
init(const NamedList & params)309 bool SslContext::init(const NamedList& params)
310 {
311 // Load certificate and key. Check them
312 if (!loadCertificate(params["certificate"],params["key"]))
313 return false;
314 // Load domains
315 m_domains.clear();
316 String* d = params.getParam("domains");
317 if (d) {
318 ObjList* list = d->split(',',false);
319 for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
320 String* s = static_cast<String*>(o->get());
321 s->trimBlanks();
322 if (s->null())
323 continue;
324 if (s->startsWith("*") && (s->length() < 3 || (*s)[1] != '.')) {
325 Debug(&__plugin,DebugNote,"Context '%s' ignoring invalid domain='%s'",
326 c_str(),s->c_str());
327 continue;
328 }
329 m_domains.append(new String(s->toLower()));
330 }
331 TelEngine::destruct(list);
332 DDebug(&__plugin,DebugAll,"Context '%s' loaded domains=%s",
333 c_str(),d->safe());
334 }
335 return true;
336 }
337
338 // Load a certificate and key. Check the key
loadCertificate(const String & c,const String & k)339 bool SslContext::loadCertificate(const String& c, const String& k)
340 {
341 String cert;
342 if (c) {
343 cert << Engine::configPath();
344 if (cert && !cert.endsWith(Engine::pathSeparator()))
345 cert << Engine::pathSeparator();
346 cert << c;
347 }
348 String key;
349 if (k) {
350 key << Engine::configPath();
351 if (key && !key.endsWith(Engine::pathSeparator()))
352 key << Engine::pathSeparator();
353 key << k;
354 }
355 else
356 key = cert;
357 if (!::SSL_CTX_use_certificate_chain_file(m_context,cert)) {
358 unsigned long err = ::ERR_get_error();
359 Debug(&__plugin,DebugWarn,
360 "Context '%s' failed to load certificate from '%s' '%s'",
361 c_str(),cert.c_str(),::ERR_error_string(err,0));
362 return false;
363 }
364 if (!::SSL_CTX_use_PrivateKey_file(m_context,key,SSL_FILETYPE_PEM)) {
365 unsigned long err = ::ERR_get_error();
366 Debug(&__plugin,DebugWarn,
367 "Context '%s' failed to load key from '%s' '%s'",
368 c_str(),key.c_str(),::ERR_error_string(err,0));
369 return false;
370 }
371 if (!::SSL_CTX_check_private_key(m_context)) {
372 unsigned long err = ::ERR_get_error();
373 Debug(&__plugin,DebugWarn,
374 "Context '%s' certificate='%s' or key='%s' are invalid '%s'",
375 c_str(),cert.c_str(),key.c_str(),::ERR_error_string(err,0));
376 return false;
377 }
378 DDebug(&__plugin,DebugAll,"Context '%s' loaded certificate='%s' key='%s'",
379 c_str(),cert.c_str(),key.c_str());
380 return true;
381 }
382
383 // Check if this context can be used for server sockets in a given domain
hasDomain(const String & domain)384 bool SslContext::hasDomain(const String& domain)
385 {
386 for (ObjList* o = m_domains.skipNull(); o; o = o->skipNext()) {
387 String* s = static_cast<String*>(o->get());
388 if (*s == domain ||
389 ((*s)[0] == '*' && domain.endsWith(s->c_str() + 1)))
390 return true;
391 }
392 return false;
393 }
394
395 // Add a comma separated list of domains to a buffer
addDomains(String & buf)396 void SslContext::addDomains(String& buf)
397 {
398 bool notFirst = false;
399 for (ObjList* o = m_domains.skipNull(); o; o = o->skipNext()) {
400 if (notFirst)
401 buf << ",";
402 else
403 notFirst = true;
404 buf << (static_cast<String*>(o->get()))->c_str();
405 }
406 }
407
408 // Release memory, free the context
destruct()409 void SslContext::destruct()
410 {
411 ::SSL_CTX_free(m_context);
412 String::destruct();
413 }
414
415
416 // Create a SSL socket from a regular socket handle
SslSocket(SOCKET handle,bool server,int verify,SslContext * context)417 SslSocket::SslSocket(SOCKET handle, bool server, int verify, SslContext* context)
418 : Socket(handle), Mutex(false,"SslSocket"),
419 m_ssl(0)
420 {
421 DDebug(&__plugin,DebugAll,"SslSocket::SslSocket(%d,%s,%s,%s) [%p]",
422 handle,String::boolText(server),lookup(verify,s_verifyMode,"unknown"),
423 context ? context->c_str() : "",this);
424 if (Socket::valid()) {
425 m_ssl = ::SSL_new(context ? *context : s_context);
426 if (!m_ssl) {
427 Debug(&__plugin,DebugNote,"SslSocket::SslSocket(%d) could not create SSL context, terminating [%p]",
428 handle,this);
429 Socket::terminate();
430 return;
431 }
432 if (s_index >= 0)
433 ::SSL_set_ex_data(m_ssl,s_index,this);
434 ::SSL_set_verify(m_ssl,verify,0);
435 ::SSL_set_fd(m_ssl,handle);
436 BIO* bio = ::SSL_get_rbio(m_ssl);
437 if (!(bio && BIO_set_close(bio,BIO_NOCLOSE)))
438 Debug(&__plugin,DebugCrit,"SslSocket::SslSocket(%d) no BIO or cannot set NOCLOSE [%p]",
439 handle,this);
440 if (server)
441 ::SSL_set_accept_state(m_ssl);
442 else
443 ::SSL_set_connect_state(m_ssl);
444 }
445 }
446
447 // Destructor, clean up early
~SslSocket()448 SslSocket::~SslSocket()
449 {
450 DDebug(&__plugin,DebugAll,"SslSocket::~SslSocket() handle=%d [%p]",handle(),this);
451 clearFilters();
452 terminate();
453 }
454
455 // Terminate the socket and the SSL session around it
terminate()456 bool SslSocket::terminate()
457 {
458 lock();
459 if (m_ssl) {
460 if (s_index >= 0)
461 ::SSL_set_ex_data(m_ssl,s_index,0);
462 ::SSL_shutdown(m_ssl);
463 ::SSL_free(m_ssl);
464 m_ssl = 0;
465 // SSL_free also destroys the BIO
466 }
467 unlock();
468 return Socket::terminate();
469 }
470
471 // Check if the socket is valid
valid()472 bool SslSocket::valid()
473 {
474 return m_ssl && Socket::valid();
475 }
476
477 // Write unencrypted data through the SSL stream
writeData(const void * buffer,int length)478 int SslSocket::writeData(const void* buffer, int length)
479 {
480 if (!buffer)
481 length = 0;
482 Lock lock(this);
483 if (!m_ssl) {
484 m_error = EINVAL;
485 return socketError();
486 }
487 return sslError(::SSL_write(m_ssl,buffer,length));
488 }
489
490 // Read decrypted data from the SSL stream
readData(void * buffer,int length)491 int SslSocket::readData(void* buffer, int length)
492 {
493 if (!buffer)
494 length = 0;
495 Lock lock(this);
496 if (!m_ssl) {
497 m_error = EINVAL;
498 return socketError();
499 }
500 return sslError(::SSL_read(m_ssl,buffer,length));
501 }
502
503 // Deal with the various SSL error codes
sslError(int retcode)504 int SslSocket::sslError(int retcode)
505 {
506 if (retcode <= 0) {
507 switch (::SSL_get_error(m_ssl,retcode)) {
508 case SSL_ERROR_ZERO_RETURN:
509 clearError();
510 retcode = 0;
511 break;
512 case SSL_ERROR_WANT_READ:
513 case SSL_ERROR_WANT_WRITE:
514 case SSL_ERROR_WANT_CONNECT:
515 case SSL_ERROR_WANT_ACCEPT:
516 m_error = EAGAIN;
517 retcode = socketError();
518 break;
519 case SSL_ERROR_SYSCALL:
520 copyError();
521 break;
522 default:
523 m_error = EINVAL;
524 retcode = socketError();
525 break;
526 }
527 #ifdef DEBUG
528 if (!canRetry())
529 Debug(&__plugin,DebugNote,"SslSocket error='%s' state='%s' [%p]",
530 ERR_error_string(ERR_get_error(),0),SSL_state_string_long(m_ssl),this);
531 #endif
532 }
533 else
534 clearError();
535 return retcode;
536 }
537
538 // Callback function called from OpenSSL for state changes and alerts
onInfo(int where,int retVal)539 void SslSocket::onInfo(int where, int retVal)
540 {
541 #ifdef DEBUG
542 if (where & SSL_CB_LOOP)
543 Debug(&__plugin,DebugAll,"State %s [%p]",SSL_state_string_long(m_ssl),this);
544 #endif
545 if ((where & SSL_CB_EXIT) && (retVal == 0))
546 Debug(&__plugin,DebugMild,"Failed %s [%p]",SSL_state_string_long(m_ssl),this);
547 if (where & SSL_CB_ALERT)
548 Debug(&__plugin,DebugMild,"Alert %s: %s [%p]",
549 SSL_alert_type_string_long(retVal),
550 SSL_alert_desc_string_long(retVal),this);
551 if (where & SSL_CB_HANDSHAKE_DONE) {
552 long verify = ::SSL_get_verify_result(m_ssl);
553 if (verify != X509_V_OK) {
554 // handshake succeeded but the certificate has problems
555 const char* error = lookup(verify,s_verifyCodes);
556 Debug(&__plugin,DebugWarn,"Certificate verify error %ld%s%s [%p]",
557 verify,error ? ": " : "",c_safe(error),this);
558 }
559 }
560 }
561
562
563 // Handler for the socket.ssl message - turns regular sockets into SSL
received(Message & msg)564 bool SslHandler::received(Message& msg)
565 {
566 if (msg.getBoolValue("test")) {
567 if (!msg.getBoolValue("server"))
568 return true;
569 Lock lock(__plugin);
570 return 0 != __plugin.findContext(msg);
571 }
572 addRand(msg.msgTime());
573 Socket** ppSock = static_cast<Socket**>(msg.userObject(YATOM("Socket*")));
574 if (!ppSock) {
575 Debug(&__plugin,DebugCrit,"SslHandler: No pointer to Socket");
576 return false;
577 }
578 Socket* pSock = *ppSock;
579 if (!pSock) {
580 Debug(&__plugin,DebugCrit,"SslHandler: NULL Socket pointer");
581 return false;
582 }
583 if (!pSock->valid()) {
584 Debug(&__plugin,DebugWarn,"SslHandler: Invalid Socket");
585 return false;
586 }
587 SslSocket* sSock = 0;
588 if (msg.getBoolValue("server",false)) {
589 Lock lock(&__plugin);
590 SslContext* c = __plugin.findContext(msg);
591 if (!c)
592 return false;
593 sSock = new SslSocket(pSock->handle(),true,
594 msg.getIntValue("verify",s_verifyMode,SSL_VERIFY_NONE),c);
595 }
596 else {
597 const String& cert = msg["certificate"];
598 SslContext* c = cert ? new SslContext(msg) : 0;
599 if (!c || c->loadCertificate(cert,msg["key"]))
600 sSock = new SslSocket(pSock->handle(),false,
601 msg.getIntValue("verify",s_verifyMode,SSL_VERIFY_NONE),c);
602 TelEngine::destruct(c);
603 }
604 if (!(sSock && sSock->valid())) {
605 if (sSock) {
606 Debug(&__plugin,DebugWarn,"SslHandler: Invalid SSL Socket");
607 // detach and destroy new socket, preserve old one
608 sSock->detach();
609 delete sSock;
610 }
611 return false;
612 }
613 // replace socket, detach and destroy old one
614 *ppSock = sSock;
615 pSock->detach();
616 delete pSock;
617 return true;
618 }
619
620
621 #ifndef OPENSSL_NO_AES
AesCtrCipher()622 AesCtrCipher::AesCtrCipher()
623 : m_key(0)
624 {
625 m_key = new AES_KEY;
626 DDebug(&__plugin,DebugAll,"AesCtrCipher::AesCtrCipher() key=%p [%p]",m_key,this);
627 }
628
~AesCtrCipher()629 AesCtrCipher::~AesCtrCipher()
630 {
631 DDebug(&__plugin,DebugAll,"AesCtrCipher::~AesCtrCipher() key=%p [%p]",m_key,this);
632 delete m_key;
633 }
634
setKey(const void * key,unsigned int len,Direction dir)635 bool AesCtrCipher::setKey(const void* key, unsigned int len, Direction dir)
636 {
637 if (!(key && len && m_key))
638 return false;
639 // AES_ctr128_encrypt is its own inverse
640 return 0 == AES_set_encrypt_key((const unsigned char*)key,len*8,m_key);
641 }
642
initVector(const void * vect,unsigned int len,Direction dir)643 bool AesCtrCipher::initVector(const void* vect, unsigned int len, Direction dir)
644 {
645 if (len && !vect)
646 return false;
647 if (len > AES_BLOCK_SIZE)
648 len = AES_BLOCK_SIZE;
649 if (len < AES_BLOCK_SIZE)
650 ::memset(m_initVector,0,AES_BLOCK_SIZE);
651 if (len)
652 ::memcpy(m_initVector,vect,len);
653 return true;
654 }
655
encrypt(void * outData,unsigned int len,const void * inpData)656 bool AesCtrCipher::encrypt(void* outData, unsigned int len, const void* inpData)
657 {
658 if (!(outData && len))
659 return false;
660 if (!inpData)
661 inpData = outData;
662 unsigned int num = 0;
663 unsigned char eCountBuf[AES_BLOCK_SIZE];
664 AES_ctr128_encrypt(
665 (const unsigned char*)inpData,
666 (unsigned char*)outData,
667 len,
668 m_key,
669 m_initVector,
670 eCountBuf,
671 &num);
672 return true;
673 }
674
decrypt(void * outData,unsigned int len,const void * inpData)675 bool AesCtrCipher::decrypt(void* outData, unsigned int len, const void* inpData)
676 {
677 // AES_ctr128_encrypt is its own inverse
678 return encrypt(outData,len,inpData);
679 }
680
AesCfbCipher()681 AesCfbCipher::AesCfbCipher()
682 {
683 DDebug(&__plugin,DebugAll,"AesCfbCipher::AesCfbCipher() key=%p [%p]",m_key,this);
684 }
685
~AesCfbCipher()686 AesCfbCipher::~AesCfbCipher()
687 {
688 DDebug(&__plugin,DebugAll,"AesCfbCipher::~AesCfbCipher() key=%p [%p]",m_key,this);
689 }
690
encrypt(void * outData,unsigned int len,const void * inpData)691 bool AesCfbCipher::encrypt(void* outData, unsigned int len, const void* inpData)
692 {
693 if (!(outData && len))
694 return false;
695 if (!inpData)
696 inpData = outData;
697 int num = 0;
698 AES_cfb128_encrypt(
699 (const unsigned char*)inpData,
700 (unsigned char*)outData,
701 len,
702 m_key,
703 m_initVector,
704 &num,
705 AES_ENCRYPT);
706 return true;
707 }
708
decrypt(void * outData,unsigned int len,const void * inpData)709 bool AesCfbCipher::decrypt(void* outData, unsigned int len, const void* inpData)
710 {
711 if (!(outData && len))
712 return false;
713 if (!inpData)
714 inpData = outData;
715 int num = 0;
716 AES_cfb128_encrypt(
717 (const unsigned char*)inpData,
718 (unsigned char*)outData,
719 len,
720 m_key,
721 m_initVector,
722 &num,
723 AES_DECRYPT);
724 return true;
725 }
726
727 #endif
728
729 #ifndef OPENSSL_NO_DES
DesCtrCipher(const char * type)730 DesCtrCipher::DesCtrCipher(const char* type)
731 : m_keysSet(false)
732 {
733 m_type = lookup(type,s_des,Des);
734 DDebug(&__plugin,DebugAll,"DesCtrCipher::DesCtrCipher() key=%p [%p]",&m_key1,this);
735 }
736
~DesCtrCipher()737 DesCtrCipher::~DesCtrCipher()
738 {
739 DDebug(&__plugin,DebugAll,"DesCtrCipher::~DesCtrCipher() key=%p [%p]",&m_key1,this);
740 }
741
initKey(const void * key,DES_key_schedule & k)742 bool DesCtrCipher::initKey(const void* key,DES_key_schedule& k)
743 {
744 DES_cblock nativeKey;
745 ::memcpy(nativeKey,key,8);
746
747 DES_set_odd_parity(&nativeKey);
748 return 0 == DES_set_key_checked(&nativeKey,&k);
749 }
750
setKey(const void * key,unsigned int len,Direction dir)751 bool DesCtrCipher::setKey(const void* key, unsigned int len, Direction dir)
752 {
753 m_keysSet = false;
754 if (!(key && len))
755 return false;
756 bool lenOk = false;
757 uint8_t* buf = (uint8_t*)key;
758
759 switch (m_type) {
760 case Des:
761 if ((lenOk = (len == 8)))
762 m_keysSet = initKey(buf,m_key1);
763 break;
764 case Des3_2:
765 if ((lenOk = (len == 16)))
766 m_keysSet = initKey(buf,m_key1) && initKey(buf + 8,m_key2);
767 break;
768 case Des3_3:
769 if (len == 16) {
770 Debug(&__plugin,DebugAll,"Key length=%u too short for 3-key DES cipher, switching to 2-key DES cipher [%p]",
771 len,this);
772 m_keysSet = initKey(buf,m_key3);
773 } else if (len == 24) {
774 m_keysSet = initKey(buf + 16,m_key3);
775 } else // lenOk = false
776 break;
777 lenOk = true;
778 m_keysSet = m_keysSet && initKey(buf,m_key1) && initKey(buf + 8,m_key2);
779 break;
780 default:
781 Debug(&__plugin,DebugStub,"DesCtrCipher::setKey() Unknown cipher type '%s'",lookup(m_type,s_des));
782 return m_keysSet;
783 }
784 if (!lenOk) {
785 Debug(&__plugin,DebugMild,"Invalid key length %u for cipher type %s",
786 len,lookup(m_type,s_des));
787 return false;
788 }
789 return m_keysSet;
790 }
791
initVector(const void * vect,unsigned int len,Direction dir)792 bool DesCtrCipher::initVector(const void* vect, unsigned int len, Direction dir)
793 {
794 if (len && !vect)
795 return false;
796 if (len > DES_KEY_SZ)
797 len = DES_KEY_SZ;
798 if (len < DES_KEY_SZ)
799 ::memset(m_initVector,0,DES_KEY_SZ);
800 if (len)
801 ::memcpy(m_initVector,vect,len);
802 return true;
803 }
804
encrypt(void * outData,unsigned int len,const void * inpData)805 bool DesCtrCipher::encrypt(void* outData, unsigned int len, const void* inpData)
806 {
807 if (!m_keysSet) {
808 Debug(&__plugin,DebugNote,"DesCtrCipher::encrypt() Please set the keys first! [%p]",this);
809 return false;
810 }
811 DDebug(&__plugin,DebugAll,"DesCtrCipher::encrypt(%p, %d. %p) [%p]",outData,len,inpData,this);
812 if (!(outData && len))
813 return false;
814 if (len % 8 != 0) {
815 Debug(&__plugin,DebugWarn,"DesCtrCipher::encrypt() - length of data block to be encrypted is not a multiple of 8, memory corruption possible - encryption aborted");
816 return false;
817 }
818 if (!inpData)
819 inpData = outData;
820
821 switch (m_type) {
822 case Des:
823 DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,(DES_cblock *)m_initVector,DES_ENCRYPT);
824 break;
825 case Des3_2:
826 DES_ede2_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,(DES_cblock *)m_initVector,DES_ENCRYPT);
827 break;
828 case Des3_3:
829 DES_ede3_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,&m_key3,(DES_cblock *)m_initVector,DES_ENCRYPT);
830 break;
831 default:
832 return false;
833 }
834 return true;
835 }
836
decrypt(void * outData,unsigned int len,const void * inpData)837 bool DesCtrCipher::decrypt(void* outData, unsigned int len, const void* inpData)
838 {
839 if (!m_keysSet) {
840 Debug(&__plugin,DebugNote,"DesCtrCipher::dencrypt() Please set the keys first! [%p]",this);
841 return false;
842 }
843
844 DDebug(&__plugin,DebugAll,"DesCtrCipher::decrypt(%p, %d. %p) [%p]",outData,len,inpData,this);
845 if (!(outData && len))
846 return false;
847 if (len % 8 != 0) {
848 Debug(&__plugin,DebugWarn,"DesCtrCipher::decrypt() - length of data block to be decrypted is not a multiple of 8, memory corruption possible - decryption aborted");
849 return false;
850 }
851 if (!inpData)
852 inpData = outData;
853 switch (m_type) {
854 case Des:
855 DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,(DES_cblock *)m_initVector,DES_DECRYPT);
856 break;
857 case Des3_2:
858 DES_ede2_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,(DES_cblock *)m_initVector,DES_DECRYPT);
859 break;
860 case Des3_3:
861 DES_ede3_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,&m_key3,(DES_cblock *)m_initVector,DES_DECRYPT);
862 break;
863 default:
864 return false;
865 }
866 return true;
867 }
868 #endif
869
870 // Handler for the engine.cipher message - Cipher Factory
received(Message & msg)871 bool CipherHandler::received(Message& msg)
872 {
873 addRand(msg.msgTime());
874 const String* name = msg.getParam("cipher");
875 if (!name)
876 return false;
877 Cipher** ppCipher = static_cast<Cipher**>(msg.userObject(YATOM("Cipher*")));
878 #ifndef OPENSSL_NO_AES
879 if (*name == "aes_ctr") {
880 if (ppCipher)
881 *ppCipher = new AesCtrCipher();
882 return true;
883 }
884 if (*name == "aes_cfb") {
885 if (ppCipher)
886 *ppCipher = new AesCfbCipher();
887 return true;
888 }
889 #endif
890 #ifndef OPENSSL_NO_DES
891 if (*name == "des_cbc") {
892 if (ppCipher)
893 *ppCipher = new DesCtrCipher(msg.getValue(YSTRING("type"),"des"));
894 return true;
895 }
896 #endif
897 return false;
898 }
899
900
OpenSSL()901 OpenSSL::OpenSSL()
902 : Module("openssl","misc",true),
903 m_handler(0)
904 {
905 Output("Loaded module OpenSSL - based on " OPENSSL_VERSION_TEXT);
906 m_statusCmd << "status " << name();
907 }
908
~OpenSSL()909 OpenSSL::~OpenSSL()
910 {
911 Output("Unloading module OpenSSL");
912 ::SSL_CTX_free(s_context);
913 }
914
initialize()915 void OpenSSL::initialize()
916 {
917 Output("Initializing module OpenSSL");
918 Configuration cfg(Engine::configFile("openssl"));
919 if (!m_handler) {
920 setup();
921 #ifndef NO_LOAD_ERR
922 ::SSL_load_error_strings();
923 ::SSL_library_init();
924 #endif
925 addRand(Time::now());
926 s_index = ::SSL_get_ex_new_index(0,const_cast<char*>("TelEngine::SslSocket"),0,0,0);
927 s_context = ::SSL_CTX_new(CTX_METHOD);
928 SSL_CTX_set_info_callback(s_context,infoCallback); // macro - no ::
929 m_handler = new SslHandler;
930 Engine::install(m_handler);
931 #if !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_DES)
932 Engine::install(new CipherHandler);
933 #endif
934 }
935
936 lock();
937 // Load server contexts
938 unsigned int n = cfg.sections();
939 for (unsigned int i = 0; i < n; i++) {
940 NamedList* p = cfg.getSection(i);
941 if (!p || *p == "general" || !p->c_str())
942 continue;
943 SslContext* context = findContext(*p);
944 if (!p->getBoolValue("enable",true)) {
945 if (context) {
946 DDebug(this,DebugAll,"Removing disabled context '%s'",context->c_str());
947 m_contexts.remove(context);
948 }
949 continue;
950 }
951 if (!context)
952 context = new SslContext(*p);
953 if (context->init(*p)) {
954 if (!findContext(*p)) {
955 m_contexts.append(context);
956 DDebug(this,DebugAll,"Added context '%s'",context->c_str());
957 }
958 }
959 else {
960 if (findContext(*p)) {
961 DDebug(this,DebugAll,"Removing invalid context '%s'",context->c_str());
962 m_contexts.remove(context);
963 }
964 else {
965 DDebug(this,DebugAll,"Ignoring invalid context '%s'",context->c_str());
966 TelEngine::destruct(context);
967 }
968 }
969 }
970 unlock();
971 }
972
973 // Find a context by name or domain
findContext(const String & token,bool byDomain) const974 SslContext* OpenSSL::findContext(const String& token, bool byDomain) const
975 {
976 if (!byDomain) {
977 ObjList* o = m_contexts.find(token);
978 return o ? static_cast<SslContext*>(o->get()) : 0;
979 }
980 for (ObjList* o = m_contexts.skipNull(); o; o = o->skipNext()) {
981 SslContext* c = static_cast<SslContext*>(o->get());
982 if (c->hasDomain(token))
983 return c;
984 }
985 return 0;
986 }
987
988 // Find a context from 'context' or 'domain' parameters
findContext(Message & msg) const989 SslContext* OpenSSL::findContext(Message& msg) const
990 {
991 SslContext* c = 0;
992 const String& context = msg["context"];
993 String domain;
994 if (context)
995 c = __plugin.findContext(context);
996 if (!c) {
997 domain = msg["domain"];
998 if (domain)
999 c = __plugin.findContext(domain.toLower(),true);
1000 }
1001 if (c)
1002 return c;
1003 Debug(this,DebugWarn,
1004 "SslHandler: Unable to find a server context for context=%s or domain=%s",
1005 context.safe(),domain.safe());
1006 return 0;
1007 }
1008
statusParams(String & str)1009 void OpenSSL::statusParams(String& str)
1010 {
1011 Lock lock(this);
1012 str << "contexts=" << m_contexts.count();
1013 }
1014
statusDetail(String & str)1015 void OpenSSL::statusDetail(String& str)
1016 {
1017 Lock lock(this);
1018 for (ObjList* o = m_contexts.skipNull(); o; o = o->skipNext()) {
1019 SslContext* c = static_cast<SslContext*>(o->get());
1020 str.append(c->c_str(),";");
1021 str << "=";
1022 c->addDomains(str);
1023 }
1024 }
1025
1026 }; // anonymous namespace
1027
1028 /* vi: set ts=8 sw=4 sts=4 noet: */
1029