Initial Debian packaging; add src/include.mk
[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 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.
16  *  
17  *
18  *  Copyright (C) 2007-2008 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 version 3 as
24  *  published by the Free Software Foundation.
25  *
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.
30  *
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/>.
33  */
34
35 #include "datatypes.h"
36
37 #include "encrypted_packet.h"
38
39 #include "auth_algo.h"
40
41 #include "log.h"
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 auth_algo_type_t auth_algo_get_type(const char* type)
47 {
48   if(!strcmp(type, "null"))
49     return aa_null;
50   else if(!strcmp(type, "sha1"))
51     return aa_sha1;
52   
53   return aa_unknown;
54 }
55
56 u_int32_t auth_algo_get_max_length(const char* type)
57 {
58   switch(auth_algo_get_type(type)) {
59   case aa_null: return 0;
60   case aa_sha1: return SHA1_LENGTH;
61   default: return 0;
62   }
63 }
64
65 int auth_algo_init(auth_algo_t* aa, const char* type)
66 {
67   if(!aa) 
68     return -1;
69
70   aa->type_ = auth_algo_get_type(type);
71   if(aa->type_ == aa_unknown) {
72     log_printf(ERROR, "unknown auth algo type");
73     return -1;
74   }
75
76   aa->params_ = NULL;
77
78   aa->key_.buf_ = NULL;
79   aa->key_.length_ = 0;
80
81   int ret = 0;
82   if(aa->type_ == aa_sha1)
83     ret = auth_algo_sha1_init(aa);
84
85   if(ret)
86     auth_algo_close(aa);
87
88   return ret;
89 }
90
91 void auth_algo_close(auth_algo_t* aa)
92 {
93   if(!aa)
94     return;
95
96   if(aa->type_ == aa_sha1)
97     auth_algo_sha1_close(aa);
98
99   if(aa->key_.buf_)
100     free(aa->key_.buf_);
101 }
102
103 void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
104 {
105   if(!aa) 
106     return;
107
108   if(aa->type_ == aa_null)
109     return;
110   else if(aa->type_ == aa_sha1)
111     auth_algo_sha1_generate(aa, kd, dir, packet);
112   else {
113     log_printf(ERROR, "unknown auth algo type");
114     return;
115   }
116 }
117
118 int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
119 {
120   if(!aa) 
121     return 0;
122
123   if(aa->type_ == aa_null)
124     return 1;
125   else if(aa->type_ == aa_sha1)
126     return auth_algo_sha1_check_tag(aa, kd, dir, packet);
127   else {
128     log_printf(ERROR, "unknown auth algo type");
129     return 0;
130   }
131 }
132
133 /* ---------------- HMAC Sha1 Auth Algo ---------------- */
134
135 int auth_algo_sha1_init(auth_algo_t* aa)
136 {
137   if(!aa)
138     return -1;
139
140   if(aa->key_.buf_)
141     free(aa->key_.buf_);
142
143   aa->key_.length_ = SHA1_LENGTH;
144   aa->key_.buf_ = malloc(aa->key_.length_);
145   if(!aa->key_.buf_)
146     return -2;
147
148   if(aa->params_)
149     free(aa->params_);
150   aa->params_ = malloc(sizeof(auth_algo_sha1_param_t));
151   if(!aa->params_)
152     return -2;
153
154   auth_algo_sha1_param_t* params = aa->params_;
155
156 #ifndef USE_SSL_CRYPTO
157   gcry_error_t err = gcry_md_open(&params->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
158   if(err) {
159     log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err));
160     return -1;
161   } 
162 #else
163   HMAC_CTX_init(&params->ctx_);
164   HMAC_Init_ex(&params->ctx_, NULL, 0, EVP_sha1(), NULL);
165 #endif
166
167   return 0;
168 }
169
170 void auth_algo_sha1_close(auth_algo_t* aa)
171 {
172   if(!aa)
173     return;
174
175   if(aa->params_) {
176     auth_algo_sha1_param_t* params = aa->params_;
177
178 #ifndef USE_SSL_CRYPTO
179     if(params->handle_)
180       gcry_md_close(params->handle_);
181 #else
182     HMAC_CTX_cleanup(&params->ctx_);
183 #endif    
184
185     free(aa->params_);
186   }
187
188 }
189
190 void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
191 {
192   if(!encrypted_packet_get_auth_tag_length(packet))
193     return;
194
195   if(!aa || !aa->params_) {
196     log_printf(ERROR, "auth algo not initialized");
197     return;
198   }
199   if(!kd) {
200     log_printf(ERROR, "no key derivation supplied");
201     return;
202   }
203   auth_algo_sha1_param_t* params = aa->params_;
204
205   int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
206   if(ret < 0)
207     return;
208
209 #ifndef USE_SSL_CRYPTO
210   gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_);
211   if(err) {
212     log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err));
213     return;
214   } 
215   
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);
220 #else
221   HMAC_Init_ex(&params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
222
223   u_int8_t hmac[SHA1_LENGTH];
224   HMAC_Update(&params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
225   HMAC_Final(&params->ctx_, hmac, NULL);
226 #endif
227
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;
230
231   if(length > SHA1_LENGTH)
232     memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
233
234   memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
235 }
236
237
238 int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet)
239 {
240   if(!encrypted_packet_get_auth_tag_length(packet))
241     return 1;
242
243   if(!aa || !aa->params_) {
244     log_printf(ERROR, "auth algo not initialized");
245     return 0;
246   }
247   if(!kd) {
248     log_printf(ERROR, "no key derivation supplied");
249     return 0;
250   }
251   auth_algo_sha1_param_t* params = aa->params_;
252
253   int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
254   if(ret < 0)
255     return 0;
256
257 #ifndef USE_SSL_CRYPTO
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 -1;
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 #else
269   HMAC_Init_ex(&params->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL);
270
271   u_int8_t hmac[SHA1_LENGTH];
272   HMAC_Update(&params->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
273   HMAC_Final(&params->ctx_, hmac, NULL);
274 #endif
275
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;
278
279   if(length > SHA1_LENGTH) {
280     u_int32_t i;
281     for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
282       if(tag[i]) return 0; 
283   }
284   
285   int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
286   
287   if(result)
288     return 0;
289
290   return 1;
291 }