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-2009 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 as published by
21 * the Free Software Foundation, either version 3 of the License, or
24 * Anytun is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
35 #include "anytunError.h"
36 #include "keyDerivation.h"
37 #include "threadUtils.hpp"
38 #include "datatypes.h"
50 #include <openssl/sha.h>
55 void KeyDerivation::setRole(const role_t role)
57 WritersLock lock(mutex_);
59 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: using role " << role_;
64 void KeyDerivation::calcMasterKey(std::string passphrase, uint16_t length)
66 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: calculating master key from passphrase";
68 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: bad master key length";
72 #ifndef USE_SSL_CRYPTO
73 if(length > gcry_md_get_algo_dlen(GCRY_MD_SHA256)) {
75 if(length > SHA256_DIGEST_LENGTH) {
77 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: master key too long for passphrase algorithm";
81 #ifndef USE_SSL_CRYPTO
82 Buffer digest(static_cast<uint32_t>(gcry_md_get_algo_dlen(GCRY_MD_SHA256)));
83 gcry_md_hash_buffer(GCRY_MD_SHA256, digest.getBuf(), passphrase.c_str(), passphrase.length());
85 Buffer digest(uint32_t(SHA256_DIGEST_LENGTH));
86 SHA256(reinterpret_cast<const unsigned char*>(passphrase.c_str()), passphrase.length(), digest.getBuf());
88 master_key_.setLength(length);
90 std::memcpy(master_key_.getBuf(), &digest.getBuf()[digest.getLength() - master_key_.getLength()], master_key_.getLength());
93 void KeyDerivation::calcMasterSalt(std::string passphrase, uint16_t length)
95 cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation: calculating master salt from passphrase";
97 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: bad master salt length";
101 #ifndef USE_SSL_CRYPTO
102 if(length > gcry_md_get_algo_dlen(GCRY_MD_SHA1)) {
104 if(length > SHA_DIGEST_LENGTH) {
106 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation: master key too long for passphrase algorithm";
110 #ifndef USE_SSL_CRYPTO
111 Buffer digest(static_cast<uint32_t>(gcry_md_get_algo_dlen(GCRY_MD_SHA1)));
112 gcry_md_hash_buffer(GCRY_MD_SHA1, digest.getBuf(), passphrase.c_str(), passphrase.length());
114 Buffer digest(uint32_t(SHA_DIGEST_LENGTH));
115 SHA1(reinterpret_cast<const unsigned char*>(passphrase.c_str()), passphrase.length(), digest.getBuf());
117 master_salt_.setLength(length);
119 std::memcpy(master_salt_.getBuf(), &digest.getBuf()[digest.getLength() - master_salt_.getLength()], master_salt_.getLength());
124 satp_prf_label_t KeyDerivation::convertLabel(kd_dir_t dir, satp_prf_label_t label)
128 if(dir == KD_OUTBOUND) {
129 if(role_ == ROLE_LEFT) { return LABEL_LEFT_ENC; }
130 if(role_ == ROLE_RIGHT) { return LABEL_RIGHT_ENC; }
132 if(role_ == ROLE_LEFT) { return LABEL_RIGHT_ENC; }
133 if(role_ == ROLE_RIGHT) { return LABEL_LEFT_ENC; }
138 if(dir == KD_OUTBOUND) {
139 if(role_ == ROLE_LEFT) { return LABEL_LEFT_SALT; }
140 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; }
152 if(role_ == ROLE_LEFT) { return LABEL_RIGHT_AUTH; }
153 if(role_ == ROLE_RIGHT) { return LABEL_LEFT_AUTH; }
162 //****** NullKeyDerivation ******
164 bool NullKeyDerivation::generate(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, Buffer& key)
166 std::memset(key.getBuf(), 0, key.getLength());
171 //****** AesIcmKeyDerivation ******
173 AesIcmKeyDerivation::AesIcmKeyDerivation() : KeyDerivation(DEFAULT_KEY_LENGTH)
175 #ifndef USE_SSL_CRYPTO
176 for(int i=0; i<2; i++) {
182 AesIcmKeyDerivation::AesIcmKeyDerivation(uint16_t key_length) : KeyDerivation(key_length)
184 #ifndef USE_SSL_CRYPTO
185 for(int i=0; i<2; i++) {
191 AesIcmKeyDerivation::~AesIcmKeyDerivation()
193 WritersLock lock(mutex_);
194 #ifndef USE_SSL_CRYPTO
195 for(int i=0; i<2; i++)
197 gcry_cipher_close(handle_[i]);
202 void AesIcmKeyDerivation::init(Buffer key, Buffer salt, std::string passphrase)
204 WritersLock lock(mutex_);
206 is_initialized_ = false;
207 #ifndef NO_PASSPHRASE
208 if(passphrase != "" && !key.getLength()) {
209 calcMasterKey(passphrase, key_length_/8);
211 master_key_ = SyncBuffer(key);
214 if(passphrase != "" && !salt.getLength()) {
215 calcMasterSalt(passphrase, SALT_LENGTH);
217 master_salt_ = SyncBuffer(salt);
220 master_key_ = SyncBuffer(key);
221 master_salt_ = SyncBuffer(salt);
227 void AesIcmKeyDerivation::updateMasterKey()
229 if(master_key_.getLength()*8 != key_length_) {
230 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: key lengths don't match";
234 if(master_salt_.getLength() != SALT_LENGTH) {
235 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: salt lengths don't match";
239 #ifndef USE_SSL_CRYPTO
241 switch(key_length_) {
243 algo = GCRY_CIPHER_AES128;
246 algo = GCRY_CIPHER_AES192;
249 algo = GCRY_CIPHER_AES256;
252 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: cipher key length of " << key_length_ << " Bits is not supported";
257 for(int i=0; i<2; i++) {
259 gcry_cipher_close(handle_[i]);
262 gcry_error_t err = gcry_cipher_open(&handle_[i], algo, GCRY_CIPHER_MODE_CTR, 0);
264 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to open cipher: " << AnytunGpgError(err);
268 err = gcry_cipher_setkey(handle_[i], master_key_.getBuf(), master_key_.getLength());
270 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << AnytunGpgError(err);
275 for(int i=0; i<2; i++) {
276 int ret = AES_set_encrypt_key(master_key_.getBuf(), master_key_.getLength()*8, &aes_key_[i]);
278 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::updateMasterKey: Failed to set ssl key (code: " << ret << ")";
283 is_initialized_ = true;
286 std::string AesIcmKeyDerivation::printType()
288 ReadersLock lock(mutex_);
290 std::stringstream sstr;
291 sstr << "AesIcm" << key_length_ << "KeyDerivation";
295 bool AesIcmKeyDerivation::calcCtr(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr)
297 if(master_salt_.getLength() != SALT_LENGTH) {
298 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::calcCtr: salt lengths don't match";
301 std::memcpy(ctr_[dir].salt_.buf_, master_salt_.getBuf(), SALT_LENGTH);
302 ctr_[dir].salt_.zero_ = 0;
303 ctr_[dir].params_.label_ ^= SATP_PRF_LABEL_T_HTON(convertLabel(dir, label));
304 ctr_[dir].params_.seq_ ^= SEQ_NR_T_HTON(seq_nr);
309 bool AesIcmKeyDerivation::generate(kd_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, Buffer& key)
311 ReadersLock lock(mutex_);
313 if(!is_initialized_) {
317 if(!calcCtr(dir, label, seq_nr)) {
321 #ifndef USE_SSL_CRYPTO
322 gcry_error_t err = gcry_cipher_reset(handle_[dir]);
324 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to reset cipher: " << AnytunGpgError(err);
327 err = gcry_cipher_setctr(handle_[dir], ctr_[dir].buf_, CTR_LENGTH);
329 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to set CTR: " << AnytunGpgError(err);
333 std::memset(key.getBuf(), 0, key.getLength());
334 err = gcry_cipher_encrypt(handle_[dir], key, key.getLength(), NULL, 0);
336 cLog.msg(Log::PRIO_ERROR) << "KeyDerivation::generate: Failed to generate cipher bitstream: " << AnytunGpgError(err);
339 if(CTR_LENGTH != AES_BLOCK_SIZE) {
340 cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: size don't fits";
343 unsigned int num = 0;
344 std::memset(ecount_buf_[dir], 0, AES_BLOCK_SIZE);
345 std::memset(key.getBuf(), 0, key.getLength());
346 AES_ctr128_encrypt(key.getBuf(), key.getBuf(), key.getLength(), &aes_key_[dir], ctr_[dir].buf_, ecount_buf_[dir], &num);