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.
 */
openSUSE Build Service is sponsored by