Path: blob/main/crypto/openssl/demos/digest/EVP_MD_stdin.c
34889 views
/*-1* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*-10* Example of using EVP_MD_fetch and EVP_Digest* methods to calculate11* a digest of static buffers12* You can find SHA3 test vectors from NIST here:13* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip14* For example, contains these lines:15Len = 8016Msg = 1ca984dcc913344370cf17MD = 6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd1481618* use xxd convert the hex message string to binary input for EVP_MD_stdin:19* echo "1ca984dcc913344370cf" | xxd -r -p | ./EVP_MD_stdin20* and then verify the output matches MD above.21*/2223#include <string.h>24#include <stdio.h>25#include <openssl/err.h>26#include <openssl/evp.h>2728/*-29* This demonstration will show how to digest data using30* a BIO created to read from stdin31*/3233static int demonstrate_digest(BIO *input)34{35OSSL_LIB_CTX *library_context = NULL;36int ret = 0;37const char *option_properties = NULL;38EVP_MD *message_digest = NULL;39EVP_MD_CTX *digest_context = NULL;40unsigned int digest_length;41unsigned char *digest_value = NULL;42unsigned char buffer[512];43unsigned int ii;4445library_context = OSSL_LIB_CTX_new();46if (library_context == NULL) {47fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");48goto cleanup;49}5051/*52* Fetch a message digest by name53* The algorithm name is case insensitive.54* See providers(7) for details about algorithm fetching55*/56message_digest = EVP_MD_fetch(library_context,57"SHA3-512", option_properties);58if (message_digest == NULL) {59fprintf(stderr, "EVP_MD_fetch could not find SHA3-512.");60ERR_print_errors_fp(stderr);61OSSL_LIB_CTX_free(library_context);62return 0;63}64/* Determine the length of the fetched digest type */65digest_length = EVP_MD_get_size(message_digest);66if (digest_length <= 0) {67fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");68goto cleanup;69}7071digest_value = OPENSSL_malloc(digest_length);72if (digest_value == NULL) {73fprintf(stderr, "No memory.\n");74goto cleanup;75}76/*77* Make a message digest context to hold temporary state78* during digest creation79*/80digest_context = EVP_MD_CTX_new();81if (digest_context == NULL) {82fprintf(stderr, "EVP_MD_CTX_new failed.\n");83ERR_print_errors_fp(stderr);84goto cleanup;85}86/*87* Initialize the message digest context to use the fetched88* digest provider89*/90if (EVP_DigestInit(digest_context, message_digest) != 1) {91fprintf(stderr, "EVP_DigestInit failed.\n");92ERR_print_errors_fp(stderr);93goto cleanup;94}95while ((ii = BIO_read(input, buffer, sizeof(buffer))) > 0) {96if (EVP_DigestUpdate(digest_context, buffer, ii) != 1) {97fprintf(stderr, "EVP_DigestUpdate() failed.\n");98goto cleanup;99}100}101if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) {102fprintf(stderr, "EVP_DigestFinal() failed.\n");103goto cleanup;104}105ret = 1;106for (ii=0; ii<digest_length; ii++) {107fprintf(stdout, "%02x", digest_value[ii]);108}109fprintf(stdout, "\n");110111cleanup:112if (ret != 1)113ERR_print_errors_fp(stderr);114/* OpenSSL free functions will ignore NULL arguments */115EVP_MD_CTX_free(digest_context);116OPENSSL_free(digest_value);117EVP_MD_free(message_digest);118119OSSL_LIB_CTX_free(library_context);120return ret;121}122123int main(void)124{125int ret = EXIT_FAILURE;126BIO *input = BIO_new_fd(fileno(stdin), 1);127128if (input != NULL) {129ret = (demonstrate_digest(input) ? EXIT_SUCCESS : EXIT_FAILURE);130BIO_free(input);131}132if (ret != EXIT_SUCCESS)133ERR_print_errors_fp(stderr);134return ret;135}136137138