]>
Commit | Line | Data |
---|---|---|
29ce1066 PN |
1 | /*- |
2 | * Copyright 2019-2021 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 | * You can find SHA3 test vectors from NIST here: | |
14 | * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip | |
15 | * For example, contains these lines: | |
16 | Len = 80 | |
17 | Msg = 1ca984dcc913344370cf | |
18 | MD = 6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd14816 | |
19 | * use xxd convert the hex message string to binary input for EVP_MD_stdin: | |
20 | * echo "1ca984dcc913344370cf" | xxd -r -p | ./EVP_MD_stdin | |
21 | * and then verify the output matches MD above. | |
22 | */ | |
23 | ||
24 | #include <string.h> | |
25 | #include <stdio.h> | |
26 | #include <openssl/err.h> | |
27 | #include <openssl/evp.h> | |
28 | ||
29 | /*- | |
30 | * This demonstration will show how to digest data using | |
31 | * a BIO created to read from stdin | |
32 | */ | |
33 | ||
34 | int demonstrate_digest(BIO *input) | |
35 | { | |
36 | OSSL_LIB_CTX *library_context = NULL; | |
09ff84bd | 37 | int ret = 0; |
29ce1066 PN |
38 | const char * option_properties = NULL; |
39 | EVP_MD *message_digest = NULL; | |
40 | EVP_MD_CTX *digest_context = NULL; | |
41 | unsigned int digest_length; | |
42 | unsigned char *digest_value = NULL; | |
43 | unsigned char buffer[512]; | |
44 | int ii; | |
45 | ||
46 | library_context = OSSL_LIB_CTX_new(); | |
47 | if (library_context == NULL) { | |
48 | fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); | |
49 | goto cleanup; | |
50 | } | |
51 | ||
52 | /* | |
53 | * Fetch a message digest by name | |
54 | * The algorithm name is case insensitive. | |
55 | * See providers(7) for details about algorithm fetching | |
56 | */ | |
57 | message_digest = EVP_MD_fetch(library_context, | |
58 | "SHA3-512", option_properties); | |
59 | if (message_digest == NULL) { | |
60 | fprintf(stderr, "EVP_MD_fetch could not find SHA3-512."); | |
61 | ERR_print_errors_fp(stderr); | |
62 | OSSL_LIB_CTX_free(library_context); | |
63 | return 0; | |
64 | } | |
65 | /* Determine the length of the fetched digest type */ | |
ed576acd | 66 | digest_length = EVP_MD_get_size(message_digest); |
29ce1066 | 67 | if (digest_length <= 0) { |
ed576acd | 68 | fprintf(stderr, "EVP_MD_get_size returned invalid size.\n"); |
29ce1066 PN |
69 | goto cleanup; |
70 | } | |
71 | ||
72 | digest_value = OPENSSL_malloc(digest_length); | |
73 | if (digest_value == NULL) { | |
74 | fprintf(stderr, "No memory.\n"); | |
75 | goto cleanup; | |
76 | } | |
77 | /* | |
78 | * Make a message digest context to hold temporary state | |
79 | * during digest creation | |
80 | */ | |
81 | digest_context = EVP_MD_CTX_new(); | |
82 | if (digest_context == NULL) { | |
83 | fprintf(stderr, "EVP_MD_CTX_new failed.\n"); | |
84 | ERR_print_errors_fp(stderr); | |
85 | goto cleanup; | |
86 | } | |
87 | /* | |
88 | * Initialize the message digest context to use the fetched | |
89 | * digest provider | |
90 | */ | |
91 | if (EVP_DigestInit(digest_context, message_digest) != 1) { | |
92 | fprintf(stderr, "EVP_DigestInit failed.\n"); | |
93 | ERR_print_errors_fp(stderr); | |
94 | goto cleanup; | |
95 | } | |
96 | while ((ii = BIO_read(input, buffer, sizeof(buffer))) > 0) { | |
97 | if (EVP_DigestUpdate(digest_context, buffer, ii) != 1) { | |
98 | fprintf(stderr, "EVP_DigestUpdate() failed.\n"); | |
99 | goto cleanup; | |
100 | } | |
101 | } | |
102 | if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) { | |
103 | fprintf(stderr, "EVP_DigestFinal() failed.\n"); | |
104 | goto cleanup; | |
105 | } | |
09ff84bd | 106 | ret = 1; |
29ce1066 PN |
107 | for (ii=0; ii<digest_length; ii++) { |
108 | fprintf(stdout, "%02x", digest_value[ii]); | |
109 | } | |
110 | fprintf(stdout, "\n"); | |
111 | ||
112 | cleanup: | |
09ff84bd | 113 | if (ret != 1) |
29ce1066 PN |
114 | ERR_print_errors_fp(stderr); |
115 | /* OpenSSL free functions will ignore NULL arguments */ | |
116 | EVP_MD_CTX_free(digest_context); | |
117 | OPENSSL_free(digest_value); | |
118 | EVP_MD_free(message_digest); | |
119 | ||
120 | OSSL_LIB_CTX_free(library_context); | |
09ff84bd | 121 | return ret; |
29ce1066 PN |
122 | } |
123 | ||
124 | int main(void) | |
125 | { | |
09ff84bd | 126 | int ret = EXIT_FAILURE; |
1287dabd | 127 | BIO *input = BIO_new_fd(fileno(stdin), 1); |
29ce1066 PN |
128 | |
129 | if (input != NULL) { | |
09ff84bd | 130 | ret = (demonstrate_digest(input) ? EXIT_SUCCESS : EXIT_FAILURE); |
29ce1066 PN |
131 | BIO_free(input); |
132 | } | |
09ff84bd | 133 | if (ret != EXIT_SUCCESS) |
134 | ERR_print_errors_fp(stderr); | |
135 | return ret; | |
29ce1066 | 136 | } |