Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/digest/EVP_MD_demo.c
110033 views
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
236