/* SPDX-License-Identifier: GPL-2.0-only */

#include <ppm/crypto.h>

#include <stdio.h>
#include <string.h>

/*
 * SHA-512 of the empty string, well-known test vector:
 *   cf83e1357eefb8bd...e2a9ac94fa54ca49f
 */
static const char SHA512_EMPTY_HEX[] =
    "cf83e1357eefb8bdf1542850d66d8007"
    "d620e4050b5715dc83f4a921d36ce9ce"
    "47d0d13c5d85f2b0ff8318d2877eec2f"
    "63b931bd47417a81a538327af927da3e";

#define CHECK(expr) do {                                            \
    if (!(expr)) {                                                  \
        fprintf(stderr, "FAIL: %s:%d: %s\n", __FILE__, __LINE__, #expr); \
        return 1;                                                   \
    }                                                               \
} while (0)

int main(void) {
    CHECK(ppm_crypto_init() == PPM_OK);

    /* Empty buffer hash. */
    ppm_sha512_t h;
    CHECK(ppm_sha512_buf("", 0, &h) == PPM_OK);

    char hex[PPM_SHA512_HEX_BUFSZ];
    ppm_sha512_to_hex(&h, hex);
    CHECK(strcmp(hex, SHA512_EMPTY_HEX) == 0);

    /* Streaming should match one-shot. */
    ppm_sha512_ctx_t *ctx = NULL;
    CHECK(ppm_sha512_init(&ctx) == PPM_OK);
    CHECK(ppm_sha512_update(ctx, "abc", 3) == PPM_OK);
    ppm_sha512_t streamed;
    CHECK(ppm_sha512_final(ctx, &streamed) == PPM_OK);
    ppm_sha512_free(ctx);

    ppm_sha512_t oneshot;
    CHECK(ppm_sha512_buf("abc", 3, &oneshot) == PPM_OK);
    CHECK(ppm_sha512_equal(&streamed, &oneshot));

    /* Hex round-trip. */
    ppm_sha512_t parsed;
    CHECK(ppm_sha512_from_hex(SHA512_EMPTY_HEX, &parsed) == PPM_OK);
    CHECK(ppm_sha512_equal(&parsed, &h));

    /* Constant-time inequality. */
    ppm_sha512_t other;
    CHECK(ppm_sha512_buf("x", 1, &other) == PPM_OK);
    CHECK(!ppm_sha512_equal(&other, &h));

    printf("ok\n");
    return 0;
}
