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-2010 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 as published by
24 * the Free Software Foundation, either version 3 of the License, or
27 * uAnytun is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
36 #include "datatypes.h"
38 #include "encrypted_packet.h"
40 #include "auth_algo.h"
47 auth_algo_type_t auth_algo_get_type(const char* type)
49 if(!strcmp(type, "null"))
51 else if(!strcmp(type, "sha1"))
57 u_int32_t auth_algo_get_max_length(const char* type)
59 switch(auth_algo_get_type(type)) {
60 case aa_null: return 0;
61 case aa_sha1: return SHA1_LENGTH;
66 int auth_algo_init(auth_algo_t* aa, const char* type)
71 aa->type_ = auth_algo_get_type(type);
72 if(aa->type_ == aa_unknown) {
73 log_printf(ERROR, "unknown auth algo type");
83 if(aa->type_ == aa_sha1)
84 ret = auth_algo_sha1_init(aa);
92 void auth_algo_close(auth_algo_t* aa)
97 if(aa->type_ == aa_sha1)
98 auth_algo_sha1_close(aa);
104 void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
109 if(aa->type_ == aa_null)
111 else if(aa->type_ == aa_sha1)
112 auth_algo_sha1_generate(aa, kd, dir, packet);
114 log_printf(ERROR, "unknown auth algo type");
119 int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
124 if(aa->type_ == aa_null)
126 else if(aa->type_ == aa_sha1)
127 return auth_algo_sha1_check_tag(aa, kd, dir, packet);
129 log_printf(ERROR, "unknown auth algo type");
134 /* ---------------- HMAC Sha1 Auth Algo ---------------- */
136 int auth_algo_sha1_init(auth_algo_t* aa)
144 aa->key_.length_ = SHA1_LENGTH;
145 aa->key_.buf_ = malloc(aa->key_.length_);
151 aa->params_ = malloc(sizeof(auth_algo_sha1_param_t));
155 auth_algo_sha1_param_t* params = aa->params_;
157 #ifndef USE_SSL_CRYPTO
158 gcry_error_t err = gcry_md_open(¶ms->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
160 log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
164 HMAC_CTX_init(¶ms->ctx_);
165 HMAC_Init_ex(¶ms->ctx_, NULL, 0, EVP_sha1(), NULL);
171 void auth_algo_sha1_close(auth_algo_t* aa)
177 auth_algo_sha1_param_t* params = aa->params_;
179 #ifndef USE_SSL_CRYPTO
181 gcry_md_close(params->handle_);
183 HMAC_CTX_cleanup(¶ms->ctx_);
191 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
193 if(!encrypted_packet_get_auth_tag_length(packet))
196 if(!aa || !aa->params_) {
197 log_printf(ERROR, "auth algo not initialized");
201 log_printf(ERROR, "no key derivation supplied");
204 auth_algo_sha1_param_t* params = aa->params_;
206 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
210 #ifndef USE_SSL_CRYPTO
211 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
213 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
217 gcry_md_reset(params->handle_);
218 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
219 gcry_md_final(params->handle_);
220 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
222 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
224 u_int8_t hmac[SHA1_LENGTH];
225 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
226 HMAC_Final(¶ms->ctx_, hmac, NULL);
229 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
230 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
232 if(length > SHA1_LENGTH)
233 memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
235 memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
239 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
241 if(!encrypted_packet_get_auth_tag_length(packet))
244 if(!aa || !aa->params_) {
245 log_printf(ERROR, "auth algo not initialized");
249 log_printf(ERROR, "no key derivation supplied");
252 auth_algo_sha1_param_t* params = aa->params_;
254 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
258 #ifndef USE_SSL_CRYPTO
259 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
261 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
265 gcry_md_reset(params->handle_);
266 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
267 gcry_md_final(params->handle_);
268 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
270 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
272 u_int8_t hmac[SHA1_LENGTH];
273 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
274 HMAC_Final(¶ms->ctx_, hmac, NULL);
277 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
278 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
280 if(length > SHA1_LENGTH) {
282 for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
286 int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);