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_ = calloc(1, sizeof(auth_algo_sha1_param_t));
168 #if defined(USE_SSL_CRYPTO)
169 auth_algo_sha1_param_t* params = aa->params_;
170 # if OPENSSL_VERSION_NUMBER >= 0x10100000L
171 if ((params->ctx_ = HMAC_CTX_new()) == NULL) {
172 log_printf(ERROR, "failed to allocate HMAC_CTX");
176 if ((params->ctx_ = calloc(1, sizeof(HMAC_CTX))) == NULL) {
177 log_printf(ERROR, "failed to allocate HMAC_CTX");
180 HMAC_CTX_init(params->ctx_);
182 HMAC_Init_ex(params->ctx_, NULL, 0, EVP_sha1(), NULL);
183 #elif defined(USE_NETTLE)
185 #else // USE_GCRYPT is the default
186 auth_algo_sha1_param_t* params = aa->params_;
187 gcry_error_t err = gcry_md_open(¶ms->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
189 log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
197 void auth_algo_sha1_close(auth_algo_t* aa)
203 #if defined(USE_SSL_CRYPTO)
204 auth_algo_sha1_param_t* params = aa->params_;
206 # if OPENSSL_VERSION_NUMBER >= 0x10100000L
207 HMAC_CTX_free(params->ctx_);
209 HMAC_CTX_cleanup(params->ctx_);
213 #elif defined(USE_NETTLE)
215 #else // USE_GCRYPT is the default
216 auth_algo_sha1_param_t* params = aa->params_;
218 gcry_md_close(params->handle_);
226 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
228 if(!encrypted_packet_get_auth_tag_length(packet))
231 if(!aa || !aa->params_) {
232 log_printf(ERROR, "auth algo not initialized");
236 log_printf(ERROR, "no key derivation supplied");
239 auth_algo_sha1_param_t* params = aa->params_;
241 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
245 #if defined(USE_SSL_CRYPTO)
246 HMAC_Init_ex(params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
248 u_int8_t hmac[SHA1_LENGTH];
249 HMAC_Update(params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
250 HMAC_Final(params->ctx_, hmac, NULL);
251 #elif defined(USE_NETTLE)
252 hmac_sha1_set_key(¶ms->ctx_, aa->key_.length_, aa->key_.buf_);
254 u_int8_t hmac[SHA1_LENGTH];
255 hmac_sha1_update(¶ms->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
256 hmac_sha1_digest(¶ms->ctx_, SHA1_LENGTH, hmac);
257 #else // USE_GCRYPT is the default
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);
270 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
271 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
273 if(length > SHA1_LENGTH)
274 memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
276 memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
280 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
282 if(!encrypted_packet_get_auth_tag_length(packet))
285 if(!aa || !aa->params_) {
286 log_printf(ERROR, "auth algo not initialized");
290 log_printf(ERROR, "no key derivation supplied");
293 auth_algo_sha1_param_t* params = aa->params_;
295 int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
299 #if defined(USE_SSL_CRYPTO)
300 HMAC_Init_ex(params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
302 u_int8_t hmac[SHA1_LENGTH];
303 HMAC_Update(params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
304 HMAC_Final(params->ctx_, hmac, NULL);
305 #elif defined(USE_NETTLE)
306 hmac_sha1_set_key(¶ms->ctx_, aa->key_.length_, aa->key_.buf_);
308 u_int8_t hmac[SHA1_LENGTH];
309 hmac_sha1_update(¶ms->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
310 hmac_sha1_digest(¶ms->ctx_, SHA1_LENGTH, hmac);
311 #else // USE_GCRYPT is the default
312 gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
314 log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
318 gcry_md_reset(params->handle_);
319 gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
320 gcry_md_final(params->handle_);
321 u_int8_t* hmac = gcry_md_read(params->handle_, 0);
324 u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
325 u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
327 if(length > SHA1_LENGTH) {
329 for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
333 int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);