1e1051a39Sopenharmony_ci/*- 2e1051a39Sopenharmony_ci * Copyright 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 */ 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci#include <string.h> 16e1051a39Sopenharmony_ci#include <stdio.h> 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci#include <openssl/evp.h> 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci/*- 21e1051a39Sopenharmony_ci * This demonstration will show how to digest data using 22e1051a39Sopenharmony_ci * the soliloqy from Hamlet scene 1 act 3 23e1051a39Sopenharmony_ci * The soliloqy is split into two parts to demonstrate using EVP_DigestUpdate 24e1051a39Sopenharmony_ci * more than once. 25e1051a39Sopenharmony_ci */ 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ciconst char * hamlet_1 = 28e1051a39Sopenharmony_ci "To be, or not to be, that is the question,\n" 29e1051a39Sopenharmony_ci "Whether tis nobler in the minde to suffer\n" 30e1051a39Sopenharmony_ci "The ſlings and arrowes of outragious fortune,\n" 31e1051a39Sopenharmony_ci "Or to take Armes again in a sea of troubles,\n" 32e1051a39Sopenharmony_ci "And by opposing, end them, to die to sleep;\n" 33e1051a39Sopenharmony_ci "No more, and by a sleep, to say we end\n" 34e1051a39Sopenharmony_ci "The heart-ache, and the thousand natural shocks\n" 35e1051a39Sopenharmony_ci "That flesh is heir to? tis a consumation\n" 36e1051a39Sopenharmony_ci "Devoutly to be wished. To die to sleep,\n" 37e1051a39Sopenharmony_ci "To sleepe, perchance to dreame, Aye, there's the rub,\n" 38e1051a39Sopenharmony_ci "For in that sleep of death what dreams may come\n" 39e1051a39Sopenharmony_ci "When we haue shuffled off this mortal coil\n" 40e1051a39Sopenharmony_ci "Must give us pause. There's the respect\n" 41e1051a39Sopenharmony_ci "That makes calamity of so long life:\n" 42e1051a39Sopenharmony_ci "For who would bear the Ships and Scorns of time,\n" 43e1051a39Sopenharmony_ci "The oppressor's wrong, the proud man's Contumely,\n" 44e1051a39Sopenharmony_ci "The pangs of dispised love, the Law's delay,\n" 45e1051a39Sopenharmony_ci; 46e1051a39Sopenharmony_ciconst char * hamlet_2 = 47e1051a39Sopenharmony_ci "The insolence of Office, and the spurns\n" 48e1051a39Sopenharmony_ci "That patient merit of the'unworthy takes,\n" 49e1051a39Sopenharmony_ci "When he himself might his Quietas make\n" 50e1051a39Sopenharmony_ci "With a bare bodkin? Who would fardels bear,\n" 51e1051a39Sopenharmony_ci "To grunt and sweat under a weary life,\n" 52e1051a39Sopenharmony_ci "But that the dread of something after death,\n" 53e1051a39Sopenharmony_ci "The undiscovered country, from whose bourn\n" 54e1051a39Sopenharmony_ci "No traveller returns, puzzles the will,\n" 55e1051a39Sopenharmony_ci "And makes us rather bear those ills we have,\n" 56e1051a39Sopenharmony_ci "Then fly to others we know not of?\n" 57e1051a39Sopenharmony_ci "Thus conscience does make cowards of us all,\n" 58e1051a39Sopenharmony_ci "And thus the native hue of Resolution\n" 59e1051a39Sopenharmony_ci "Is sickled o'er with the pale cast of Thought,\n" 60e1051a39Sopenharmony_ci "And enterprises of great pith and moment,\n" 61e1051a39Sopenharmony_ci "With this regard their currents turn awry,\n" 62e1051a39Sopenharmony_ci "And lose the name of Action. Soft you now,\n" 63e1051a39Sopenharmony_ci "The fair Ophelia? Nymph in thy Orisons\n" 64e1051a39Sopenharmony_ci "Be all my sins remember'd.\n" 65e1051a39Sopenharmony_ci; 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci/* The known value of the SHA3-512 digest of the above soliloqy */ 68e1051a39Sopenharmony_ciconst unsigned char known_answer[] = { 69e1051a39Sopenharmony_ci 0xbb, 0x69, 0xf8, 0x09, 0x9c, 0x2e, 0x00, 0x3d, 70e1051a39Sopenharmony_ci 0xa4, 0x29, 0x5f, 0x59, 0x4b, 0x89, 0xe4, 0xd9, 71e1051a39Sopenharmony_ci 0xdb, 0xa2, 0xe5, 0xaf, 0xa5, 0x87, 0x73, 0x9d, 72e1051a39Sopenharmony_ci 0x83, 0x72, 0xcf, 0xea, 0x84, 0x66, 0xc1, 0xf9, 73e1051a39Sopenharmony_ci 0xc9, 0x78, 0xef, 0xba, 0x3d, 0xe9, 0xc1, 0xff, 74e1051a39Sopenharmony_ci 0xa3, 0x75, 0xc7, 0x58, 0x74, 0x8e, 0x9c, 0x1d, 75e1051a39Sopenharmony_ci 0x14, 0xd9, 0xdd, 0xd1, 0xfd, 0x24, 0x30, 0xd6, 76e1051a39Sopenharmony_ci 0x81, 0xca, 0x8f, 0x78, 0x29, 0x19, 0x9a, 0xfe, 77e1051a39Sopenharmony_ci}; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ciint demonstrate_digest(void) 80e1051a39Sopenharmony_ci{ 81e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context; 82e1051a39Sopenharmony_ci int result = 0; 83e1051a39Sopenharmony_ci const char *option_properties = NULL; 84e1051a39Sopenharmony_ci EVP_MD *message_digest = NULL; 85e1051a39Sopenharmony_ci EVP_MD_CTX *digest_context = NULL; 86e1051a39Sopenharmony_ci unsigned int digest_length; 87e1051a39Sopenharmony_ci unsigned char *digest_value = NULL; 88e1051a39Sopenharmony_ci int j; 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 91e1051a39Sopenharmony_ci if (library_context == NULL) { 92e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 93e1051a39Sopenharmony_ci goto cleanup; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci /* 97e1051a39Sopenharmony_ci * Fetch a message digest by name 98e1051a39Sopenharmony_ci * The algorithm name is case insensitive. 99e1051a39Sopenharmony_ci * See providers(7) for details about algorithm fetching 100e1051a39Sopenharmony_ci */ 101e1051a39Sopenharmony_ci message_digest = EVP_MD_fetch(library_context, 102e1051a39Sopenharmony_ci "SHA3-512", option_properties); 103e1051a39Sopenharmony_ci if (message_digest == NULL) { 104e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_fetch could not find SHA3-512."); 105e1051a39Sopenharmony_ci goto cleanup; 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci /* Determine the length of the fetched digest type */ 108e1051a39Sopenharmony_ci digest_length = EVP_MD_get_size(message_digest); 109e1051a39Sopenharmony_ci if (digest_length <= 0) { 110e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_get_size returned invalid size.\n"); 111e1051a39Sopenharmony_ci goto cleanup; 112e1051a39Sopenharmony_ci } 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci digest_value = OPENSSL_malloc(digest_length); 115e1051a39Sopenharmony_ci if (digest_value == NULL) { 116e1051a39Sopenharmony_ci fprintf(stderr, "No memory.\n"); 117e1051a39Sopenharmony_ci goto cleanup; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_ci /* 120e1051a39Sopenharmony_ci * Make a message digest context to hold temporary state 121e1051a39Sopenharmony_ci * during digest creation 122e1051a39Sopenharmony_ci */ 123e1051a39Sopenharmony_ci digest_context = EVP_MD_CTX_new(); 124e1051a39Sopenharmony_ci if (digest_context == NULL) { 125e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MD_CTX_new failed.\n"); 126e1051a39Sopenharmony_ci goto cleanup; 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci /* 129e1051a39Sopenharmony_ci * Initialize the message digest context to use the fetched 130e1051a39Sopenharmony_ci * digest provider 131e1051a39Sopenharmony_ci */ 132e1051a39Sopenharmony_ci if (EVP_DigestInit(digest_context, message_digest) != 1) { 133e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestInit failed.\n"); 134e1051a39Sopenharmony_ci goto cleanup; 135e1051a39Sopenharmony_ci } 136e1051a39Sopenharmony_ci /* Digest parts one and two of the soliloqy */ 137e1051a39Sopenharmony_ci if (EVP_DigestUpdate(digest_context, hamlet_1, strlen(hamlet_1)) != 1) { 138e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestUpdate(hamlet_1) failed.\n"); 139e1051a39Sopenharmony_ci goto cleanup; 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci if (EVP_DigestUpdate(digest_context, hamlet_2, strlen(hamlet_2)) != 1) { 142e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestUpdate(hamlet_2) failed.\n"); 143e1051a39Sopenharmony_ci goto cleanup; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) { 146e1051a39Sopenharmony_ci fprintf(stderr, "EVP_DigestFinal() failed.\n"); 147e1051a39Sopenharmony_ci goto cleanup; 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci for (j=0; j<digest_length; j++) { 150e1051a39Sopenharmony_ci fprintf(stdout, "%02x", digest_value[j]); 151e1051a39Sopenharmony_ci } 152e1051a39Sopenharmony_ci fprintf(stdout, "\n"); 153e1051a39Sopenharmony_ci /* Check digest_value against the known answer */ 154e1051a39Sopenharmony_ci if ((size_t)digest_length != sizeof(known_answer)) { 155e1051a39Sopenharmony_ci fprintf(stdout, "Digest length(%d) not equal to known answer length(%lu).\n", 156e1051a39Sopenharmony_ci digest_length, sizeof(known_answer)); 157e1051a39Sopenharmony_ci } else if (memcmp(digest_value, known_answer, digest_length) != 0) { 158e1051a39Sopenharmony_ci for (j=0; j<sizeof(known_answer); j++) { 159e1051a39Sopenharmony_ci fprintf(stdout, "%02x", known_answer[j] ); 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci fprintf(stdout, "\nDigest does not match known answer\n"); 162e1051a39Sopenharmony_ci } else { 163e1051a39Sopenharmony_ci fprintf(stdout, "Digest computed properly.\n"); 164e1051a39Sopenharmony_ci result = 1; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_cicleanup: 169e1051a39Sopenharmony_ci if (result != 1) 170e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 171e1051a39Sopenharmony_ci /* OpenSSL free functions will ignore NULL arguments */ 172e1051a39Sopenharmony_ci EVP_MD_CTX_free(digest_context); 173e1051a39Sopenharmony_ci OPENSSL_free(digest_value); 174e1051a39Sopenharmony_ci EVP_MD_free(message_digest); 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 177e1051a39Sopenharmony_ci return result; 178e1051a39Sopenharmony_ci} 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ciint main(void) 181e1051a39Sopenharmony_ci{ 182e1051a39Sopenharmony_ci return demonstrate_digest() == 0; 183e1051a39Sopenharmony_ci} 184