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