File crypto-openssl-10.cpp of Package failed_git-crypt
/*
* Minimal OpenSSL-1.0 compatible glue for git-crypt.
*
* This file provides AES-ECB encryption and HMAC-SHA1 state handling
* using OpenSSL APIs. It has been adjusted to work with OpenSSL 3.0+
* where HMAC_CTX is an opaque type and must be handled via pointers
* (HMAC_CTX_new / HMAC_CTX_free) instead of stack-allocated structs
* and HMAC_cleanup.
*
* Only the symbols actually used by the rest of git-crypt are exposed
* here in a small, self-contained implementation.
*/
#include <cstring>
#include <cstdint>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
class Aes_ecb_encryptor {
public:
explicit Aes_ecb_encryptor(const unsigned char *raw_key);
~Aes_ecb_encryptor() = default;
void encrypt(const unsigned char *plain, unsigned char *cipher);
private:
struct Impl {
AES_KEY key;
};
Impl *impl;
};
Aes_ecb_encryptor::Aes_ecb_encryptor(const unsigned char *raw_key)
{
impl = new Impl();
// KEY_LEN historically 16 for AES-128 in this codebase.
// To be robust, derive from AES_BLOCK_SIZE if needed; keep 16 bytes as earlier behavior.
const int KEY_LEN = 16;
AES_set_encrypt_key(raw_key, KEY_LEN * 8, &impl->key);
}
void Aes_ecb_encryptor::encrypt(const unsigned char *plain, unsigned char *cipher)
{
AES_encrypt(plain, cipher, &impl->key);
}
/* HMAC-SHA1 state wrapper.
*
* OpenSSL 3 defines HMAC_CTX as an opaque structure; you must use
* HMAC_CTX_new() / HMAC_CTX_free(). Older code may have used a stack
* HMAC_CTX and HMAC_cleanup(), which is not available with the opaque
* type. Wrap it here and expose the simple operations needed.
*/
class Hmac_sha1_state {
public:
Hmac_sha1_state();
~Hmac_sha1_state();
void init(const unsigned char *key, size_t keylen);
void update(const unsigned char *data, size_t len);
void finish(unsigned char *out, unsigned int *outlen);
private:
struct Impl {
HMAC_CTX *ctx;
Impl() : ctx(nullptr) {}
};
Impl *impl;
};
Hmac_sha1_state::Hmac_sha1_state()
{
impl = new Impl();
impl->ctx = HMAC_CTX_new();
// No key yet; user must call init() with the key.
}
Hmac_sha1_state::~Hmac_sha1_state()
{
if (impl) {
if (impl->ctx) {
HMAC_CTX_free(impl->ctx);
impl->ctx = nullptr;
}
delete impl;
impl = nullptr;
}
}
void Hmac_sha1_state::init(const unsigned char *key, size_t keylen)
{
// Initialize HMAC with SHA1 and provided key.
// HMAC_Init_ex returns 1 on success.
if (!impl->ctx) {
impl->ctx = HMAC_CTX_new();
}
HMAC_Init_ex(impl->ctx, key, static_cast<int>(keylen), EVP_sha1(), nullptr);
}
void Hmac_sha1_state::update(const unsigned char *data, size_t len)
{
if (impl->ctx) {
HMAC_Update(impl->ctx, data, len);
}
}
void Hmac_sha1_state::finish(unsigned char *out, unsigned int *outlen)
{
if (impl->ctx) {
HMAC_Final(impl->ctx, out, outlen);
} else if (outlen) {
*outlen = 0;
}
}
/* The rest of the program expects to be able to create these objects
* and call the methods above. This file intentionally limits itself
* to the minimal API used by the project and keeps changes small:
* - Switch stack HMAC_CTX to pointer-based usage (compatible with OpenSSL 3)
* - Replace HMAC_cleanup usage with HMAC_CTX_free
*
* No other behavior was changed.
*/