1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
// Wrap the mbed TLS HMAC API defined in <mbedtls/md.h> so
// that it can be used as part of the crypto layer of the OpenVPN core.
#ifndef OPENVPN_MBEDTLS_CRYPTO_HMAC_H
#define OPENVPN_MBEDTLS_CRYPTO_HMAC_H
#include <string>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/mbedtls/crypto/digest.hpp>
#include <openvpn/mbedtls/mbedtls_compat.hpp>
namespace openvpn::MbedTLSCrypto {
class HMACContext
{
HMACContext(const HMACContext &) = delete;
HMACContext &operator=(const HMACContext &) = delete;
public:
OPENVPN_SIMPLE_EXCEPTION(mbedtls_hmac_uninitialized);
OPENVPN_EXCEPTION(mbedtls_hmac_error);
enum
{
MAX_HMAC_SIZE = MBEDTLS_MD_MAX_SIZE
};
HMACContext()
: initialized(false)
{
}
HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
: initialized(false)
{
init(digest, key, key_size);
}
~HMACContext()
{
erase();
}
void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
{
erase();
mbedtls_md_init(&ctx);
if (mbedtls_md_setup(&ctx, DigestContext::digest_type(digest), 1) < 0)
throw mbedtls_hmac_error("mbedtls_md_setup");
if (mbedtls_md_hmac_starts(&ctx, key, key_size) < 0)
throw mbedtls_hmac_error("mbedtls_md_hmac_starts");
initialized = true;
}
void reset()
{
check_initialized();
if (mbedtls_md_hmac_reset(&ctx) < 0)
throw mbedtls_hmac_error("mbedtls_md_hmac_reset");
}
void update(const unsigned char *in, const size_t size)
{
check_initialized();
if (mbedtls_md_hmac_update(&ctx, in, size) < 0)
throw mbedtls_hmac_error("mbedtls_md_hmac_update");
}
size_t final(unsigned char *out)
{
check_initialized();
if (mbedtls_md_hmac_finish(&ctx, out) < 0)
throw mbedtls_hmac_error("mbedtls_md_hmac_finish");
return size_();
}
size_t size() const
{
check_initialized();
return size_();
}
bool is_initialized() const
{
return initialized;
}
private:
void erase()
{
if (initialized)
{
mbedtls_md_free(&ctx);
initialized = false;
}
}
size_t size_() const
{
return mbedtls_md_get_size(mbedtls_md_info_from_ctx(&ctx));
}
void check_initialized() const
{
#ifdef OPENVPN_ENABLE_ASSERT
if (!initialized)
throw mbedtls_hmac_uninitialized();
#endif
}
bool initialized;
mbedtls_md_context_t ctx;
};
} // namespace openvpn::MbedTLSCrypto
#endif
|