#include <string.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char *argv[])
{
int ret = EXIT_FAILURE;
OSSL_LIB_CTX *library_context = NULL;
BIO *input = NULL;
BIO *bio_digest = NULL, *reading = NULL;
EVP_MD *md = NULL;
unsigned char buffer[512];
int digest_size;
char *digest_value = NULL;
int j;
input = BIO_new_fd(fileno(stdin), 1);
if (input == NULL) {
fprintf(stderr, "BIO_new_fd() for stdin returned NULL\n");
goto cleanup;
}
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto cleanup;
}
md = EVP_MD_fetch(library_context, "SHA3-512", NULL);
if (md == NULL) {
fprintf(stderr, "EVP_MD_fetch did not find SHA3-512.\n");
goto cleanup;
}
digest_size = EVP_MD_get_size(md);
if (digest_size <= 0) {
fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
goto cleanup;
}
digest_value = OPENSSL_malloc(digest_size);
if (digest_value == NULL) {
fprintf(stderr, "Can't allocate %lu bytes for the digest value.\n", (unsigned long)digest_size);
goto cleanup;
}
bio_digest = BIO_new(BIO_f_md());
if (bio_digest == NULL) {
fprintf(stderr, "BIO_new(BIO_f_md()) returned NULL\n");
goto cleanup;
}
if (BIO_set_md(bio_digest, md) != 1) {
fprintf(stderr, "BIO_set_md failed.\n");
goto cleanup;
}
reading = BIO_push(bio_digest, input);
while (BIO_read(reading, buffer, sizeof(buffer)) > 0)
;
if (BIO_gets(bio_digest, digest_value, digest_size) != digest_size) {
fprintf(stderr, "BIO_gets(bio_digest) failed\n");
goto cleanup;
}
for (j = 0; j < digest_size; j++) {
fprintf(stdout, "%02x", (unsigned char)digest_value[j]);
}
fprintf(stdout, "\n");
ret = EXIT_SUCCESS;
cleanup:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
OPENSSL_free(digest_value);
BIO_free(input);
BIO_free(bio_digest);
EVP_MD_free(md);
OSSL_LIB_CTX_free(library_context);
return ret;
}