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 BIO_f_md: 20e1051a39Sopenharmony_ci * echo "1ca984dcc913344370cf" | xxd -r -p | ./BIO_f_md 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/bio.h> 28e1051a39Sopenharmony_ci#include <openssl/evp.h> 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/*- 31e1051a39Sopenharmony_ci * This demonstration will show how to digest data using 32e1051a39Sopenharmony_ci * a BIO configured with a message digest 33e1051a39Sopenharmony_ci * A message digest name may be passed as an argument. 34e1051a39Sopenharmony_ci * The default digest is SHA3-512 35e1051a39Sopenharmony_ci */ 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ciint main(int argc, char * argv[]) 38e1051a39Sopenharmony_ci{ 39e1051a39Sopenharmony_ci int result = 1; 40e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context = NULL; 41e1051a39Sopenharmony_ci BIO *input = NULL; 42e1051a39Sopenharmony_ci BIO *bio_digest = NULL; 43e1051a39Sopenharmony_ci EVP_MD *md = NULL; 44e1051a39Sopenharmony_ci unsigned char buffer[512]; 45e1051a39Sopenharmony_ci size_t readct, writect; 46e1051a39Sopenharmony_ci size_t digest_size; 47e1051a39Sopenharmony_ci char *digest_value=NULL; 48e1051a39Sopenharmony_ci int j; 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci input = BIO_new_fd( fileno(stdin), 1 ); 51e1051a39Sopenharmony_ci if (input == NULL) { 52e1051a39Sopenharmony_ci fprintf(stderr, "BIO_new_fd() for stdin returned NULL\n"); 53e1051a39Sopenharmony_ci goto cleanup; 54e1051a39Sopenharmony_ci } 55e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 56e1051a39Sopenharmony_ci if (library_context == NULL) { 57e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 58e1051a39Sopenharmony_ci goto cleanup; 59e1051a39Sopenharmony_ci } 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci /* 62e1051a39Sopenharmony_ci * Fetch a message digest by name 63e1051a39Sopenharmony_ci * The algorithm name is case insensitive. 64e1051a39Sopenharmony_ci * See providers(7) for details about algorithm fetching 65e1051a39Sopenharmony_ci */ 66e1051a39Sopenharmony_ci md = EVP_MD_fetch( library_context, "SHA3-512", NULL ); 67e1051a39Sopenharmony_ci if (md == NULL) { 68e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_fetch did not find SHA3-512.\n"); 69e1051a39Sopenharmony_ci goto cleanup; 70e1051a39Sopenharmony_ci } 71e1051a39Sopenharmony_ci digest_size = EVP_MD_get_size(md); 72e1051a39Sopenharmony_ci digest_value = OPENSSL_malloc(digest_size); 73e1051a39Sopenharmony_ci if (digest_value == NULL) { 74e1051a39Sopenharmony_ci fprintf(stderr, "Can't allocate %lu bytes for the digest value.\n", (unsigned long)digest_size); 75e1051a39Sopenharmony_ci goto cleanup; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci /* Make a bio that uses the digest */ 78e1051a39Sopenharmony_ci bio_digest = BIO_new(BIO_f_md()); 79e1051a39Sopenharmony_ci if (bio_digest == NULL) { 80e1051a39Sopenharmony_ci fprintf(stderr, "BIO_new(BIO_f_md()) returned NULL\n"); 81e1051a39Sopenharmony_ci goto cleanup; 82e1051a39Sopenharmony_ci } 83e1051a39Sopenharmony_ci /* set our bio_digest BIO to digest data */ 84e1051a39Sopenharmony_ci if (BIO_set_md(bio_digest,md) != 1) { 85e1051a39Sopenharmony_ci fprintf(stderr, "BIO_set_md failed.\n"); 86e1051a39Sopenharmony_ci goto cleanup; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci /*- 89e1051a39Sopenharmony_ci * We will use BIO chaining so that as we read, the digest gets updated 90e1051a39Sopenharmony_ci * See the man page for BIO_push 91e1051a39Sopenharmony_ci */ 92e1051a39Sopenharmony_ci BIO *reading = BIO_push( bio_digest, input ); 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci while( BIO_read(reading, buffer, sizeof(buffer)) > 0 ) 95e1051a39Sopenharmony_ci ; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci /*- 98e1051a39Sopenharmony_ci * BIO_gets must be used to calculate the final 99e1051a39Sopenharmony_ci * digest value and then copy it to digest_value. 100e1051a39Sopenharmony_ci */ 101e1051a39Sopenharmony_ci if (BIO_gets(bio_digest, digest_value, digest_size) != digest_size) { 102e1051a39Sopenharmony_ci fprintf(stderr, "BIO_gets(bio_digest) failed\n"); 103e1051a39Sopenharmony_ci goto cleanup; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci for (j=0; j<digest_size; j++) { 106e1051a39Sopenharmony_ci fprintf(stdout, "%02x", (unsigned char)digest_value[j]); 107e1051a39Sopenharmony_ci } 108e1051a39Sopenharmony_ci fprintf(stdout, "\n"); 109e1051a39Sopenharmony_ci result = 0; 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_cicleanup: 112e1051a39Sopenharmony_ci if (result != 0) 113e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci OPENSSL_free(digest_value); 116e1051a39Sopenharmony_ci BIO_free(input); 117e1051a39Sopenharmony_ci BIO_free(bio_digest); 118e1051a39Sopenharmony_ci EVP_MD_free(md); 119e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci return result; 122e1051a39Sopenharmony_ci} 123