1 /*
2  *  Example computing a SHA-256 hash using the PSA Crypto API
3  *
4  *  The example computes the SHA-256 hash of a test string using the
5  *  one-shot API call psa_hash_compute() and the using multi-part
6  *  operation, which requires psa_hash_setup(), psa_hash_update() and
7  *  psa_hash_finish(). The multi-part operation is popular on embedded
8  *  devices where a rolling hash needs to be computed.
9  *
10  *
11  *  Copyright The Mbed TLS Contributors
12  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
13  */
14 
15 #include "psa/crypto.h"
16 #include <string.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 #include "mbedtls/build_info.h"
21 #include "mbedtls/platform.h"
22 
23 /* Information about hashing with the PSA API can be
24  * found here:
25  * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html
26  *
27  * The algorithm used by this demo is SHA 256.
28  * Please see include/psa/crypto_values.h to see the other
29  * algorithms that are supported by Mbed TLS.
30  * If you switch to a different algorithm you will need to update
31  * the hash data in the EXAMPLE_HASH_VALUE macro below. */
32 
33 #if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)
main(void)34 int main(void)
35 {
36     mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
37                    "not defined.\r\n");
38     return EXIT_SUCCESS;
39 }
40 #else
41 
42 #define HASH_ALG PSA_ALG_SHA_256
43 
44 const uint8_t sample_message[] = "Hello World!";
45 /* sample_message is terminated with a null byte which is not part of
46  * the message itself so we make sure to subtract it in order to get
47  * the message length. */
48 const size_t sample_message_length = sizeof(sample_message) - 1;
49 
50 #define EXPECTED_HASH_VALUE {                                                    \
51         0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
52         0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \
53         0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
54 }
55 
56 const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
57 const size_t expected_hash_len = sizeof(expected_hash);
58 
main(void)59 int main(void)
60 {
61     psa_status_t status;
62     uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
63     size_t hash_length;
64     psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
65     psa_hash_operation_t cloned_hash_operation = PSA_HASH_OPERATION_INIT;
66 
67     mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
68 
69     status = psa_crypto_init();
70     if (status != PSA_SUCCESS) {
71         mbedtls_printf("psa_crypto_init failed\n");
72         return EXIT_FAILURE;
73     }
74 
75     /* Compute hash using multi-part operation */
76     status = psa_hash_setup(&hash_operation, HASH_ALG);
77     if (status == PSA_ERROR_NOT_SUPPORTED) {
78         mbedtls_printf("unknown hash algorithm supplied\n");
79         return EXIT_FAILURE;
80     } else if (status != PSA_SUCCESS) {
81         mbedtls_printf("psa_hash_setup failed\n");
82         return EXIT_FAILURE;
83     }
84 
85     status = psa_hash_update(&hash_operation, sample_message, sample_message_length);
86     if (status != PSA_SUCCESS) {
87         mbedtls_printf("psa_hash_update failed\n");
88         goto cleanup;
89     }
90 
91     status = psa_hash_clone(&hash_operation, &cloned_hash_operation);
92     if (status != PSA_SUCCESS) {
93         mbedtls_printf("PSA hash clone failed\n");
94         goto cleanup;
95     }
96 
97     status = psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_length);
98     if (status != PSA_SUCCESS) {
99         mbedtls_printf("psa_hash_finish failed\n");
100         goto cleanup;
101     }
102 
103     /* Check the result of the operation against the sample */
104     if (hash_length != expected_hash_len ||
105         (memcmp(hash, expected_hash, expected_hash_len) != 0)) {
106         mbedtls_printf("Multi-part hash operation gave the wrong result!\n\n");
107         goto cleanup;
108     }
109 
110     status =
111         psa_hash_verify(&cloned_hash_operation, expected_hash,
112                         expected_hash_len);
113     if (status != PSA_SUCCESS) {
114         mbedtls_printf("psa_hash_verify failed\n");
115         goto cleanup;
116     } else {
117         mbedtls_printf("Multi-part hash operation successful!\n");
118     }
119 
120     /* Clear local variables prior to one-shot hash demo */
121     memset(hash, 0, sizeof(hash));
122     hash_length = 0;
123 
124     /* Compute hash using one-shot function call */
125     status = psa_hash_compute(HASH_ALG,
126                               sample_message, sample_message_length,
127                               hash, sizeof(hash),
128                               &hash_length);
129     if (status != PSA_SUCCESS) {
130         mbedtls_printf("psa_hash_compute failed\n");
131         goto cleanup;
132     }
133 
134     if (hash_length != expected_hash_len ||
135         (memcmp(hash, expected_hash, expected_hash_len) != 0)) {
136         mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
137         goto cleanup;
138     }
139 
140     mbedtls_printf("One-shot hash operation successful!\n\n");
141 
142     /* Print out result */
143     mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
144 
145     for (size_t j = 0; j < expected_hash_len; j++) {
146         mbedtls_printf("%02x", hash[j]);
147     }
148 
149     mbedtls_printf("\n");
150 
151     mbedtls_psa_crypto_free();
152     return EXIT_SUCCESS;
153 
154 cleanup:
155     psa_hash_abort(&hash_operation);
156     psa_hash_abort(&cloned_hash_operation);
157     return EXIT_FAILURE;
158 }
159 #endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */
160