doing replay protection before learning remote host
[anytun.git] / src / authAlgo.cpp
blob6bbf65113f254700c9ffd05afb219058bbb54866
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-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
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.
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.
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/>.
32 #include "authAlgo.h"
33 #include "log.h"
34 #include "buffer.h"
35 #include "encryptedPacket.h"
37 #include <iostream>
38 #include <cstring>
40 //****** NullAuthAlgo ******
41 void NullAuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet)
45 bool NullAuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet)
47 return true;
50 #ifndef NOCRYPT
51 //****** Sha1AuthAlgo ******
53 Sha1AuthAlgo::Sha1AuthAlgo(kd_dir_t d) : AuthAlgo(d), key_(DIGEST_LENGTH)
55 #ifndef USE_SSL_CRYPTO
56 gcry_error_t err = gcry_md_open(&handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
57 if(err) {
58 cLog.msg(Log::PRIO_CRIT) << "Sha1AuthAlgo::Sha1AuthAlgo: Failed to open message digest algo";
59 return;
61 #else
62 HMAC_CTX_init(&ctx_);
63 HMAC_Init_ex(&ctx_, NULL, 0, EVP_sha1(), NULL);
64 #endif
67 Sha1AuthAlgo::~Sha1AuthAlgo()
69 #ifndef USE_SSL_CRYPTO
70 if(handle_)
71 gcry_md_close(handle_);
72 #else
73 HMAC_CTX_cleanup(&ctx_);
74 #endif
77 void Sha1AuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet)
79 #ifndef USE_SSL_CRYPTO
80 if(!handle_)
81 return;
82 #endif
84 packet.addAuthTag();
85 if(!packet.getAuthTagLength())
86 return;
88 kd.generate(dir_, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
89 #ifndef USE_SSL_CRYPTO
90 gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength());
91 if(err) {
92 cLog.msg(Log::PRIO_ERR) << "Sha1AuthAlgo::setKey: Failed to set hmac key: " << LogGpgError(err);
93 return;
96 gcry_md_reset(handle_);
97 gcry_md_write(handle_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength());
98 gcry_md_final(handle_);
99 u_int8_t* hmac = gcry_md_read(handle_, 0);
100 #else
101 HMAC_Init_ex(&ctx_, key_.getBuf(), key_.getLength(), EVP_sha1(), NULL);
103 u_int8_t hmac[DIGEST_LENGTH];
104 HMAC_Update(&ctx_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength());
105 HMAC_Final(&ctx_, hmac, NULL);
106 #endif
108 u_int8_t* tag = packet.getAuthTag();
109 u_int32_t length = (packet.getAuthTagLength() < DIGEST_LENGTH) ? packet.getAuthTagLength() : DIGEST_LENGTH;
111 if(length > DIGEST_LENGTH)
112 std::memset(tag, 0, packet.getAuthTagLength());
114 std::memcpy(&tag[packet.getAuthTagLength() - length], &hmac[DIGEST_LENGTH - length], length);
117 bool Sha1AuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet)
119 #ifndef USE_SSL_CRYPTO
120 if(!handle_)
121 return false;
122 #endif
124 packet.withAuthTag(true);
125 if(!packet.getAuthTagLength())
126 return true;
128 kd.generate(dir_, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
129 #ifndef USE_SSL_CRYPTO
130 gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength());
131 if(err) {
132 cLog.msg(Log::PRIO_ERR) << "Sha1AuthAlgo::setKey: Failed to set hmac key: " << LogGpgError(err);
133 return false;
136 gcry_md_reset(handle_);
137 gcry_md_write(handle_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength());
138 gcry_md_final(handle_);
139 u_int8_t* hmac = gcry_md_read(handle_, 0);
140 #else
141 HMAC_Init_ex(&ctx_, key_.getBuf(), key_.getLength(), EVP_sha1(), NULL);
143 u_int8_t hmac[DIGEST_LENGTH];
144 HMAC_Update(&ctx_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength());
145 HMAC_Final(&ctx_, hmac, NULL);
146 #endif
148 u_int8_t* tag = packet.getAuthTag();
149 u_int32_t length = (packet.getAuthTagLength() < DIGEST_LENGTH) ? packet.getAuthTagLength() : DIGEST_LENGTH;
151 if(length > DIGEST_LENGTH)
152 for(u_int32_t i=0; i < (packet.getAuthTagLength() - DIGEST_LENGTH); ++i)
153 if(tag[i]) return false;
155 int ret = std::memcmp(&tag[packet.getAuthTagLength() - length], &hmac[DIGEST_LENGTH - length], length);
156 packet.removeAuthTag();
158 if(ret)
159 return false;
161 return true;
165 #endif