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