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