blob: f57e871e4c2cdb96672a59255c184ade08a9d90d [file] [log] [blame]
/*
Copyright (C) 2006-2013 Werner Dittmann
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
*/
#include <crypto/aesCFB.h>
#include <crypto/twoCFB.h>
#include <libzrtpcpp/ZrtpConfigure.h>
#include <libzrtpcpp/ZrtpTextData.h>
AlgorithmEnum::AlgorithmEnum(const AlgoTypes type, const char* name,
int32_t klen, const char* ra, encrypt_t en,
decrypt_t de, SrtpAlgorithms alId):
algoType(type) , algoName(name), keyLen(klen), readable(ra), encrypt(en),
decrypt(de), algoId(alId) {
}
AlgorithmEnum::~AlgorithmEnum()
{
}
const char* AlgorithmEnum::getName() {
return algoName.c_str();
}
const char* AlgorithmEnum::getReadable() {
return readable.c_str();
}
int AlgorithmEnum::getKeylen() {
return keyLen;
}
SrtpAlgorithms AlgorithmEnum::getAlgoId() {
return algoId;
}
encrypt_t AlgorithmEnum::getEncrypt() {
return encrypt;
}
decrypt_t AlgorithmEnum::getDecrypt() {
return decrypt;
}
AlgoTypes AlgorithmEnum::getAlgoType() {
return algoType;
}
bool AlgorithmEnum::isValid() {
return (algoType != Invalid);
}
static AlgorithmEnum invalidAlgo(Invalid, "", 0, "", NULL, NULL, None);
EnumBase::EnumBase(AlgoTypes a) : algoType(a) {
}
EnumBase::~EnumBase() {}
void EnumBase::insert(const char* name) {
if (!name)
return;
AlgorithmEnum* e = new AlgorithmEnum(algoType, name, 0, "", NULL, NULL, None);
algos.push_back(e);
}
void EnumBase::insert(const char* name, int32_t klen, const char* ra,
encrypt_t enc, decrypt_t dec, SrtpAlgorithms alId) {
if (!name)
return;
AlgorithmEnum* e = new AlgorithmEnum(algoType, name, klen, ra, enc, dec, alId);
algos.push_back(e);
}
int EnumBase::getSize() {
return algos.size();
}
AlgoTypes EnumBase::getAlgoType() {
return algoType;
}
AlgorithmEnum& EnumBase::getByName(const char* name) {
std::vector<AlgorithmEnum* >::iterator b = algos.begin();
std::vector<AlgorithmEnum* >::iterator e = algos.end();
for (; b != e; b++) {
if (strncmp((*b)->getName(), name, 4) == 0) {
return *(*b);
}
}
return invalidAlgo;
}
AlgorithmEnum& EnumBase::getByOrdinal(int ord) {
std::vector<AlgorithmEnum* >::iterator b = algos.begin();
std::vector<AlgorithmEnum* >::iterator e = algos.end();
for (int i = 0; b != e; ++b) {
if (i == ord) {
return *(*b);
}
i++;
}
return invalidAlgo;
}
int EnumBase::getOrdinal(AlgorithmEnum& algo) {
std::vector<AlgorithmEnum* >::iterator b = algos.begin();
std::vector<AlgorithmEnum* >::iterator e = algos.end();
for (int i = 0; b != e; ++b) {
if (strncmp((*b)->getName(), algo.getName(), 4) == 0) {
return i;
}
i++;
}
return -1;
}
std::list<std::string>* EnumBase::getAllNames() {
std::vector<AlgorithmEnum* >::iterator b = algos.begin();
std::vector<AlgorithmEnum* >::iterator e = algos.end();
std::list<std::string>* strg = new std::list<std::string>();
for (; b != e; b++) {
std::string s((*b)->getName());
strg->push_back(s);
}
return strg;
}
/**
* Set up the enumeration list for available hash algorithms
*/
HashEnum::HashEnum() : EnumBase(HashAlgorithm) {
insert(s256, 0, "SHA-256", NULL, NULL, None);
insert(s384, 0, "SHA-384", NULL, NULL, None);
insert(skn2, 0, "Skein-256", NULL, NULL, None);
insert(skn3, 0, "Skein-384", NULL, NULL, None);
}
HashEnum::~HashEnum() {}
/**
* Set up the enumeration list for available symmetric cipher algorithms
*/
SymCipherEnum::SymCipherEnum() : EnumBase(CipherAlgorithm) {
insert(aes3, 32, "AES-256", aesCfbEncrypt, aesCfbDecrypt, Aes);
insert(aes1, 16, "AES-128", aesCfbEncrypt, aesCfbDecrypt, Aes);
insert(two3, 32, "Twofish-256", twoCfbEncrypt, twoCfbDecrypt, TwoFish);
insert(two1, 16, "TwoFish-128", twoCfbEncrypt, twoCfbDecrypt, TwoFish);
}
SymCipherEnum::~SymCipherEnum() {}
/**
* Set up the enumeration list for available public key algorithms
*/
PubKeyEnum::PubKeyEnum() : EnumBase(PubKeyAlgorithm) {
insert(dh2k, 0, "DH-2048", NULL, NULL, None);
insert(ec25, 0, "ECDH-256", NULL, NULL, None);
insert(dh3k, 0, "DH-3072", NULL, NULL, None);
insert(ec38, 0, "ECDH-384", NULL, NULL, None);
insert(mult, 0, "Multi-stream", NULL, NULL, None);
#ifdef SUPPORT_NON_NIST
insert(e255, 0, "Curve25519", NULL, NULL, None);
insert(e414, 0, "Curve3617", NULL, NULL, None);
#endif
}
PubKeyEnum::~PubKeyEnum() {}
/**
* Set up the enumeration list for available SAS algorithms
*/
SasTypeEnum::SasTypeEnum() : EnumBase(SasType) {
insert(b32);
insert(b256);
}
SasTypeEnum::~SasTypeEnum() {}
/**
* Set up the enumeration list for available SRTP authentications
*/
AuthLengthEnum::AuthLengthEnum() : EnumBase(AuthLength) {
insert(hs32, 32, "HMAC-SHA1 32 bit", NULL, NULL, Sha1);
insert(hs80, 80, "HMAC-SHA1 80 bit", NULL, NULL, Sha1);
insert(sk32, 32, "Skein-MAC 32 bit", NULL, NULL, Skein);
insert(sk64, 64, "Skein-MAC 64 bit", NULL, NULL, Skein);
}
AuthLengthEnum::~AuthLengthEnum() {}
/*
* Here the global accessible enumerations for all implemented algorithms.
*/
HashEnum zrtpHashes;
SymCipherEnum zrtpSymCiphers;
PubKeyEnum zrtpPubKeys;
SasTypeEnum zrtpSasTypes;
AuthLengthEnum zrtpAuthLengths;
/*
* The public methods are mainly a facade to the private methods.
*/
ZrtpConfigure::ZrtpConfigure(): enableTrustedMitM(false), enableSasSignature(false), enableParanoidMode(false),
selectionPolicy(Standard){}
ZrtpConfigure::~ZrtpConfigure() {}
void ZrtpConfigure::setStandardConfig() {
clear();
addAlgo(HashAlgorithm, zrtpHashes.getByName(s384));
addAlgo(HashAlgorithm, zrtpHashes.getByName(s256));
addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(two3));
addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes3));
addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(two1));
addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes1));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec25));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh3k));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec38));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh2k));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(mult));
addAlgo(SasType, zrtpSasTypes.getByName(b32));
addAlgo(AuthLength, zrtpAuthLengths.getByName(sk32));
addAlgo(AuthLength, zrtpAuthLengths.getByName(sk64));
addAlgo(AuthLength, zrtpAuthLengths.getByName(hs32));
addAlgo(AuthLength, zrtpAuthLengths.getByName(hs80));
}
void ZrtpConfigure::setMandatoryOnly() {
clear();
addAlgo(HashAlgorithm, zrtpHashes.getByName(s256));
addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes1));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh3k));
addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(mult));
addAlgo(SasType, zrtpSasTypes.getByName(b32));
addAlgo(AuthLength, zrtpAuthLengths.getByName(hs32));
addAlgo(AuthLength, zrtpAuthLengths.getByName(hs80));
}
void ZrtpConfigure::clear() {
hashes.clear();
symCiphers.clear();
publicKeyAlgos.clear();
sasTypes.clear();
authLengths.clear();
}
int32_t ZrtpConfigure::addAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {
return addAlgo(getEnum(algoType), algo);
}
int32_t ZrtpConfigure::addAlgoAt(AlgoTypes algoType, AlgorithmEnum& algo, int32_t index) {
return addAlgoAt(getEnum(algoType), algo, index);
}
AlgorithmEnum& ZrtpConfigure::getAlgoAt(AlgoTypes algoType, int32_t index) {
return getAlgoAt(getEnum(algoType), index);
}
int32_t ZrtpConfigure::removeAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {
return removeAlgo(getEnum(algoType), algo);
}
int32_t ZrtpConfigure::getNumConfiguredAlgos(AlgoTypes algoType) {
return getNumConfiguredAlgos(getEnum(algoType));
}
bool ZrtpConfigure::containsAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {
return containsAlgo(getEnum(algoType), algo);
}
void ZrtpConfigure::printConfiguredAlgos(AlgoTypes algoType) {
printConfiguredAlgos(getEnum(algoType));
}
/*
* The next methods are the private methods that implement the real
* details.
*/
AlgorithmEnum& ZrtpConfigure::getAlgoAt(std::vector<AlgorithmEnum* >& a, int32_t index) {
if (index >= (int)a.size())
return invalidAlgo;
std::vector<AlgorithmEnum* >::iterator b = a.begin();
std::vector<AlgorithmEnum* >::iterator e = a.end();
for (int i = 0; b != e; ++b) {
if (i == index) {
return *(*b);
}
i++;
}
return invalidAlgo;
}
int32_t ZrtpConfigure::addAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {
int size = (int)a.size();
if (size >= maxNoOfAlgos)
return -1;
if (!algo.isValid())
return -1;
if (containsAlgo(a, algo))
return (maxNoOfAlgos - size);
a.push_back(&algo);
return (maxNoOfAlgos - (int)a.size());
}
int32_t ZrtpConfigure::addAlgoAt(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo, int32_t index) {
if (index >= maxNoOfAlgos)
return -1;
int size = (int)a.size();
if (!algo.isValid())
return -1;
// a[index] = &algo;
if (index >= size) {
a.push_back(&algo);
return maxNoOfAlgos - (int)a.size();
}
std::vector<AlgorithmEnum* >::iterator b = a.begin();
std::vector<AlgorithmEnum* >::iterator e = a.end();
for (int i = 0; b != e; ++b) {
if (i == index) {
a.insert(b, &algo);
break;
}
i++;
}
return (maxNoOfAlgos - (int)a.size());
}
int32_t ZrtpConfigure::removeAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {
if ((int)a.size() == 0 || !algo.isValid())
return maxNoOfAlgos;
std::vector<AlgorithmEnum* >::iterator b = a.begin();
std::vector<AlgorithmEnum* >::iterator e = a.end();
for (; b != e; ++b) {
if (strcmp((*b)->getName(), algo.getName()) == 0) {
a.erase(b);
break;
}
}
return (maxNoOfAlgos - (int)a.size());
}
int32_t ZrtpConfigure::getNumConfiguredAlgos(std::vector<AlgorithmEnum* >& a) {
return (int32_t)a.size();
}
bool ZrtpConfigure::containsAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {
if ((int)a.size() == 0 || !algo.isValid())
return false;
std::vector<AlgorithmEnum* >::iterator b = a.begin();
std::vector<AlgorithmEnum* >::iterator e = a.end();
for (; b != e; ++b) {
if (strcmp((*b)->getName(), algo.getName()) == 0) {
return true;
}
}
return false;
}
void ZrtpConfigure::printConfiguredAlgos(std::vector<AlgorithmEnum* >& a) {
std::vector<AlgorithmEnum* >::iterator b = a.begin();
std::vector<AlgorithmEnum* >::iterator e = a.end();
for (; b != e; ++b) {
printf("print configured: name: %s\n", (*b)->getName());
}
}
std::vector<AlgorithmEnum* >& ZrtpConfigure::getEnum(AlgoTypes algoType) {
switch(algoType) {
case HashAlgorithm:
return hashes;
break;
case CipherAlgorithm:
return symCiphers;
break;
case PubKeyAlgorithm:
return publicKeyAlgos;
break;
case SasType:
return sasTypes;
break;
case AuthLength:
return authLengths;
break;
default:
break;
}
return hashes;
}
void ZrtpConfigure::setTrustedMitM(bool yesNo) {
enableTrustedMitM = yesNo;
}
bool ZrtpConfigure::isTrustedMitM() {
return enableTrustedMitM;
}
void ZrtpConfigure::setSasSignature(bool yesNo) {
enableSasSignature = yesNo;
}
bool ZrtpConfigure::isSasSignature() {
return enableSasSignature;
}
void ZrtpConfigure::setParanoidMode(bool yesNo) {
enableParanoidMode = yesNo;
}
bool ZrtpConfigure::isParanoidMode() {
return enableParanoidMode;
}
#if 0
ZrtpConfigure config;
main() {
printf("Start\n");
printf("size: %d\n", zrtpHashes.getSize());
AlgorithmEnum e = zrtpHashes.getByName("S256");
printf("algo name: %s\n", e.getName());
printf("algo type: %d\n", e.getAlgoType());
std::list<std::string>* names = zrtpHashes.getAllNames();
printf("size of name list: %d\n", names->size());
printf("first name: %s\n", names->front().c_str());
printf("last name: %s\n", names->back().c_str());
printf("free slots: %d (expected 6)\n", config.addAlgo(HashAlgorithm, e));
AlgorithmEnum e1(HashAlgorithm, "SHA384");
printf("free slots: %d (expected 5)\n", config.addAlgoAt(HashAlgorithm, e1, 0));
AlgorithmEnum e2 = config.getAlgoAt(HashAlgorithm, 0);
printf("algo name: %s (expected SHA384)\n", e2.getName());
printf("Num of configured algos: %d (expected 2)\n", config.getNumConfiguredAlgos(HashAlgorithm));
config.printConfiguredAlgos(HashAlgorithm);
printf("free slots: %d (expected 6)\n", config.removeAlgo(HashAlgorithm, e2));
e2 = config.getAlgoAt(HashAlgorithm, 0);
printf("algo name: %s (expected SHA256)\n", e2.getName());
printf("clearing config\n");
config.clear();
printf("size: %d\n", zrtpHashes.getSize());
e = zrtpHashes.getByName("S256");
printf("algo name: %s\n", e.getName());
printf("algo type: %d\n", e.getAlgoType());
}
#endif
/** EMACS **
* Local variables:
* mode: c++
* c-default-style: ellemtel
* c-basic-offset: 4
* End:
*/