Fix typo in manpage
[debian/uanytun.git] / src / auth_algo.c
1 /*
2  *  uAnytun
3  *
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.
16  *
17  *
18  *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
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
25  *  any later version.
26  *
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.
31  *
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/>.
34  *
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
39  *  including the two.
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.
47  */
48
49 #include "datatypes.h"
50
51 #include "encrypted_packet.h"
52
53 #include "auth_algo.h"
54
55 #include "log.h"
56
57 #include <stdlib.h>
58 #include <string.h>
59
60 auth_algo_type_t auth_algo_get_type(const char* type)
61 {
62   if(!strcmp(type, "null"))
63     return aa_null;
64   else if(!strcmp(type, "sha1"))
65     return aa_sha1;
66
67   return aa_unknown;
68 }
69
70 u_int32_t auth_algo_get_max_length(const char* type)
71 {
72   switch(auth_algo_get_type(type)) {
73   case aa_null: return 0;
74   case aa_sha1: return SHA1_LENGTH;
75   default: return 0;
76   }
77 }
78
79 int auth_algo_init(auth_algo_t* aa, const char* type)
80 {
81   if(!aa)
82     return -1;
83
84   aa->type_ = auth_algo_get_type(type);
85   if(aa->type_ == aa_unknown) {
86     log_printf(ERROR, "unknown auth algo type");
87     return -1;
88   }
89
90   aa->params_ = NULL;
91
92   aa->key_.buf_ = NULL;
93   aa->key_.length_ = 0;
94
95   int ret = 0;
96   if(aa->type_ == aa_sha1)
97     ret = auth_algo_sha1_init(aa);
98
99   if(ret)
100     auth_algo_close(aa);
101
102   return ret;
103 }
104
105 void auth_algo_close(auth_algo_t* aa)
106 {
107   if(!aa)
108     return;
109
110   if(aa->type_ == aa_sha1)
111     auth_algo_sha1_close(aa);
112
113   if(aa->key_.buf_)
114     free(aa->key_.buf_);
115 }
116
117 void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
118 {
119   if(!aa)
120     return;
121
122   if(aa->type_ == aa_null)
123     return;
124   else if(aa->type_ == aa_sha1)
125     auth_algo_sha1_generate(aa, kd, dir, packet);
126   else {
127     log_printf(ERROR, "unknown auth algo type");
128     return;
129   }
130 }
131
132 int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
133 {
134   if(!aa)
135     return 0;
136
137   if(aa->type_ == aa_null)
138     return 1;
139   else if(aa->type_ == aa_sha1)
140     return auth_algo_sha1_check_tag(aa, kd, dir, packet);
141   else {
142     log_printf(ERROR, "unknown auth algo type");
143     return 0;
144   }
145 }
146
147 /* ---------------- HMAC Sha1 Auth Algo ---------------- */
148
149 int auth_algo_sha1_init(auth_algo_t* aa)
150 {
151   if(!aa)
152     return -1;
153
154   if(aa->key_.buf_)
155     free(aa->key_.buf_);
156
157   aa->key_.length_ = SHA1_LENGTH;
158   aa->key_.buf_ = malloc(aa->key_.length_);
159   if(!aa->key_.buf_)
160     return -2;
161
162   if(aa->params_)
163     free(aa->params_);
164   aa->params_ = calloc(1, sizeof(auth_algo_sha1_param_t));
165   if(!aa->params_)
166     return -2;
167
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");
173     return -2;
174   }
175 # else
176   if ((params->ctx_ = calloc(1, sizeof(HMAC_CTX))) == NULL) {
177     log_printf(ERROR, "failed to allocate HMAC_CTX");
178     return -2;
179   }
180   HMAC_CTX_init(params->ctx_);
181 # endif
182   HMAC_Init_ex(params->ctx_, NULL, 0, EVP_sha1(), NULL);
183 #elif defined(USE_NETTLE)
184   // nothing here
185 #else  // USE_GCRYPT is the default
186   auth_algo_sha1_param_t* params = aa->params_;
187   gcry_error_t err = gcry_md_open(&params->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
188   if(err) {
189     log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
190     return -1;
191   }
192 #endif
193
194   return 0;
195 }
196
197 void auth_algo_sha1_close(auth_algo_t* aa)
198 {
199   if(!aa)
200     return;
201
202   if(aa->params_) {
203 #if defined(USE_SSL_CRYPTO)
204     auth_algo_sha1_param_t* params = aa->params_;
205     if(params->ctx_) {
206 # if OPENSSL_VERSION_NUMBER >= 0x10100000L
207       HMAC_CTX_free(params->ctx_);
208 # else
209       HMAC_CTX_cleanup(params->ctx_);
210       free(params->ctx_);
211 # endif
212     }
213 #elif defined(USE_NETTLE)
214     // nothing here
215 #else  // USE_GCRYPT is the default
216     auth_algo_sha1_param_t* params = aa->params_;
217     if(params->handle_)
218       gcry_md_close(params->handle_);
219 #endif
220
221     free(aa->params_);
222   }
223
224 }
225
226 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
227 {
228   if(!encrypted_packet_get_auth_tag_length(packet))
229     return;
230
231   if(!aa || !aa->params_) {
232     log_printf(ERROR, "auth algo not initialized");
233     return;
234   }
235   if(!kd) {
236     log_printf(ERROR, "no key derivation supplied");
237     return;
238   }
239   auth_algo_sha1_param_t* params = aa->params_;
240
241   int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
242   if(ret < 0)
243     return;
244
245 #if defined(USE_SSL_CRYPTO)
246   HMAC_Init_ex(params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
247
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(&params->ctx_, aa->key_.length_, aa->key_.buf_);
253
254   u_int8_t hmac[SHA1_LENGTH];
255   hmac_sha1_update(&params->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
256   hmac_sha1_digest(&params->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_);
259   if(err) {
260     log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
261     return;
262   }
263
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);
268 #endif
269
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;
272
273   if(length > SHA1_LENGTH)
274     memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
275
276   memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
277 }
278
279
280 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
281 {
282   if(!encrypted_packet_get_auth_tag_length(packet))
283     return 1;
284
285   if(!aa || !aa->params_) {
286     log_printf(ERROR, "auth algo not initialized");
287     return 0;
288   }
289   if(!kd) {
290     log_printf(ERROR, "no key derivation supplied");
291     return 0;
292   }
293   auth_algo_sha1_param_t* params = aa->params_;
294
295   int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
296   if(ret < 0)
297     return 0;
298
299 #if defined(USE_SSL_CRYPTO)
300   HMAC_Init_ex(params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
301
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(&params->ctx_, aa->key_.length_, aa->key_.buf_);
307
308   u_int8_t hmac[SHA1_LENGTH];
309   hmac_sha1_update(&params->ctx_, encrypted_packet_get_auth_portion_length(packet), encrypted_packet_get_auth_portion(packet));
310   hmac_sha1_digest(&params->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_);
313   if(err) {
314     log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
315     return -1;
316   }
317
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);
322 #endif
323
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;
326
327   if(length > SHA1_LENGTH) {
328     u_int32_t i;
329     for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
330       if(tag[i]) return 0;
331   }
332
333   int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
334
335   if(result)
336     return 0;
337
338   return 1;
339 }