4 * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5 * featured implementation uAnytun has no support for multiple connections
6 * or synchronisation. It is a small single threaded implementation intended
7 * to act as a client on small platforms.
8 * The secure anycast tunneling protocol (satp) defines a protocol used
9 * for communication between any combination of unicast and anycast
10 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
11 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
12 * ethernet, ip, arp ...). satp directly includes cryptography and
13 * message authentication based on the methodes used by SRTP. It is
14 * intended to deliver a generic, scaleable and secure solution for
15 * tunneling and relaying of packets of any protocol.
18 * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
20 * This file is part of uAnytun.
22 * uAnytun is free software: you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License version 3 as
24 * published by the Free Software Foundation.
26 * uAnytun is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
35 #include "datatypes.h"
37 #include "encrypted_packet.h"
39 #include "auth_algo.h"
46 auth_algo_type_t auth_algo_get_type(const char* type)
48 if(!strcmp(type, "null"))
50 else if(!strcmp(type, "sha1"))
56 u_int32_t auth_algo_get_max_length(const char* type)
58 switch(auth_algo_get_type(type)) {
59 case aa_null: return 0;
60 case aa_sha1: return SHA1_LENGTH;
65 int auth_algo_init(auth_algo_t* aa, const char* type)
70 aa->type_ = auth_algo_get_type(type);
71 if(aa->type_ == aa_unknown) {
72 log_printf(ERROR, "unknown auth algo type");
82 if(aa->type_ == aa_sha1)
83 ret = auth_algo_sha1_init(aa);
91 void auth_algo_close(auth_algo_t* aa)
96 if(aa->type_ == aa_sha1)
97 auth_algo_sha1_close(aa);
103 void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
108 if(aa->type_ == aa_null)
110 else if(aa->type_ == aa_sha1)
111 auth_algo_sha1_generate(aa, kd, dir, packet);
113 log_printf(ERROR, "unknown auth algo type");
118 int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
123 if(aa->type_ == aa_null)
125 else if(aa->type_ == aa_sha1)
126 return auth_algo_sha1_check_tag(aa, kd, dir, packet);
128 log_printf(ERROR, "unknown auth algo type");
133 /* ---------------- HMAC Sha1 Auth Algo ---------------- */
135 int auth_algo_sha1_init(auth_algo_t* aa)
143 aa->key_.length_ = SHA1_LENGTH;
144 aa->key_.buf_ = malloc(aa->key_.length_);
150 aa->params_ = malloc(sizeof(auth_algo_sha1_param_t));
154 auth_algo_sha1_param_t* params = aa->params_;
156 #ifndef USE_SSL_CRYPTO
157 gcry_error_t err = gcry_md_open(¶ms->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
159 log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
163 HMAC_CTX_init(¶ms->ctx_);
164 HMAC_Init_ex(¶ms->ctx_, NULL, 0, EVP_sha1(), NULL);
170 void auth_algo_sha1_close(auth_algo_t* aa)
176 auth_algo_sha1_param_t* params = aa->params_;
178 #ifndef USE_SSL_CRYPTO
180 gcry_md_close(params->handle_);
182 HMAC_CTX_cleanup(¶ms->ctx_);
190 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
192 if(!encrypted_packet_get_auth_tag_length(packet))
195 if(!aa || !aa->params_) {
196 log_printf(ERROR, "auth algo not initialized");
200 log_printf(ERROR, "no key derivation supplied");
203 auth_algo_sha1_param_t* params = aa->params_;
205 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
209 #ifndef USE_SSL_CRYPTO
210 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
212 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
216 gcry_md_reset(params->handle_);
217 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
218 gcry_md_final(params->handle_);
219 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
221 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
223 u_int8_t hmac[SHA1_LENGTH];
224 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
225 HMAC_Final(¶ms->ctx_, hmac, NULL);
228 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
229 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
231 if(length > SHA1_LENGTH)
232 memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
234 memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
238 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
240 if(!encrypted_packet_get_auth_tag_length(packet))
243 if(!aa || !aa->params_) {
244 log_printf(ERROR, "auth algo not initialized");
248 log_printf(ERROR, "no key derivation supplied");
251 auth_algo_sha1_param_t* params = aa->params_;
253 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
257 #ifndef USE_SSL_CRYPTO
258 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
260 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
264 gcry_md_reset(params->handle_);
265 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
266 gcry_md_final(params->handle_);
267 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
269 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
271 u_int8_t hmac[SHA1_LENGTH];
272 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
273 HMAC_Final(¶ms->ctx_, hmac, NULL);
276 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
277 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
279 if(length > SHA1_LENGTH) {
281 for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
285 int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);