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