xref: /third_party/mbedtls/programs/psa/psa_hash.c (revision a8e1175b)
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)
34int 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
44const 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. */
48const 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
56const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
57const size_t expected_hash_len = sizeof(expected_hash);
58
59int 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
154cleanup:
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