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