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 "plain_packet.h"
52 #include "encrypted_packet.h"
55 #if defined(USE_NETTLE)
56 #include <nettle/ctr.h>
64 int cipher_init(cipher_t* c, const char* type)
72 if(!strcmp(type, "null"))
75 else if(!strncmp(type, "aes-ctr", 7)) {
78 c->key_length_ = C_AESCTR_DEFAULT_KEY_LENGTH;
80 else if(type[7] != '-')
83 const char* tmp = &type[8];
84 c->key_length_ = atoi(tmp);
89 log_printf(ERROR, "unknown cipher type");
103 if(c->type_ == c_aes_ctr)
104 ret = cipher_aesctr_init(c);
113 void cipher_close(cipher_t* c)
119 if(c->type_ == c_aes_ctr)
120 cipher_aesctr_close(c);
130 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)
136 if(c->type_ == c_null)
137 len = cipher_null_crypt(plain_packet_get_packet(in), plain_packet_get_length(in),
138 encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out));
140 else if(c->type_ == c_aes_ctr)
141 len = cipher_aesctr_crypt(c, kd, dir, plain_packet_get_packet(in), plain_packet_get_length(in),
142 encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out),
143 seq_nr, sender_id, mux);
146 log_printf(ERROR, "unknown cipher type");
153 encrypted_packet_set_sender_id(out, sender_id);
154 encrypted_packet_set_seq_nr(out, seq_nr);
155 encrypted_packet_set_mux(out, mux);
157 encrypted_packet_set_payload_length(out, len);
162 int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out)
168 if(c->type_ == c_null)
169 len = cipher_null_crypt(encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
170 plain_packet_get_packet(out), plain_packet_get_length(out));
172 else if(c->type_ == c_aes_ctr)
173 len = cipher_aesctr_crypt(c, kd, dir, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in),
174 plain_packet_get_packet(out), plain_packet_get_length(out),
175 encrypted_packet_get_seq_nr(in), encrypted_packet_get_sender_id(in),
176 encrypted_packet_get_mux(in));
179 log_printf(ERROR, "unknown cipher type");
186 plain_packet_set_length(out, len);
191 /* ---------------- NULL Cipher ---------------- */
193 int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen)
195 memcpy(out, in, (ilen < olen) ? ilen : olen);
196 return (ilen < olen) ? ilen : olen;
200 /* ---------------- AES-Ctr Cipher ---------------- */
202 int cipher_aesctr_init(cipher_t* c)
210 c->key_.length_ = c->key_length_/8;
211 c->key_.buf_ = malloc(c->key_.length_);
218 c->salt_.length_ = C_AESCTR_SALT_LENGTH;
219 c->salt_.buf_ = malloc(c->salt_.length_);
225 c->params_ = malloc(sizeof(cipher_aesctr_param_t));
229 #if defined(USE_SSL_CRYPTO)
231 #elif defined(USE_NETTLE)
233 #else // USE_GCRYPT is the default
235 switch(c->key_length_) {
236 case 128: algo = GCRY_CIPHER_AES128; break;
237 case 192: algo = GCRY_CIPHER_AES192; break;
238 case 256: algo = GCRY_CIPHER_AES256; break;
240 log_printf(ERROR, "cipher key length of %d Bits is not supported", c->key_length_);
245 cipher_aesctr_param_t* params = c->params_;
246 gcry_error_t err = gcry_cipher_open(¶ms->handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
248 log_printf(ERROR, "failed to open cipher: %s", gcry_strerror(err));
256 void cipher_aesctr_close(cipher_t* c)
262 #if defined(USE_SSL_CRYPTO)
264 #elif defined(USE_NETTLE)
266 #else // USE_GCRYPT is the default
267 cipher_aesctr_param_t* params = c->params_;
268 gcry_cipher_close(params->handle_);
274 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)
276 if(!c || !c->params_)
279 cipher_aesctr_param_t* params = c->params_;
281 int ret = key_derivation_generate(kd, dir, LABEL_SALT, seq_nr, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
285 memcpy(params->ctr_.salt_.buf_, c->salt_.buf_, C_AESCTR_SALT_LENGTH);
286 params->ctr_.salt_.zero_ = 0;
287 params->ctr_.params_.mux_ ^= MUX_T_HTON(mux);
288 params->ctr_.params_.sender_id_ ^= SENDER_ID_T_HTON(sender_id);
289 params->ctr_.params_.seq_nr_ ^= SEQ_NR_T_HTON(seq_nr);
294 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)
296 if(!c || !c->params_) {
297 log_printf(ERROR, "cipher not initialized");
302 log_printf(ERROR, "no key derivation supplied");
306 cipher_aesctr_param_t* params = c->params_;
308 int ret = key_derivation_generate(kd, dir, LABEL_ENC, seq_nr, c->key_.buf_, c->key_.length_);
312 #if defined(USE_SSL_CRYPTO)
313 ret = AES_set_encrypt_key(c->key_.buf_, c->key_length_, ¶ms->aes_key_);
315 log_printf(ERROR, "failed to set cipher key (code: %d)", ret);
318 #elif defined(USE_NETTLE)
319 aes_set_encrypt_key(¶ms->ctx_, c->key_.length_, c->key_.buf_);
320 #else // USE_GCRYPT is the default
321 gcry_error_t err = gcry_cipher_setkey(params->handle_, c->key_.buf_, c->key_.length_);
323 log_printf(ERROR, "failed to set cipher key: %s", gcry_strerror(err));
328 ret = cipher_aesctr_calc_ctr(c, kd, dir, seq_nr, sender_id, mux);
330 log_printf(ERROR, "failed to calculate cipher CTR");
334 #if defined(USE_SSL_CRYPTO)
335 if(C_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
336 log_printf(ERROR, "failed to set cipher CTR: size doesn't fit");
340 memset(params->ecount_buf_, 0, AES_BLOCK_SIZE);
341 AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, ¶ms->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num);
342 #elif defined(USE_NETTLE)
343 if(C_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
344 log_printf(ERROR, "failed to set cipher CTR: size doesn't fit");
347 ctr_crypt(¶ms->ctx_, (nettle_crypt_func *)(aes_encrypt), AES_BLOCK_SIZE, params->ctr_.buf_, (ilen < olen) ? ilen : olen, out, in);
348 #else // USE_GCRYPT is the default
349 err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, C_AESCTR_CTR_LENGTH);
351 log_printf(ERROR, "failed to set cipher CTR: %s", gcry_strerror(err));
355 err = gcry_cipher_encrypt(params->handle_, out, olen, in, ilen);
357 log_printf(ERROR, "failed to de/encrypt packet: %s", gcry_strerror(err));
362 return (ilen < olen) ? ilen : olen;