/* * ľAnytun * * ľAnytun is a tiny implementation of SATP. Unlike Anytun which is a full * featured implementation ľAnytun has no support for multiple connections * or synchronisation. It is a small single threaded implementation intended * to act as a client on small platforms. * The secure anycast tunneling protocol (satp) defines a protocol used * for communication between any combination of unicast and anycast * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel * mode and allows tunneling of every ETHER TYPE protocol (e.g. * ethernet, ip, arp ...). satp directly includes cryptography and * message authentication based on the methodes used by SRTP. It is * intended to deliver a generic, scaleable and secure solution for * tunneling and relaying of packets of any protocol. * * * Copyright (C) 2007-2008 Christian Pointner * * This file is part of ľAnytun. * * ľAnytun is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * ľAnytun 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 ľAnytun. If not, see . */ #include "datatypes.h" #include "key_derivation.h" #include "log.h" #include #include int key_derivation_init(key_derivation_t* kd, const char* type, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len) { if(!kd) return -1; kd->type_ = unknown; if(!strcmp(type, "null")) kd->type_ = null; else if(!strcmp(type, "aes-ctr")) kd->type_ = aes_ctr; else { log_printf(ERR, "unknown key derivation type"); return -1; } kd->ld_kdr_ = -1; kd->handle_ = 0; if(!key) { kd->master_key_.buf_ = NULL; kd->master_key_.length_ = 0; } else { kd->master_key_.buf_ = malloc(key_len); if(!kd->master_key_.buf_) return -2; memcpy(kd->master_key_.buf_, key, key_len); kd->master_key_.length_ = key_len; } if(!salt) { kd->master_salt_.buf_ = NULL; kd->master_salt_.length_ = 0; } else { kd->master_salt_.buf_ = malloc(salt_len); if(!kd->master_salt_.buf_) { if(kd->master_key_.buf_) free(kd->master_key_.buf_); return -2; } memcpy(kd->master_salt_.buf_, salt, salt_len); kd->master_salt_.length_ = salt_len; } int ret = 0; if(kd->type_ == aes_ctr) ret = key_derivation_aesctr_init(kd, key, key_len, salt, salt_len); return ret; } void key_derivation_close(key_derivation_t* kd) { if(!kd) return; if(kd->type_ == aes_ctr) key_derivation_aesctr_close(kd); if(kd->master_key_.buf_) free(kd->master_key_.buf_); if(kd->master_salt_.buf_) free(kd->master_salt_.buf_); } void key_derivation_generate(key_derivation_t* kd, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len) { if(!kd) return; if(kd->type_ == null) key_derivation_null_generate(key, len); else if(kd->type_ == aes_ctr) key_derivation_aesctr_generate(kd, label, seq_nr, key, len); else { log_printf(ERR, "unknown cipher type"); return; } } /* ---------------- NULL Key Derivation ---------------- */ void key_derivation_null_generate(u_int8_t* key, u_int32_t len) { memset(key, 0, len); } /* ---------------- AES-Ctr Key Derivation ---------------- */ int key_derivation_aesctr_init(key_derivation_t* kd, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len) { if(!kd) return -1; gcry_error_t err = gcry_cipher_open(&kd->handle_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0); if(err) { log_printf(ERR, "failed to open cipher: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; } err = gcry_cipher_setkey(kd->handle_, kd->master_key_.buf_, kd->master_key_.length_); if(err) { log_printf(ERR, "failed to set cipher key: %s/%s", gcry_strerror(err), gcry_strsource(err)); return -1; } return 0; } void key_derivation_aesctr_close(key_derivation_t* kd) { if(!kd) return; if(kd->handle_) gcry_cipher_close(kd->handle_); } buffer_t key_derivation_aesctr_calc_ctr(key_derivation_t* kd, satp_prf_label_t label, seq_nr_t seq_nr) { buffer_t result; result.buf_ = NULL; result.length_ = 0; if(!kd) return result; // see at: http://tools.ietf.org/html/rfc3711#section-4.3 // * Let r = index DIV key_derivation_rate (with DIV as defined above). // * Let key_id =