blob: c5244d6d4074791af18fd38ae1022ef715b49c3d [file] [log] [blame]
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +01001/*
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
Dave Rodgman16799db2023-11-02 19:47:20 +000012 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010013 */
14
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010015#include "psa/crypto.h"
16#include <string.h>
17#include <stdio.h>
18#include <stdlib.h>
19
20#include "mbedtls/build_info.h"
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010021#include "mbedtls/platform.h"
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010022
Thomas Daubney86f97952023-10-10 16:50:49 +010023/* 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
Thomas Daubney34500872023-10-11 10:04:54 +010026 *
Thomas Daubney86f97952023-10-10 16:50:49 +010027 * The algorithm used by this demo is SHA 256.
Thomas Daubney606110f2023-07-28 15:57:10 +010028 * Please see include/psa/crypto_values.h to see the other
Thomas Daubney86f97952023-10-10 16:50:49 +010029 * algorithms that are supported by Mbed TLS.
30 * If you switch to a different algorithm you will need to update
Thomas Daubney2e677812023-10-12 10:46:43 +010031 * the hash data in the EXAMPLE_HASH_VALUE macro below. */
Thomas Daubney1c2378b2023-10-11 15:19:38 +010032
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010033#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)
Thomas Daubney209c9c92023-07-18 14:59:45 +010034int main(void)
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010035{
Thomas Daubney2c872342023-07-28 14:21:38 +010036 mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
Thomas Daubney9520df72023-07-25 10:56:54 +010037 "not defined.\r\n");
Thomas Daubney209c9c92023-07-18 14:59:45 +010038 return EXIT_SUCCESS;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010039}
40#else
41
Thomas Daubney2e677812023-10-12 10:46:43 +010042#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
Thomas Daubney209c9c92023-07-18 14:59:45 +010059int main(void)
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010060{
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010061 psa_status_t status;
Thomas Daubney1db78fa2023-07-24 16:49:14 +010062 uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
Thomas Daubney6fc4ca22023-07-28 14:31:06 +010063 size_t hash_length;
Thomas Daubneyc0500372023-07-28 14:44:25 +010064 psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
65 psa_hash_operation_t cloned_hash_operation = PSA_HASH_OPERATION_INIT;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010066
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010067 mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010068
Thomas Daubney209c9c92023-07-18 14:59:45 +010069 status = psa_crypto_init();
70 if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010071 mbedtls_printf("psa_crypto_init failed\n");
Thomas Daubney209c9c92023-07-18 14:59:45 +010072 return EXIT_FAILURE;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010073 }
74
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010075 /* Compute hash using multi-part operation */
Thomas Daubneyc0500372023-07-28 14:44:25 +010076 status = psa_hash_setup(&hash_operation, HASH_ALG);
Thomas Daubney2e677812023-10-12 10:46:43 +010077 if (status == PSA_ERROR_NOT_SUPPORTED) {
Thomas Daubney76053882023-10-10 17:38:53 +010078 mbedtls_printf("unknown hash algorithm supplied\n");
79 return EXIT_FAILURE;
Thomas Daubney2e677812023-10-12 10:46:43 +010080 } else if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010081 mbedtls_printf("psa_hash_setup failed\n");
Thomas Daubney209c9c92023-07-18 14:59:45 +010082 return EXIT_FAILURE;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010083 }
84
Thomas Daubney1c2378b2023-10-11 15:19:38 +010085 status = psa_hash_update(&hash_operation, sample_message, sample_message_length);
Thomas Daubney209c9c92023-07-18 14:59:45 +010086 if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010087 mbedtls_printf("psa_hash_update failed\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +010088 goto cleanup;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010089 }
90
Thomas Daubneyc0500372023-07-28 14:44:25 +010091 status = psa_hash_clone(&hash_operation, &cloned_hash_operation);
Thomas Daubney209c9c92023-07-18 14:59:45 +010092 if (status != PSA_SUCCESS) {
Thomas Daubneycd79f772023-10-11 15:28:13 +010093 mbedtls_printf("PSA hash clone failed\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +010094 goto cleanup;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +010095 }
96
Thomas Daubneyc0500372023-07-28 14:44:25 +010097 status = psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_length);
Thomas Daubney209c9c92023-07-18 14:59:45 +010098 if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +010099 mbedtls_printf("psa_hash_finish failed\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100100 goto cleanup;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100101 }
102
Thomas Daubneyce141242023-07-28 16:14:20 +0100103 /* Check the result of the operation against the sample */
Thomas Daubney2e677812023-10-12 10:46:43 +0100104 if (hash_length != expected_hash_len ||
105 (memcmp(hash, expected_hash, expected_hash_len) != 0)) {
Thomas Daubneyce141242023-07-28 16:14:20 +0100106 mbedtls_printf("Multi-part hash operation gave the wrong result!\n\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100107 goto cleanup;
Thomas Daubneyce141242023-07-28 16:14:20 +0100108 }
109
Thomas Daubney209c9c92023-07-18 14:59:45 +0100110 status =
Thomas Daubney2e677812023-10-12 10:46:43 +0100111 psa_hash_verify(&cloned_hash_operation, expected_hash,
112 expected_hash_len);
Thomas Daubney209c9c92023-07-18 14:59:45 +0100113 if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +0100114 mbedtls_printf("psa_hash_verify failed\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100115 goto cleanup;
Thomas Daubney209c9c92023-07-18 14:59:45 +0100116 } else {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +0100117 mbedtls_printf("Multi-part hash operation successful!\n");
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100118 }
119
Thomas Daubney3071c852023-07-28 14:47:47 +0100120 /* Clear local variables prior to one-shot hash demo */
Thomas Daubney209c9c92023-07-18 14:59:45 +0100121 memset(hash, 0, sizeof(hash));
Thomas Daubney6fc4ca22023-07-28 14:31:06 +0100122 hash_length = 0;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100123
Thomas Daubney3071c852023-07-28 14:47:47 +0100124 /* Compute hash using one-shot function call */
Thomas Daubney1db78fa2023-07-24 16:49:14 +0100125 status = psa_hash_compute(HASH_ALG,
Thomas Daubney1c2378b2023-10-11 15:19:38 +0100126 sample_message, sample_message_length,
Thomas Daubney209c9c92023-07-18 14:59:45 +0100127 hash, sizeof(hash),
Thomas Daubney6fc4ca22023-07-28 14:31:06 +0100128 &hash_length);
Thomas Daubney209c9c92023-07-18 14:59:45 +0100129 if (status != PSA_SUCCESS) {
Thomas Daubneyf7348ae2023-07-24 12:18:40 +0100130 mbedtls_printf("psa_hash_compute failed\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100131 goto cleanup;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100132 }
133
Thomas Daubney2e677812023-10-12 10:46:43 +0100134 if (hash_length != expected_hash_len ||
135 (memcmp(hash, expected_hash, expected_hash_len) != 0)) {
Thomas Daubneya2b75192023-07-28 15:21:46 +0100136 mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100137 goto cleanup;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100138 }
139
Thomas Daubneyf7348ae2023-07-24 12:18:40 +0100140 mbedtls_printf("One-shot hash operation successful!\n\n");
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100141
Thomas Daubney1f987362023-07-28 15:23:06 +0100142 /* Print out result */
Thomas Daubney606110f2023-07-28 15:57:10 +0100143 mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100144
Thomas Daubney2e677812023-10-12 10:46:43 +0100145 for (size_t j = 0; j < expected_hash_len; j++) {
Thomas Daubney9730cb12023-07-28 15:07:19 +0100146 mbedtls_printf("%02x", hash[j]);
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100147 }
148
Thomas Daubneyf7348ae2023-07-24 12:18:40 +0100149 mbedtls_printf("\n");
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100150
Thomas Daubney209c9c92023-07-18 14:59:45 +0100151 mbedtls_psa_crypto_free();
152 return EXIT_SUCCESS;
Thomas Daubney5c2dcbd2023-08-03 16:03:30 +0100153
154cleanup:
155 psa_hash_abort(&hash_operation);
156 psa_hash_abort(&cloned_hash_operation);
157 return EXIT_FAILURE;
Hannes Tschofenigf8b9ebf2023-07-18 13:46:10 +0100158}
Thomas Daubney2e677812023-10-12 10:46:43 +0100159#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */