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 methods 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-2014 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/>.
35 * In addition, as a special exception, the copyright holders give
36 * permission to link the code of portions of this program with the
37 * OpenSSL library under certain conditions as described in each
38 * individual source file, and distribute linked combinations
40 * You must obey the GNU General Public License in all respects
41 * for all of the code used other than OpenSSL. If you modify
42 * file(s) with this exception, you may extend this exception to your
43 * version of the file(s), but you are not obligated to do so. If you
44 * do not wish to do so, delete this exception statement from your
45 * version. If you delete this exception statement from all source
46 * files in the program, then also delete it here.
49 #include "datatypes.h"
51 #include "encrypted_packet.h"
53 #include "auth_algo.h"
60 auth_algo_type_t auth_algo_get_type(const char* type)
62 if(!strcmp(type, "null"))
64 else if(!strcmp(type, "sha1"))
70 u_int32_t auth_algo_get_max_length(const char* type)
72 switch(auth_algo_get_type(type)) {
73 case aa_null: return 0;
74 case aa_sha1: return SHA1_LENGTH;
79 int auth_algo_init(auth_algo_t* aa, const char* type)
84 aa->type_ = auth_algo_get_type(type);
85 if(aa->type_ == aa_unknown) {
86 log_printf(ERROR, "unknown auth algo type");
96 if(aa->type_ == aa_sha1)
97 ret = auth_algo_sha1_init(aa);
105 void auth_algo_close(auth_algo_t* aa)
110 if(aa->type_ == aa_sha1)
111 auth_algo_sha1_close(aa);
117 void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
122 if(aa->type_ == aa_null)
124 else if(aa->type_ == aa_sha1)
125 auth_algo_sha1_generate(aa, kd, dir, packet);
127 log_printf(ERROR, "unknown auth algo type");
132 int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
137 if(aa->type_ == aa_null)
139 else if(aa->type_ == aa_sha1)
140 return auth_algo_sha1_check_tag(aa, kd, dir, packet);
142 log_printf(ERROR, "unknown auth algo type");
147 /* ---------------- HMAC Sha1 Auth Algo ---------------- */
149 int auth_algo_sha1_init(auth_algo_t* aa)
157 aa->key_.length_ = SHA1_LENGTH;
158 aa->key_.buf_ = malloc(aa->key_.length_);
164 aa->params_ = malloc(sizeof(auth_algo_sha1_param_t));
168 #if defined(USE_SSL_CRYPTO)
169 auth_algo_sha1_param_t* params = aa->params_;
170 HMAC_CTX_init(¶ms->ctx_);
171 HMAC_Init_ex(¶ms->ctx_, NULL, 0, EVP_sha1(), NULL);
172 #elif defined(USE_NETTLE)
174 #else // USE_GCRYPT is the default
175 auth_algo_sha1_param_t* params = aa->params_;
176 gcry_error_t err = gcry_md_open(¶ms->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
178 log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
186 void auth_algo_sha1_close(auth_algo_t* aa)
192 #if defined(USE_SSL_CRYPTO)
193 auth_algo_sha1_param_t* params = aa->params_;
194 HMAC_CTX_cleanup(¶ms->ctx_);
195 #elif defined(USE_NETTLE)
197 #else // USE_GCRYPT is the default
198 auth_algo_sha1_param_t* params = aa->params_;
200 gcry_md_close(params->handle_);
208 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
210 if(!encrypted_packet_get_auth_tag_length(packet))
213 if(!aa || !aa->params_) {
214 log_printf(ERROR, "auth algo not initialized");
218 log_printf(ERROR, "no key derivation supplied");
221 auth_algo_sha1_param_t* params = aa->params_;
223 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
227 #if defined(USE_SSL_CRYPTO)
228 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
230 u_int8_t hmac[SHA1_LENGTH];
231 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
232 HMAC_Final(¶ms->ctx_, hmac, NULL);
233 #elif defined(USE_NETTLE)
234 hmac_sha1_set_key(¶ms->ctx_, aa->key_.length_, aa->key_.buf_);
236 u_int8_t hmac[SHA1_LENGTH];
237 hmac_sha1_update(¶ms->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
238 hmac_sha1_digest(¶ms->ctx_, SHA1_LENGTH, hmac);
239 #else // USE_GCRYPT is the default
240 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
242 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
246 gcry_md_reset(params->handle_);
247 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
248 gcry_md_final(params->handle_);
249 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
252 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
253 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
255 if(length > SHA1_LENGTH)
256 memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
258 memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
262 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
264 if(!encrypted_packet_get_auth_tag_length(packet))
267 if(!aa || !aa->params_) {
268 log_printf(ERROR, "auth algo not initialized");
272 log_printf(ERROR, "no key derivation supplied");
275 auth_algo_sha1_param_t* params = aa->params_;
277 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
281 #if defined(USE_SSL_CRYPTO)
282 HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
284 u_int8_t hmac[SHA1_LENGTH];
285 HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
286 HMAC_Final(¶ms->ctx_, hmac, NULL);
287 #elif defined(USE_NETTLE)
288 hmac_sha1_set_key(¶ms->ctx_, aa->key_.length_, aa->key_.buf_);
290 u_int8_t hmac[SHA1_LENGTH];
291 hmac_sha1_update(¶ms->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
292 hmac_sha1_digest(¶ms->ctx_, SHA1_LENGTH, hmac);
293 #else // USE_GCRYPT is the default
294 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
296 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
300 gcry_md_reset(params->handle_);
301 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
302 gcry_md_final(params->handle_);
303 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
306 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
307 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
309 if(length > SHA1_LENGTH) {
311 for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
315 int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);