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