Imported Upstream version 0.3.3
[debian/uanytun.git] / src / cipher.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-2010 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
36 #include "datatypes.h"
37
38 #include "plain_packet.h"
39 #include "encrypted_packet.h"
40
41 #include "cipher.h"
42
43 #include "log.h"
44
45 #include <stdlib.h>
46 #include <string.h>
47
48 int cipher_init(cipher_t* c, const char* type)
49 {
50   if(!c) 
51     return -1;
52
53   c->key_length_ = 0;
54
55   c->type_ = c_unknown;
56   if(!strcmp(type, "null"))
57     c->type_ = c_null;
58 #ifndef NO_CRYPT
59   else if(!strncmp(type, "aes-ctr", 7)) {
60     c->type_ = c_aes_ctr;
61     if(type[7] == 0) {
62       c->key_length_ = C_AESCTR_DEFAULT_KEY_LENGTH;
63     }
64     else if(type[7] != '-') 
65       return -1;
66     else {
67       const char* tmp = &type[8];
68       c->key_length_ = atoi(tmp);
69     }
70   }
71 #endif
72   else {
73     log_printf(ERROR, "unknown cipher type");
74     return -1;
75   }
76
77   c->params_ = NULL;
78
79   c->key_.buf_ = NULL;
80   c->key_.length_ = 0;
81
82   c->salt_.buf_ = NULL;
83   c->salt_.length_ = 0;
84
85   int ret = 0;
86 #ifndef NO_CRYPT
87   if(c->type_ == c_aes_ctr)
88     ret = cipher_aesctr_init(c);
89 #endif
90
91   if(ret)
92     cipher_close(c);
93
94   return ret;
95 }
96
97 void cipher_close(cipher_t* c)
98 {
99   if(!c)
100     return;
101
102 #ifndef NO_CRYPT
103   if(c->type_ == c_aes_ctr)
104     cipher_aesctr_close(c);
105 #endif
106
107   if(c->key_.buf_)
108     free(c->key_.buf_);
109   if(c->salt_.buf_)
110     free(c->salt_.buf_);
111 }
112
113
114 int cipher_encrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
115 {
116   if(!c) 
117     return -1;
118
119         int32_t len;
120   if(c->type_ == c_null)
121     len = cipher_null_crypt(plain_packet_get_packet(in), plain_packet_get_length(in), 
122                             encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out));
123 #ifndef NO_CRYPT
124   else if(c->type_ == c_aes_ctr)
125     len = cipher_aesctr_crypt(c, kd, dir, plain_packet_get_packet(in), plain_packet_get_length(in),
126                               encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out),
127                               seq_nr, sender_id, mux);
128 #endif
129   else {
130     log_printf(ERROR, "unknown cipher type");
131     return -1;
132   }
133
134   if(len < 0)
135     return 0;
136
137         encrypted_packet_set_sender_id(out, sender_id);
138   encrypted_packet_set_seq_nr(out, seq_nr);
139   encrypted_packet_set_mux(out, mux);
140
141   encrypted_packet_set_payload_length(out, len);
142
143   return 0;
144 }
145
146 int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out)
147 {
148   if(!c) 
149     return -1;
150
151         int32_t len;
152   if(c->type_ == c_null)
153     len = cipher_null_crypt(encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
154                             plain_packet_get_packet(out), plain_packet_get_length(out));
155 #ifndef NO_CRYPT
156   else if(c->type_ == c_aes_ctr)
157     len = cipher_aesctr_crypt(c, kd, dir, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
158                               plain_packet_get_packet(out), plain_packet_get_length(out),
159                               encrypted_packet_get_seq_nr(in), encrypted_packet_get_sender_id(in),
160                               encrypted_packet_get_mux(in));
161 #endif
162   else {
163     log_printf(ERROR, "unknown cipher type");
164     return -1;
165   }
166   
167   if(len < 0)
168     return 0;
169
170         plain_packet_set_length(out, len);
171
172   return 0;
173 }
174
175 /* ---------------- NULL Cipher ---------------- */
176
177 int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen)
178 {
179         memcpy(out, in, (ilen < olen) ? ilen : olen);
180   return (ilen < olen) ? ilen : olen;
181 }
182
183 #ifndef NO_CRYPT
184 /* ---------------- AES-Ctr Cipher ---------------- */
185
186 int cipher_aesctr_init(cipher_t* c)
187 {
188   if(!c)
189     return -1;
190
191   if(c->key_.buf_)
192     free(c->key_.buf_);
193
194   c->key_.length_ = c->key_length_/8;
195   c->key_.buf_ = malloc(c->key_.length_);
196   if(!c->key_.buf_)
197     return -2;
198
199   if(c->salt_.buf_)
200     free(c->salt_.buf_);
201
202   c->salt_.length_ = C_AESCTR_SALT_LENGTH;
203   c->salt_.buf_ = malloc(c->salt_.length_);
204   if(!c->salt_.buf_)
205     return -2;
206
207   if(c->params_)
208     free(c->params_);
209   c->params_ = malloc(sizeof(cipher_aesctr_param_t));
210   if(!c->params_)
211     return -2;
212
213   cipher_aesctr_param_t* params = c->params_;
214
215 #ifndef USE_SSL_CRYPTO
216   int algo;
217   switch(c->key_length_) {
218   case 128: algo = GCRY_CIPHER_AES128; break;
219   case 192: algo = GCRY_CIPHER_AES192; break;
220   case 256: algo = GCRY_CIPHER_AES256; break;
221   default: {
222     log_printf(ERROR, "cipher key length of %d Bits is not supported", c->key_length_);
223     return -1;
224   }
225   }
226
227   gcry_error_t err = gcry_cipher_open(&params->handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
228   if(err) {
229     log_printf(ERROR, "failed to open cipher: %s", gcry_strerror(err));
230     return -1;
231   } 
232 #endif
233
234   return 0;
235 }
236
237 void cipher_aesctr_close(cipher_t* c)
238 {
239   if(!c)
240     return;
241
242   if(c->params_) {
243     cipher_aesctr_param_t* params = c->params_;
244
245 #ifndef USE_SSL_CRYPTO
246     if(params->handle_)
247       gcry_cipher_close(params->handle_);
248 #endif
249
250     free(c->params_);
251   }
252 }
253
254 int cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
255 {
256   if(!c || !c->params_)
257     return -1;
258   
259   cipher_aesctr_param_t* params = c->params_;
260
261   int ret = key_derivation_generate(kd, dir, LABEL_SALT, seq_nr, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
262   if(ret < 0)
263     return ret;
264
265   memcpy(params->ctr_.salt_.buf_, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
266   params->ctr_.salt_.zero_ = 0;
267   params->ctr_.params_.mux_ ^= MUX_T_HTON(mux);
268   params->ctr_.params_.sender_id_ ^= SENDER_ID_T_HTON(sender_id);
269   params->ctr_.params_.seq_nr_ ^= SEQ_NR_T_HTON(seq_nr);
270
271   return 0;
272 }
273
274 int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
275 {
276   if(!c || !c->params_) {
277     log_printf(ERROR, "cipher not initialized");
278     return -1;
279   }
280
281   if(!kd) {
282     log_printf(ERROR, "no key derivation supplied");
283     return -1;
284   }
285
286   cipher_aesctr_param_t* params = c->params_;
287
288   int ret = key_derivation_generate(kd, dir, LABEL_ENC, seq_nr, c->key_.buf_, c->key_.length_);
289   if(ret < 0)
290     return ret;
291   
292 #ifdef USE_SSL_CRYPTO
293   ret = AES_set_encrypt_key(c->key_.buf_, c->key_length_, &params->aes_key_);
294   if(ret) {
295     log_printf(ERROR, "failed to set cipher ssl aes-key (code: %d)", ret);
296     return -1;
297   }
298 #else
299   gcry_error_t err = gcry_cipher_setkey(params->handle_, c->key_.buf_, c->key_.length_);
300   if(err) {
301     log_printf(ERROR, "failed to set cipher key: %s", gcry_strerror(err));
302     return -1;
303   }
304 #endif
305
306   ret = cipher_aesctr_calc_ctr(c, kd, dir, seq_nr, sender_id, mux);
307   if(ret < 0) {
308     log_printf(ERROR, "failed to calculate cipher CTR");
309     return ret;
310   }
311   
312 #ifndef USE_SSL_CRYPTO
313   err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, C_AESCTR_CTR_LENGTH);
314   if(err) {
315     log_printf(ERROR, "failed to set cipher CTR: %s", gcry_strerror(err));
316     return -1;
317   }
318
319   err = gcry_cipher_encrypt(params->handle_, out, olen, in, ilen);
320   if(err) {
321     log_printf(ERROR, "failed to de/encrypt packet: %s", gcry_strerror(err));
322     return -1;
323   }
324 #else
325   if(C_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
326     log_printf(ERROR, "failed to set cipher CTR: size don't fits");
327     return -1;
328   }
329   u_int32_t num = 0;
330   memset(params->ecount_buf_, 0, AES_BLOCK_SIZE);
331   AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, &params->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num);
332 #endif
333
334   return (ilen < olen) ? ilen : olen;  
335 }
336 #endif