Imported Upstream version 0.3
[anytun.git] / src / encryptedPacket.cpp
1 /*
2  *  anytun
3  *
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.
12  *
13  *
14  *  Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl, 
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
19  *  Anytun is free software: you can redistribute it and/or modify
20  *  it under the terms of the GNU General Public License version 3 as
21  *  published by the Free Software Foundation.
22  *
23  *  Anytun is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.
30  */
31
32 #include <stdexcept>
33 #include <iostream>
34 #include <cstdio>       // for std::memcpy
35
36 #include "encryptedPacket.h"
37 #include "endian.h"
38 #include "datatypes.h"
39 #include "log.h"
40 #include "anytunError.h"
41
42 EncryptedPacket::EncryptedPacket(u_int32_t payload_length, u_int32_t auth_tag_length, bool allow_realloc)
43   : Buffer(payload_length + sizeof(struct HeaderStruct), allow_realloc), auth_tag_length_(auth_tag_length)
44 {
45   header_ = reinterpret_cast<struct HeaderStruct*>(buf_);
46   payload_ = buf_ + sizeof(struct HeaderStruct);
47   auth_tag_ = NULL;
48   if(header_)
49   {
50     header_->seq_nr = 0;
51     header_->sender_id = 0;
52     header_->mux = 0;
53   }
54 }
55
56 u_int32_t EncryptedPacket::getHeaderLength()
57 {
58   return sizeof(struct HeaderStruct);
59 }
60
61 seq_nr_t EncryptedPacket::getSeqNr() const
62 {
63   if(header_)
64     return SEQ_NR_T_NTOH(header_->seq_nr);
65   
66   return 0;
67 }
68
69 sender_id_t EncryptedPacket::getSenderId() const
70 {
71   if(header_)
72     return SENDER_ID_T_NTOH(header_->sender_id);
73
74   return 0;
75 }
76
77 mux_t EncryptedPacket::getMux() const
78 {
79   if(header_)
80     return MUX_T_NTOH(header_->mux);
81
82   return 0;
83 }
84
85 void EncryptedPacket::setSeqNr(seq_nr_t seq_nr)
86 {
87   if(header_)
88     header_->seq_nr = SEQ_NR_T_HTON(seq_nr);
89 }
90
91 void EncryptedPacket::setSenderId(sender_id_t sender_id)
92 {
93   if(header_)
94     header_->sender_id = SENDER_ID_T_HTON(sender_id);
95 }
96
97 void EncryptedPacket::setMux(mux_t mux)
98 {
99   if(header_)
100     header_->mux = MUX_T_HTON(mux);
101 }
102
103 void EncryptedPacket::setHeader(seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
104 {
105   if(!header_)
106     return;
107
108   header_->seq_nr = SEQ_NR_T_HTON(seq_nr);
109   header_->sender_id = SENDER_ID_T_HTON(sender_id);
110   header_->mux = MUX_T_HTON(mux);
111 }
112
113 u_int32_t EncryptedPacket::getPayloadLength() const
114 {
115   if(!payload_) 
116     return 0;
117
118   if(!auth_tag_)
119     return (length_ > sizeof(struct HeaderStruct)) ? (length_ - sizeof(struct HeaderStruct)) : 0;
120   
121   return (length_ > (sizeof(struct HeaderStruct) + auth_tag_length_)) ? (length_ - sizeof(struct HeaderStruct) - auth_tag_length_) : 0;
122 }
123
124 void EncryptedPacket::setPayloadLength(u_int32_t payload_length)
125 {
126   Buffer::setLength(payload_length + sizeof(struct HeaderStruct));
127       // depending on allow_realloc buf_ may point to another address
128       // therefore in this case reinit() gets called by Buffer::setLength()
129 }
130
131 void EncryptedPacket::reinit()
132 {
133   header_ = reinterpret_cast<struct HeaderStruct*>(buf_);
134   payload_ = buf_ + sizeof(struct HeaderStruct);
135   
136   if(length_ <= (sizeof(struct HeaderStruct)))
137     payload_ = NULL;
138   
139   if(length_ < (sizeof(struct HeaderStruct))) {
140     header_ = NULL;
141     AnytunError::throwErr() << "encrypted packet can't be initialized, buffer is too small"; 
142   }  
143   
144   if(auth_tag_)
145   {
146     if(length_ < (sizeof(struct HeaderStruct) + auth_tag_length_)) {
147       auth_tag_ = NULL;
148       AnytunError::throwErr() << "auth-tag can't be enabled, buffer is too small"; 
149     }
150     auth_tag_ = buf_ + length_ - auth_tag_length_;
151   }  
152 }
153
154 u_int8_t* EncryptedPacket::getPayload()
155 {
156   return payload_;
157 }
158
159 u_int8_t* EncryptedPacket::getAuthenticatedPortion()
160 {
161   return buf_;
162 }
163
164 u_int32_t EncryptedPacket::getAuthenticatedPortionLength()
165 {
166   if(!buf_)
167     return 0;
168
169   if(!auth_tag_)
170     return length_;
171   
172   return (length_ > auth_tag_length_) ? (length_ - auth_tag_length_) : 0;
173 }
174
175 void EncryptedPacket::withAuthTag(bool b)
176 {
177   if((b && auth_tag_) || (!b && !auth_tag_))
178     return;
179   
180   if(b)
181   {
182     if(length_ < (sizeof(struct HeaderStruct) + auth_tag_length_))
183       AnytunError::throwErr() << "auth-tag can't be enabled, buffer is too small";
184     
185     auth_tag_ = buf_ + length_ - auth_tag_length_;
186   }
187   else
188     auth_tag_ = NULL;
189 }
190
191 void EncryptedPacket::addAuthTag()
192 {
193   if(auth_tag_)
194     return;
195
196   auth_tag_ = buf_; // will be set to the correct value @ reinit
197   setLength(length_ + auth_tag_length_);
198   if(auth_tag_ == buf_) // reinit was not called by setLength
199     reinit();
200 }
201
202 void EncryptedPacket::removeAuthTag()
203 {
204   if(!auth_tag_)
205     return;
206
207   auth_tag_ = NULL;
208   setLength(length_ - auth_tag_length_);
209 }
210
211 u_int8_t* EncryptedPacket::getAuthTag()
212 {
213   return auth_tag_;
214 }
215
216 u_int32_t EncryptedPacket::getAuthTagLength()
217 {
218   if(auth_tag_)
219     return auth_tag_length_;
220
221   return 0;
222 }