Added support for 3des with two and three keys.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5924 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
andrei 2014-11-24 14:28:05 +00:00
parent de6b5b9aaa
commit bf9261a33f
1 changed files with 107 additions and 16 deletions

View File

@ -152,7 +152,12 @@ public:
class DesCtrCipher : public Cipher
{
public:
DesCtrCipher();
enum {
Des,
Des3_2,
Des3_3
};
DesCtrCipher(const char* type);
virtual ~DesCtrCipher();
virtual unsigned int blockSize() const
{ return DES_KEY_SZ; }
@ -162,9 +167,15 @@ public:
virtual bool initVector(const void* vect, unsigned int len, Direction dir);
virtual bool encrypt(void* outData, unsigned int len, const void* inpData);
virtual bool decrypt(void* outData, unsigned int len, const void* inpData);
static bool initKey(const void* key,DES_key_schedule& k);
private:
DES_key_schedule m_key;
DES_key_schedule m_key1;
DES_key_schedule m_key2;
DES_key_schedule m_key3;
unsigned char m_initVector[DES_KEY_SZ];
int m_type;
bool m_keysSet;
static const TokenDict s_des[];
};
#endif
@ -206,6 +217,15 @@ static int s_index = -1;
static SSL_CTX* s_context = 0;
static OpenSSL __plugin;
#ifndef OPENSSL_NO_DES
const TokenDict DesCtrCipher::s_des[] = {
{ "des", Des },
{ "des3_2", Des3_2 },
{ "des3_3", Des3_3 },
{ 0, 0 }
};
#endif
class SslHandler : public MessageHandler
{
public:
@ -690,29 +710,66 @@ bool AesCfbCipher::decrypt(void* outData, unsigned int len, const void* inpData)
#endif
#ifndef OPENSSL_NO_DES
DesCtrCipher::DesCtrCipher()
DesCtrCipher::DesCtrCipher(const char* type)
: m_keysSet(false)
{
DES_cblock nativeDESKey;
DES_random_key(&nativeDESKey);
DES_set_key_checked(&nativeDESKey,&m_key);
DDebug(&__plugin,DebugAll,"DesCtrCipher::DesCtrCipher() key=%p [%p]",&m_key,this);
m_type = lookup(type,s_des,Des);
DDebug(&__plugin,DebugAll,"DesCtrCipher::DesCtrCipher() key=%p [%p]",&m_key1,this);
}
DesCtrCipher::~DesCtrCipher()
{
DDebug(&__plugin,DebugAll,"DesCtrCipher::~DesCtrCipher() key=%p [%p]",&m_key,this);
DDebug(&__plugin,DebugAll,"DesCtrCipher::~DesCtrCipher() key=%p [%p]",&m_key1,this);
}
bool DesCtrCipher::initKey(const void* key,DES_key_schedule& k)
{
DES_cblock nativeKey;
::memcpy(nativeKey,key,8);
DES_set_odd_parity(&nativeKey);
return 0 == DES_set_key_checked(&nativeKey,&k);
}
bool DesCtrCipher::setKey(const void* key, unsigned int len, Direction dir)
{
m_keysSet = false;
if (!(key && len))
return false;
DES_cblock nativeKey;
::memcpy(nativeKey,key,len);
bool lenOk = false;
uint8_t* buf = (uint8_t*)key;
DES_set_odd_parity(&nativeKey);
int r = DES_set_key_checked(&nativeKey,&m_key);
return r== 0;
switch (m_type) {
case Des:
if ((lenOk = (len == 8)))
m_keysSet = initKey(buf,m_key1);
break;
case Des3_2:
if ((lenOk = (len == 16)))
m_keysSet = initKey(buf,m_key1) && initKey(buf + 8,m_key2);
break;
case Des3_3:
if (len == 16) {
Debug(&__plugin,DebugAll,"Key length=%u too short for 3-key DES cipher, switching to 2-key DES cipher [%p]",
len,this);
m_keysSet = initKey(buf,m_key3);
} else if (len == 24) {
m_keysSet = initKey(buf + 16,m_key3);
} else // lenOk = false
break;
lenOk = true;
m_keysSet = m_keysSet && initKey(buf,m_key1) && initKey(buf + 8,m_key2);
break;
default:
Debug(&__plugin,DebugStub,"DesCtrCipher::setKey() Unknown cipher type '%s'",lookup(m_type,s_des));
return m_keysSet;
}
if (!lenOk) {
Debug(&__plugin,DebugMild,"Invalid key length %u for cipher type %s",
len,lookup(m_type,s_des));
return false;
}
return m_keysSet;
}
bool DesCtrCipher::initVector(const void* vect, unsigned int len, Direction dir)
@ -730,6 +787,10 @@ bool DesCtrCipher::initVector(const void* vect, unsigned int len, Direction dir)
bool DesCtrCipher::encrypt(void* outData, unsigned int len, const void* inpData)
{
if (!m_keysSet) {
Debug(&__plugin,DebugNote,"DesCtrCipher::encrypt() Please set the keys first! [%p]",this);
return false;
}
DDebug(&__plugin,DebugAll,"DesCtrCipher::encrypt(%p, %d. %p) [%p]",outData,len,inpData,this);
if (!(outData && len))
return false;
@ -739,12 +800,30 @@ bool DesCtrCipher::encrypt(void* outData, unsigned int len, const void* inpData)
}
if (!inpData)
inpData = outData;
DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key,(DES_cblock *)m_initVector,DES_ENCRYPT);
switch (m_type) {
case Des:
DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,(DES_cblock *)m_initVector,DES_ENCRYPT);
break;
case Des3_2:
DES_ede2_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,(DES_cblock *)m_initVector,DES_ENCRYPT);
break;
case Des3_3:
DES_ede3_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,&m_key3,(DES_cblock *)m_initVector,DES_ENCRYPT);
break;
default:
return false;
}
return true;
}
bool DesCtrCipher::decrypt(void* outData, unsigned int len, const void* inpData)
{
if (!m_keysSet) {
Debug(&__plugin,DebugNote,"DesCtrCipher::dencrypt() Please set the keys first! [%p]",this);
return false;
}
DDebug(&__plugin,DebugAll,"DesCtrCipher::decrypt(%p, %d. %p) [%p]",outData,len,inpData,this);
if (!(outData && len))
return false;
@ -754,7 +833,19 @@ bool DesCtrCipher::decrypt(void* outData, unsigned int len, const void* inpData)
}
if (!inpData)
inpData = outData;
DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key,(DES_cblock *)m_initVector,DES_DECRYPT);
switch (m_type) {
case Des:
DES_ncbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,(DES_cblock *)m_initVector,DES_DECRYPT);
break;
case Des3_2:
DES_ede2_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,(DES_cblock *)m_initVector,DES_DECRYPT);
break;
case Des3_3:
DES_ede3_cbc_encrypt((const unsigned char*)inpData,(unsigned char*)outData,len,&m_key1,&m_key2,&m_key3,(DES_cblock *)m_initVector,DES_DECRYPT);
break;
default:
return false;
}
return true;
}
#endif
@ -782,7 +873,7 @@ bool CipherHandler::received(Message& msg)
#ifndef OPENSSL_NO_DES
if (*name == "des_cbc") {
if (ppCipher)
*ppCipher = new DesCtrCipher();
*ppCipher = new DesCtrCipher(msg.getValue(YSTRING("type"),"des"));
return true;
}
#endif