4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methodes used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
19 * Anytun is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 3 as
21 * published by the Free Software Foundation.
23 * Anytun is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
34 #include "anytunError.h"
35 #include "keyDerivation.h"
36 #include "threadUtils.hpp"
37 #include "datatypes.h"
48 #include <openssl/sha.h>
53 void KeyDerivation::setRole(const role_t role)
55 WritersLock lock(mutex_);
57 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: using role " << role_;
62 void KeyDerivation::calcMasterKey(std::string passphrase, u_int16_t length)
64 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: calculating master key from passphrase";
66 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: bad master key length";
70 #ifndef USE_SSL_CRYPTO
71 if(length > gcry_md_get_algo_dlen(GCRY_MD_SHA256)) {
73 if(length > SHA256_DIGEST_LENGTH) {
75 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: master key too long for passphrase algorithm";
79 #ifndef USE_SSL_CRYPTO
80 Buffer digest(gcry_md_get_algo_dlen(GCRY_MD_SHA256));
81 gcry_md_hash_buffer(GCRY_MD_SHA256, digest.getBuf(), passphrase.c_str(), passphrase.length());
83 Buffer digest(u_int32_t(SHA256_DIGEST_LENGTH));
84 SHA256(reinterpret_cast<const unsigned char*>(passphrase.c_str()), passphrase.length(), digest.getBuf());
86 master_key_.setLength(length);
88 memcpy(master_key_.getBuf(), &digest.getBuf()[digest.getLength() - master_key_.getLength()], master_key_.getLength());
91 void KeyDerivation::calcMasterSalt(std::string passphrase, u_int16_t length)
93 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: calculating master salt from passphrase";
95 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: bad master salt length";
99 #ifndef USE_SSL_CRYPTO
100 if(length > gcry_md_get_algo_dlen(GCRY_MD_SHA1)) {
102 if(length > SHA_DIGEST_LENGTH) {
104 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: master key too long for passphrase algorithm";
108 #ifndef USE_SSL_CRYPTO
109 Buffer digest(gcry_md_get_algo_dlen(GCRY_MD_SHA1));
110 gcry_md_hash_buffer(GCRY_MD_SHA1, digest.getBuf(), passphrase.c_str(), passphrase.length());
112 Buffer digest(u_int32_t(SHA_DIGEST_LENGTH));
113 SHA1(reinterpret_cast<const unsigned char*>(passphrase.c_str()), passphrase.length(), digest.getBuf());
115 master_salt_.setLength(length);
117 memcpy(master_salt_.getBuf(), &digest.getBuf()[digest.getLength() - master_salt_.getLength()], master_salt_.getLength());
122 satp_prf_label_t KeyDerivation::convertLabel(kd_dir_t dir, satp_prf_label_t label)
126 if(dir == KD_OUTBOUND) {
127 if(role_ == ROLE_LEFT) return LABEL_LEFT_ENC;
128 if(role_ == ROLE_RIGHT) return LABEL_RIGHT_ENC;
131 if(role_ == ROLE_LEFT) return LABEL_RIGHT_ENC;
132 if(role_ == ROLE_RIGHT) return LABEL_LEFT_ENC;
137 if(dir == KD_OUTBOUND) {
138 if(role_ == ROLE_LEFT) return LABEL_LEFT_SALT;
139 if(role_ == ROLE_RIGHT) return LABEL_RIGHT_SALT;
142 if(role_ == ROLE_LEFT) return LABEL_RIGHT_SALT;
143 if(role_ == ROLE_RIGHT) return LABEL_LEFT_SALT;
148 if(dir == KD_OUTBOUND) {
149 if(role_ == ROLE_LEFT) return LABEL_LEFT_AUTH;
150 if(role_ == ROLE_RIGHT) return LABEL_RIGHT_AUTH;
153 if(role_ == ROLE_LEFT) return LABEL_RIGHT_AUTH;
154 if(role_ == ROLE_RIGHT) return LABEL_LEFT_AUTH;
163 //****** NullKeyDerivation ******
165 bool NullKeyDerivation::generate(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, Buffer& key)
167 std::memset(key.getBuf(), 0, key.getLength());
172 //****** AesIcmKeyDerivation ******
174 AesIcmKeyDerivation::AesIcmKeyDerivation() : KeyDerivation(DEFAULT_KEY_LENGTH)
176 #ifndef USE_SSL_CRYPTO
177 for(int i=0; i<2; i++)
182 AesIcmKeyDerivation::AesIcmKeyDerivation(u_int16_t key_length) : KeyDerivation(key_length)
184 #ifndef USE_SSL_CRYPTO
185 for(int i=0; i<2; i++)
190 AesIcmKeyDerivation::~AesIcmKeyDerivation()
192 WritersLock lock(mutex_);
193 #ifndef USE_SSL_CRYPTO
194 for(int i=0; i<2; i++)
196 gcry_cipher_close(handle_[i]);
200 void AesIcmKeyDerivation::init(Buffer key, Buffer salt, std::string passphrase)
202 WritersLock lock(mutex_);
204 is_initialized_ = false;
205 #ifndef NO_PASSPHRASE
206 if(passphrase != "" && !key.getLength())
207 calcMasterKey(passphrase, key_length_/8);
209 master_key_ = SyncBuffer(key);
211 if(passphrase != "" && !salt.getLength())
212 calcMasterSalt(passphrase, SALT_LENGTH);
214 master_salt_ = SyncBuffer(salt);
216 master_key_ = SyncBuffer(key);
217 master_salt_ = SyncBuffer(salt);
223 void AesIcmKeyDerivation::updateMasterKey()
225 if(master_key_.getLength()*8 != key_length_) {
226 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: key lengths don't match";
230 if(master_salt_.getLength() != SALT_LENGTH) {
231 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: salt lengths don't match";
235 #ifndef USE_SSL_CRYPTO
237 switch(key_length_) {
238 case 128: algo = GCRY_CIPHER_AES128; break;
239 case 192: algo = GCRY_CIPHER_AES192; break;
240 case 256: algo = GCRY_CIPHER_AES256; break;
242 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: cipher key length of " << key_length_ << " Bits is not supported";
247 for(int i=0; i<2; i++) {
249 gcry_cipher_close(handle_[i]);
251 gcry_error_t err = gcry_cipher_open(&handle_[i], algo, GCRY_CIPHER_MODE_CTR, 0);
253 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to open cipher: " << AnytunGpgError(err);
257 err = gcry_cipher_setkey(handle_[i], master_key_.getBuf(), master_key_.getLength());
259 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << AnytunGpgError(err);
264 for(int i=0; i<2; i++) {
265 int ret = AES_set_encrypt_key(master_key_.getBuf(), master_key_.getLength()*8, &aes_key_[i]);
267 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to set ssl key (code: " << ret << ")";
272 is_initialized_ = true;
275 std::string AesIcmKeyDerivation::printType()
277 ReadersLock lock(mutex_);
279 std::stringstream sstr;
280 sstr << "AesIcm" << key_length_ << "KeyDerivation";
284 bool AesIcmKeyDerivation::calcCtr(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr)
286 if(master_salt_.getLength() != SALT_LENGTH) {
287 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::calcCtr: salt lengths don't match";
290 memcpy(ctr_[dir].salt_.buf_, master_salt_.getBuf(), SALT_LENGTH);
291 ctr_[dir].salt_.zero_ = 0;
292 ctr_[dir].params_.label_ ^= SATP_PRF_LABEL_T_HTON(convertLabel(dir, label));
293 ctr_[dir].params_.seq_ ^= SEQ_NR_T_HTON(seq_nr);
298 bool AesIcmKeyDerivation::generate(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, Buffer& key)
300 ReadersLock lock(mutex_);
305 if(!calcCtr(dir, label, seq_nr)) {
309 #ifndef USE_SSL_CRYPTO
310 gcry_error_t err = gcry_cipher_reset(handle_[dir]);
312 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to reset cipher: " << AnytunGpgError(err);
315 err = gcry_cipher_setctr(handle_[dir], ctr_[dir].buf_, CTR_LENGTH);
317 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to set CTR: " << AnytunGpgError(err);
321 std::memset(key.getBuf(), 0, key.getLength());
322 err = gcry_cipher_encrypt(handle_[dir], key, key.getLength(), NULL, 0);
324 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to generate cipher bitstream: " << AnytunGpgError(err);
327 if(CTR_LENGTH != AES_BLOCK_SIZE) {
328 cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: size don't fits";
331 unsigned int num = 0;
332 std::memset(ecount_buf_[dir], 0, AES_BLOCK_SIZE);
333 std::memset(key.getBuf(), 0, key.getLength());
334 AES_ctr128_encrypt(key.getBuf(), key.getBuf(), key.getLength(), &aes_key_[dir], ctr_[dir].buf_, ecount_buf_[dir], &num);