OpenVPN 3 Core Library
Loading...
Searching...
No Matches
digest.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// Wrap the Apple digest API defined in <CommonCrypto/CommonDigest.h>
13// so that it can be used as part of the crypto layer of the OpenVPN core.
14
15#ifndef OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H
16#define OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H
17
18#include <string>
19
20#include <CommonCrypto/CommonDigest.h>
21#include <CommonCrypto/CommonHMAC.h>
22
28
31#define OPENVPN_DIGEST_CONTEXT(TYPE) CC_##TYPE##_CTX TYPE##_ctx
32
33#define OPENVPN_DIGEST_ALG_CLASS(TYPE) \
34 class DigestAlgorithm##TYPE : public DigestAlgorithm \
35 { \
36 public: \
37 DigestAlgorithm##TYPE() \
38 { \
39 } \
40 int init(DigestCTX &ctx) const override \
41 { \
42 return CC_##TYPE##_Init(&ctx.u.TYPE##_ctx); \
43 } \
44 int update(DigestCTX &ctx, const unsigned char *data, size_t size) const override \
45 { \
46 return CC_##TYPE##_Update(&ctx.u.TYPE##_ctx, data, size); \
47 } \
48 int final(DigestCTX &ctx, unsigned char *md) const override \
49 { \
50 return CC_##TYPE##_Final(md, &ctx.u.TYPE##_ctx); \
51 } \
52 }
53
54#define OPENVPN_DIGEST_ALG_DECLARE(TYPE) const DigestAlgorithm##TYPE alg_##TYPE;
55
56#define OPENVPN_DIGEST_INFO_DECLARE(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, kCCHmacAlg##TYPE)
57
58#define OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, DigestInfo::NO_HMAC_ALG)
59
60namespace openvpn::AppleCrypto {
61typedef CC_SHA256_CTX CC_SHA224_CTX;
62typedef CC_SHA512_CTX CC_SHA384_CTX;
63
64struct DigestCTX
65{
66 union {
67 OPENVPN_DIGEST_CONTEXT(MD4);
68 OPENVPN_DIGEST_CONTEXT(MD5);
69 OPENVPN_DIGEST_CONTEXT(SHA1);
70 OPENVPN_DIGEST_CONTEXT(SHA224);
71 OPENVPN_DIGEST_CONTEXT(SHA256);
72 OPENVPN_DIGEST_CONTEXT(SHA384);
73 OPENVPN_DIGEST_CONTEXT(SHA512);
74 } u;
75};
76
77struct DigestAlgorithm
78{
79 virtual int init(DigestCTX &ctx) const = 0;
80 virtual int update(DigestCTX &ctx, const unsigned char *data, size_t size) const = 0;
81 virtual int final(DigestCTX &ctx, unsigned char *md) const = 0;
82};
83
84// individual digest algorithm classes (each inherits from DigestAlgorithm)
85OPENVPN_DIGEST_ALG_CLASS(MD4);
86OPENVPN_DIGEST_ALG_CLASS(MD5);
87OPENVPN_DIGEST_ALG_CLASS(SHA1);
88OPENVPN_DIGEST_ALG_CLASS(SHA224);
89OPENVPN_DIGEST_ALG_CLASS(SHA256);
90OPENVPN_DIGEST_ALG_CLASS(SHA384);
91OPENVPN_DIGEST_ALG_CLASS(SHA512);
92
94
96{
97 public:
98 enum
99 {
100 NO_HMAC_ALG = -1
101 };
102
103 DigestInfo(CryptoAlgs::Type type,
104 const DigestAlgorithm *digest_alg,
105 const CCHmacAlgorithm hmac_alg)
106 : type_(type),
107 digest_alg_(digest_alg),
108 hmac_alg_(hmac_alg)
109 {
110 }
111
112 CryptoAlgs::Type type() const
113 {
114 return type_;
115 }
116 const char *name() const
117 {
118 return CryptoAlgs::name(type_);
119 }
120 size_t size() const
121 {
122 return CryptoAlgs::size(type_);
123 }
124 const DigestAlgorithm *digest_alg() const
125 {
126 return digest_alg_;
127 }
128 CCHmacAlgorithm hmac_alg() const
129 {
130 return hmac_alg_;
131 }
132
133 private:
134 CryptoAlgs::Type type_;
135 const DigestAlgorithm *digest_alg_;
136 CCHmacAlgorithm hmac_alg_;
137};
138
139// instantiate individual digest algorithm class instances (each inherits from DigestAlgorithm),
140// naming convention is alg_TYPE
148
149// instantiate individual digest info class instances (each is a DigestInfo),
150// naming convention is info_TYPE
158
159class HMACContext;
160
162{
163 DigestContext(const DigestContext &) = delete;
165
166 public:
167 friend class HMACContext;
168
169 OPENVPN_SIMPLE_EXCEPTION(apple_digest_uninitialized);
170 OPENVPN_SIMPLE_EXCEPTION(apple_digest_final_overflow);
171 OPENVPN_EXCEPTION(apple_digest_error);
172
173 enum
174 {
175 MAX_DIGEST_SIZE = CC_SHA512_DIGEST_LENGTH // largest known is SHA512
176 };
177
179 {
180 clear();
181 }
182
183 DigestContext(const CryptoAlgs::Type alg)
184 {
185 init(alg);
186 }
187
188 void init(const CryptoAlgs::Type alg)
189 {
190 clear();
191 info = digest_type(alg);
192 meth = info->digest_alg();
193 if (meth->init(ctx) != 1)
194 throw apple_digest_error("init");
195 initialized = true;
196 }
197
198 void update(const unsigned char *in, const size_t size)
199 {
200 check_initialized();
201 if (meth->update(ctx, in, size) != 1)
202 throw apple_digest_error("update");
203 }
204
205 size_t final(unsigned char *out)
206 {
207 check_initialized();
208 if (meth->final(ctx, out) != 1)
209 throw apple_digest_error("final");
210 return info->size();
211 }
212
213 size_t size() const
214 {
215 check_initialized();
216 return info->size();
217 }
218
219 bool is_initialized() const
220 {
221 return initialized;
222 }
223
224 private:
225 static const DigestInfo *digest_type(const CryptoAlgs::Type alg)
226 {
227 switch (alg)
228 {
229 case CryptoAlgs::MD4:
230 return &info_MD4;
231 case CryptoAlgs::MD5:
232 return &info_MD5;
233 case CryptoAlgs::SHA1:
234 return &info_SHA1;
235 case CryptoAlgs::SHA224:
236 return &info_SHA224;
237 case CryptoAlgs::SHA256:
238 return &info_SHA256;
239 case CryptoAlgs::SHA384:
240 return &info_SHA384;
241 case CryptoAlgs::SHA512:
242 return &info_SHA512;
243 default:
244 OPENVPN_THROW(apple_digest_error, CryptoAlgs::name(alg) << ": not usable");
245 }
246 }
247
248 void clear()
249 {
250 initialized = false;
251 }
252
253 void check_initialized() const
254 {
255#ifdef OPENVPN_ENABLE_ASSERT
256 if (!initialized)
257 throw apple_digest_uninitialized();
258#endif
259 }
260
263 const DigestAlgorithm *meth;
264 DigestCTX ctx;
265};
266} // namespace openvpn::AppleCrypto
267
268#undef OPENVPN_DIGEST_CONTEXT
269#undef OPENVPN_DIGEST_ALG_CLASS
270#undef OPENVPN_DIGEST_ALG_DECLARE
271#undef OPENVPN_DIGEST_INFO_DECLARE
272
273#endif
OPENVPN_DIGEST_ALG_DECLARE(MD4)
OPENVPN_DIGEST_INFO_DECLARE(MD5)
OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(MD4)
DigestCTX ctx
Definition digest.hpp:264
void check_initialized() const
Definition digest.hpp:253
void init(const CryptoAlgs::Type alg)
Definition digest.hpp:188
OPENVPN_SIMPLE_EXCEPTION(apple_digest_final_overflow)
OPENVPN_SIMPLE_EXCEPTION(apple_digest_uninitialized)
const DigestAlgorithm * meth
Definition digest.hpp:263
OPENVPN_EXCEPTION(apple_digest_error)
DigestContext & operator=(const DigestContext &)=delete
void update(const unsigned char *in, const size_t size)
Definition digest.hpp:198
static const DigestInfo * digest_type(const CryptoAlgs::Type alg)
Definition digest.hpp:225
bool is_initialized() const
Definition digest.hpp:219
size_t size() const
Definition digest.hpp:213
const DigestInfo * info
Definition digest.hpp:262
bool initialized
Definition digest.hpp:261
DigestContext(const CryptoAlgs::Type alg)
Definition digest.hpp:183
void clear()
Definition digest.hpp:248
DigestContext(const DigestContext &)=delete
const DigestAlgorithm * digest_alg() const
Definition digest.hpp:124
CryptoAlgs::Type type_
Definition digest.hpp:134
CCHmacAlgorithm hmac_alg_
Definition digest.hpp:136
const char * name() const
Definition digest.hpp:116
CryptoAlgs::Type type() const
Definition digest.hpp:112
size_t size() const
Definition digest.hpp:120
DigestInfo(CryptoAlgs::Type type, const DigestAlgorithm *digest_alg, const CCHmacAlgorithm hmac_alg)
Definition digest.hpp:103
CCHmacAlgorithm hmac_alg() const
Definition digest.hpp:128
const DigestAlgorithm * digest_alg_
Definition digest.hpp:135
#define OPENVPN_THROW(exc, stuff)
static std::stringstream out
Definition test_path.cpp:10