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