1e1051a39Sopenharmony_ci/*- 2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/*- 11e1051a39Sopenharmony_ci * Example of using EVP_MD_fetch and EVP_Digest* methods to calculate 12e1051a39Sopenharmony_ci * a digest of static buffers 13e1051a39Sopenharmony_ci * You can find SHA3 test vectors from NIST here: 14e1051a39Sopenharmony_ci * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip 15e1051a39Sopenharmony_ci * For example, contains these lines: 16e1051a39Sopenharmony_ci Len = 80 17e1051a39Sopenharmony_ci Msg = 1ca984dcc913344370cf 18e1051a39Sopenharmony_ci MD = 6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd14816 19e1051a39Sopenharmony_ci * use xxd convert the hex message string to binary input for EVP_MD_stdin: 20e1051a39Sopenharmony_ci * echo "1ca984dcc913344370cf" | xxd -r -p | ./EVP_MD_stdin 21e1051a39Sopenharmony_ci * and then verify the output matches MD above. 22e1051a39Sopenharmony_ci */ 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci#include <string.h> 25e1051a39Sopenharmony_ci#include <stdio.h> 26e1051a39Sopenharmony_ci#include <openssl/err.h> 27e1051a39Sopenharmony_ci#include <openssl/evp.h> 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci/*- 30e1051a39Sopenharmony_ci * This demonstration will show how to digest data using 31e1051a39Sopenharmony_ci * a BIO created to read from stdin 32e1051a39Sopenharmony_ci */ 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ciint demonstrate_digest(BIO *input) 35e1051a39Sopenharmony_ci{ 36e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context = NULL; 37e1051a39Sopenharmony_ci int result = 0; 38e1051a39Sopenharmony_ci const char * option_properties = NULL; 39e1051a39Sopenharmony_ci EVP_MD *message_digest = NULL; 40e1051a39Sopenharmony_ci EVP_MD_CTX *digest_context = NULL; 41e1051a39Sopenharmony_ci unsigned int digest_length; 42e1051a39Sopenharmony_ci unsigned char *digest_value = NULL; 43e1051a39Sopenharmony_ci unsigned char buffer[512]; 44e1051a39Sopenharmony_ci int ii; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 47e1051a39Sopenharmony_ci if (library_context == NULL) { 48e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 49e1051a39Sopenharmony_ci goto cleanup; 50e1051a39Sopenharmony_ci } 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci /* 53e1051a39Sopenharmony_ci * Fetch a message digest by name 54e1051a39Sopenharmony_ci * The algorithm name is case insensitive. 55e1051a39Sopenharmony_ci * See providers(7) for details about algorithm fetching 56e1051a39Sopenharmony_ci */ 57e1051a39Sopenharmony_ci message_digest = EVP_MD_fetch(library_context, 58e1051a39Sopenharmony_ci "SHA3-512", option_properties); 59e1051a39Sopenharmony_ci if (message_digest == NULL) { 60e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_fetch could not find SHA3-512."); 61e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 62e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 63e1051a39Sopenharmony_ci return 0; 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci /* Determine the length of the fetched digest type */ 66e1051a39Sopenharmony_ci digest_length = EVP_MD_get_size(message_digest); 67e1051a39Sopenharmony_ci if (digest_length <= 0) { 68e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_get_size returned invalid size.\n"); 69e1051a39Sopenharmony_ci goto cleanup; 70e1051a39Sopenharmony_ci } 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci digest_value = OPENSSL_malloc(digest_length); 73e1051a39Sopenharmony_ci if (digest_value == NULL) { 74e1051a39Sopenharmony_ci fprintf(stderr, "No memory.\n"); 75e1051a39Sopenharmony_ci goto cleanup; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci /* 78e1051a39Sopenharmony_ci * Make a message digest context to hold temporary state 79e1051a39Sopenharmony_ci * during digest creation 80e1051a39Sopenharmony_ci */ 81e1051a39Sopenharmony_ci digest_context = EVP_MD_CTX_new(); 82e1051a39Sopenharmony_ci if (digest_context == NULL) { 83e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_CTX_new failed.\n"); 84e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 85e1051a39Sopenharmony_ci goto cleanup; 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci /* 88e1051a39Sopenharmony_ci * Initialize the message digest context to use the fetched 89e1051a39Sopenharmony_ci * digest provider 90e1051a39Sopenharmony_ci */ 91e1051a39Sopenharmony_ci if (EVP_DigestInit(digest_context, message_digest) != 1) { 92e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestInit failed.\n"); 93e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 94e1051a39Sopenharmony_ci goto cleanup; 95e1051a39Sopenharmony_ci } 96e1051a39Sopenharmony_ci while ((ii = BIO_read(input, buffer, sizeof(buffer))) > 0) { 97e1051a39Sopenharmony_ci if (EVP_DigestUpdate(digest_context, buffer, ii) != 1) { 98e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestUpdate() failed.\n"); 99e1051a39Sopenharmony_ci goto cleanup; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci } 102e1051a39Sopenharmony_ci if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) { 103e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestFinal() failed.\n"); 104e1051a39Sopenharmony_ci goto cleanup; 105e1051a39Sopenharmony_ci } 106e1051a39Sopenharmony_ci result = 1; 107e1051a39Sopenharmony_ci for (ii=0; ii<digest_length; ii++) { 108e1051a39Sopenharmony_ci fprintf(stdout, "%02x", digest_value[ii]); 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci fprintf(stdout, "\n"); 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_cicleanup: 113e1051a39Sopenharmony_ci if (result != 1) 114e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 115e1051a39Sopenharmony_ci /* OpenSSL free functions will ignore NULL arguments */ 116e1051a39Sopenharmony_ci EVP_MD_CTX_free(digest_context); 117e1051a39Sopenharmony_ci OPENSSL_free(digest_value); 118e1051a39Sopenharmony_ci EVP_MD_free(message_digest); 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 121e1051a39Sopenharmony_ci return result; 122e1051a39Sopenharmony_ci} 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ciint main(void) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci int result = 1; 127e1051a39Sopenharmony_ci BIO *input = BIO_new_fd( fileno(stdin), 1 ); 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci if (input != NULL) { 130e1051a39Sopenharmony_ci result = demonstrate_digest(input); 131e1051a39Sopenharmony_ci BIO_free(input); 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci return result; 134e1051a39Sopenharmony_ci} 135