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 OpenSSL digest API defined in <openssl/evp.h>
13// so that it can be used as part of the crypto layer of the OpenVPN core.
14
15#ifndef OPENVPN_OPENSSL_CRYPTO_DIGEST_H
16#define OPENVPN_OPENSSL_CRYPTO_DIGEST_H
17
18#include <string>
19
20#include <openssl/opensslv.h>
21#include <openssl/objects.h>
22#include <openssl/evp.h>
23#include <openssl/md4.h>
24#include <openssl/md5.h>
25#include <openssl/sha.h>
26#include <openssl/hmac.h>
27
32
34
35namespace openvpn::OpenSSLCrypto {
36class HMACContext;
37
39{
40 DigestContext(const DigestContext &) = delete;
42
43 /* In OpenSSL 3.0 the method that returns EVP_MD, the cipher needs to be
44 * freed afterwards, thus needing a non-const type. In contrast, OpenSSL 1.1.1
45 * and lower returns a const type, needing a const type */
46#if OPENSSL_VERSION_NUMBER < 0x30000000L
47 using evp_md_type = const EVP_MD;
48#else
49 using evp_md_type = EVP_MD;
50#endif
51
52 public:
53 friend class HMACContext;
54
55 OPENVPN_SIMPLE_EXCEPTION(openssl_digest_uninitialized);
56 OPENVPN_EXCEPTION(openssl_digest_error);
57
58 enum
59 {
60 MAX_DIGEST_SIZE = EVP_MAX_MD_SIZE
61 };
62
63 DigestContext() = default;
64
66 {
67 ctx.reset(EVP_MD_CTX_new());
68
69 md.reset(digest_type(alg, libctx));
70 if (!EVP_DigestInit(ctx.get(), md.get()))
71 {
73 throw openssl_digest_error("EVP_DigestInit");
74 }
75 }
76
77 void update(const unsigned char *in, const size_t size)
78 {
79 if (!EVP_DigestUpdate(ctx.get(), in, int(size)))
80 {
82 throw openssl_digest_error("EVP_DigestUpdate");
83 }
84 }
85
86 size_t final(unsigned char *out)
87 {
88 unsigned int outlen;
89 if (!EVP_DigestFinal(ctx.get(), out, &outlen))
90 {
92 throw openssl_digest_error("EVP_DigestFinal");
93 }
94 return outlen;
95 }
96
97 size_t size() const
98 {
99 return EVP_MD_CTX_size(ctx.get());
100 }
101
102 private:
104 {
105 switch (alg)
106 {
107 case CryptoAlgs::MD4:
108 case CryptoAlgs::MD5:
109 case CryptoAlgs::SHA1:
114 return EVP_MD_fetch(libctx, CryptoAlgs::name(alg), NULL);
115 default:
116 OPENVPN_THROW(openssl_digest_error, CryptoAlgs::name(alg) << ": not usable");
117 }
118 }
119
120 using MD_unique_ptr = std::unique_ptr<evp_md_type, decltype(&::EVP_MD_free)>;
122
123 using EVP_MD_CTX_unique_ptr = std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
124 EVP_MD_CTX_unique_ptr ctx{nullptr, ::EVP_MD_CTX_free};
125};
126} // namespace openvpn::OpenSSLCrypto
127
128#endif
void update(const unsigned char *in, const size_t size)
Definition digest.hpp:77
DigestContext(const DigestContext &)=delete
DigestContext(const CryptoAlgs::Type alg, SSLLib::Ctx libctx)
Definition digest.hpp:65
std::unique_ptr< EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)> EVP_MD_CTX_unique_ptr
Definition digest.hpp:123
DigestContext & operator=(const DigestContext &)=delete
OPENVPN_EXCEPTION(openssl_digest_error)
OPENVPN_SIMPLE_EXCEPTION(openssl_digest_uninitialized)
std::unique_ptr< evp_md_type, decltype(&::EVP_MD_free)> MD_unique_ptr
Definition digest.hpp:120
static evp_md_type * digest_type(const CryptoAlgs::Type alg, SSLLib::Ctx libctx)
Definition digest.hpp:103
static void EVP_MD_free(const EVP_MD *md)
Definition compat.hpp:110
static const EVP_MD * EVP_MD_fetch(void *, const char *algorithm, const char *)
Definition compat.hpp:104
#define OPENVPN_THROW(exc, stuff)
const char * name(const KeyDerivation kd)
void openssl_clear_error_stack()
Definition error.hpp:239
static std::stringstream out
Definition test_path.cpp:10