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