finallly working, payload type needs further checks
[anytun.git] / cypher.cpp
blobaa305cabdbed57e3945d3d972dc59b28c309233c
1 /*
2 * anytun
4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methodes used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007 anytun.org <satp@wirdorange.org>
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2
18 * as published by the Free Software Foundation.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program (see the file COPYING included with this
27 * distribution); if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <stdexcept>
32 #include <iostream>
33 #include <string>
34 #include <cstdio>
35 #include <gcrypt.h>
37 #include "cypher.h"
38 #include "mpi.h"
39 #include "log.h"
41 void Cypher::encrypt(const PlainPacket & in,EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id)
43 cypher(out.payload_, in.complete_payload_ , in.complete_payload_length_, seq_nr, sender_id);
44 out.setSenderId(sender_id);
45 out.setSeqNr(seq_nr);
46 out.setPayloadLength(in.complete_payload_length_);
49 void Cypher::decrypt(const EncryptedPacket & in,PlainPacket & out)
51 cypher(out.complete_payload_, in.payload_ , in.payload_length_, in.getSeqNr(), in.getSenderId());
52 out.setCompletePayloadLength(in.payload_length_);
55 void NullCypher::cypher(u_int8_t * out, u_int8_t * in, u_int32_t length, seq_nr_t seq_nr, sender_id_t sender_id)
57 std::memcpy(out, in, length );
60 const char* AesIcmCypher::MIN_GCRYPT_VERSION = "1.2.3";
62 AesIcmCypher::AesIcmCypher() : salt_(Buffer(14))
64 gcry_error_t err;
66 // No other library has already initialized libgcrypt.
67 if( !gcry_control(GCRYCTL_ANY_INITIALIZATION_P) )
69 if( !gcry_check_version( MIN_GCRYPT_VERSION ) ) {
70 cLog.msg(Log::PRIO_ERR) << "AesIcmCypher::AesIcmCypher: Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION;
71 return;
74 /* Allocate a pool of secure memory. This also drops priviliges
75 on some systems. */
76 err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0);
77 if( err ) {
78 cLog.msg(Log::PRIO_ERR) << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: " << gpg_strerror( err );
79 return;
82 /* Tell Libgcrypt that initialization has completed. */
83 err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
84 if( err ) {
85 cLog.msg(Log::PRIO_CRIT) << "AesIcmCypher::AesIcmCypher: Failed to finish the initialization of libgcrypt: " << gpg_strerror( err );
86 return;
87 } else {
88 cLog.msg(Log::PRIO_DEBUG) << "AesIcmCypher::AesIcmCypher: libgcrypt init finished";
92 err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 );
93 if( err )
94 cLog.msg(Log::PRIO_CRIT) << "AesIcmCypher::AesIcmCypher: Failed to open cypher";
98 AesIcmCypher::~AesIcmCypher()
100 gcry_cipher_close( cipher_ );
101 cLog.msg(Log::PRIO_DEBUG) << "AesIcmCypher::~AesIcmCypher: closed cipher";
105 void AesIcmCypher::setKey(Buffer key)
107 gcry_error_t err;
108 // FIXXME: hardcoded keysize
109 err = gcry_cipher_setkey( cipher_, key.getBuf(), 16 );
110 if( err )
111 cLog.msg(Log::PRIO_ERR) << "AesIcmCypher::setKey: Failed to set cipher key: " << gpg_strerror( err );
114 void AesIcmCypher::setSalt(Buffer salt)
116 salt_ = salt;
119 void AesIcmCypher::cypher(u_int8_t * out, u_int8_t * in, u_int32_t length, seq_nr_t seq_nr, sender_id_t sender_id)
121 gcry_error_t err;
123 // set the IV
124 //==========================================================================
125 // // where the 128-bit integer value IV SHALL be defined by the SSRC, the
126 // // SRTP packet index i, and the SRTP session salting key k_s, as below.
127 // //
128 // // IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
129 // // sizeof(k_s) = 112 bit, random
131 Mpi iv(128);
132 Mpi salt = Mpi(salt_.getBuf(), salt_.getLength());
133 Mpi sid = sender_id;
134 Mpi seq = seq_nr;
136 iv = salt.mul2exp(16) ^ sid.mul2exp(64) ^ seq.mul2exp(16);
138 u_int8_t *iv_buf = iv.getNewBuf(16);
139 err = gcry_cipher_setiv( cipher_, iv_buf, 16 );
140 delete[] iv_buf;
141 if( err ) {
142 cLog.msg(Log::PRIO_ERR) << "AesIcmCypher: Failed to set cipher IV: " << gpg_strerror( err );
143 return;
146 err = gcry_cipher_reset( cipher_ );
147 if( err ) {
148 cLog.msg(Log::PRIO_ERR) << "AesIcmCypher: Failed to reset cipher: " << gpg_strerror( err );
149 return;
152 err = gcry_cipher_encrypt( cipher_, out, length, in, length );
153 if( err ) {
154 cLog.msg(Log::PRIO_ERR) << "AesIcmCypher: Failed to generate cipher bitstream: " << gpg_strerror( err );
155 return;