OpenVPN 3 Core Library
Loading...
Searching...
No Matches
decrypt_chm.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// General-purpose OpenVPN protocol decrypt method (CBC/HMAC) that is independent of the underlying CRYPTO_API
13
14#ifndef OPENVPN_CRYPTO_DECRYPT_CHM_H
15#define OPENVPN_CRYPTO_DECRYPT_CHM_H
16
17#include <cstring>
18
29
30namespace openvpn {
31
32template <typename CRYPTO_API>
34{
35 public:
36 OPENVPN_SIMPLE_EXCEPTION(chm_unsupported_cipher_mode);
37
38 Error::Type decrypt(BufferAllocated &buf, const std::time_t now)
39 {
40 // skip null packets
41 if (!buf.size())
42 return Error::SUCCESS;
43
44 // verify the HMAC
45 if (hmac.defined())
46 {
47 unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE];
48 const size_t hmac_size = hmac.output_size();
49 const unsigned char *packet_hmac = buf.read_alloc(hmac_size);
50 hmac.hmac(local_hmac, hmac_size, buf.c_data(), buf.size());
51 if (crypto::memneq(local_hmac, packet_hmac, hmac_size))
52 {
53 buf.reset_size();
54 return Error::HMAC_ERROR;
55 }
56 }
57
58 // decrypt packet ID + payload
59 if (cipher.defined())
60 {
61 unsigned char iv_buf[CRYPTO_API::CipherContext::MAX_IV_LENGTH];
62 const size_t iv_length = cipher.iv_length();
63
64 // extract IV from head of packet
65 buf.read(iv_buf, iv_length);
66
67 // initialize work buffer
69
70 // decrypt from buf -> work
71 const size_t decrypt_bytes = cipher.decrypt(iv_buf, work.data(), work.max_size(), buf.c_data(), buf.size());
72 if (!decrypt_bytes)
73 {
74 buf.reset_size();
76 }
77 work.set_size(decrypt_bytes);
78
79 // handle different cipher modes
80 const int cipher_mode = cipher.cipher_mode();
81 if (cipher_mode == CRYPTO_API::CipherContext::CIPH_CBC_MODE)
82 {
83 if (!verify_packet_id(work, now))
84 {
85 buf.reset_size();
87 }
88 }
89 else
90 {
91 throw chm_unsupported_cipher_mode();
92 }
93
94 // return cleartext result in buf
95 buf.swap(work);
96 }
97 else // no encryption
98 {
99 if (!verify_packet_id(buf, now))
100 {
101 buf.reset_size();
102 return Error::REPLAY_ERROR;
103 }
104 }
105 return Error::SUCCESS;
106 }
107
113
114 private:
115 bool verify_packet_id(BufferAllocated &buf, const std::time_t now)
116 {
117 const PacketIDData pid = pid_recv.read_next(buf);
118 return pid_recv.test_add(pid, now, stats);
119 }
120
122};
123
124} // namespace openvpn
125
126#endif // OPENVPN_CRYPTO_DECRYPT_H
void swap(BufferAllocatedType< T_ > &other)
Swaps the contents of this BufferAllocatedType object with another BufferAllocatedType object.
Definition buffer.hpp:1799
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1194
size_t max_size() const
Return the maximum allowable size value in T objects given the current offset (without considering re...
Definition buffer.hpp:1377
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1242
T * data()
Get a mutable pointer to the start of the array.
Definition buffer.hpp:1450
auto * read_alloc(const size_t size)
Allocate memory and read data from the buffer into the allocated memory.
Definition buffer.hpp:1343
void set_size(const size_t size)
After an external method, operating on the array as a mutable unsigned char buffer,...
Definition buffer.hpp:1384
void reset_size()
Resets the size of the buffer to zero.
Definition buffer.hpp:1170
void read(NCT *data, const size_t size)
Read data from the buffer into the specified memory location.
Definition buffer.hpp:1331
SessionStats::Ptr stats
OPENVPN_SIMPLE_EXCEPTION(chm_unsupported_cipher_mode)
bool verify_packet_id(BufferAllocated &buf, const std::time_t now)
OvpnHMAC< CRYPTO_API > hmac
Error::Type decrypt(BufferAllocated &buf, const std::time_t now)
CipherContext< CRYPTO_API > cipher
PacketIDDataReceive pid_recv
BufferAllocated work
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:266
PacketIDData read_next(Buffer &buf) const
bool test_add(const PacketIDData &pin, const Time::base_type now, const SessionStats::Ptr &stats)
bool memneq(const void *a, const void *b, size_t size)
Definition memneq.hpp:79