xref: /netbsd-src/crypto/external/bsd/openssl/dist/demos/digest/EVP_MD_demo.c (revision 0e2e28bced52bda3788c857106bde6c44d2df3b8)
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