// Copyright 2024-2025 Beken // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #define APP_SUCCESS (0) #define APP_ERROR (-1) #define APP_SUCCESS_MESSAGE "Example finished successfully!" #define APP_ERROR_MESSAGE "Example exited with error!" #define CRYPTO_EXAMPLE_HMAC_TEXT_SIZE (100) #define CRYPTO_EXAMPLE_HMAC_KEY_SIZE (32) #define TAG "mbedtls" /* Below text is used as plaintext for signing/verifiction */ static uint8_t m_plain_text[CRYPTO_EXAMPLE_HMAC_TEXT_SIZE] = { "Example string to demonstrate basic usage of HMAC signing/verification." }; static uint8_t hmac[CRYPTO_EXAMPLE_HMAC_KEY_SIZE]; static psa_key_id_t key_id; static int crypto_init(void) { psa_status_t status; /* Initialize PSA Crypto */ status = psa_crypto_init(); if (status != PSA_SUCCESS) return APP_ERROR; return APP_SUCCESS; } static int crypto_finish(void) { psa_status_t status; /* Destroy the key handle */ status = psa_destroy_key(key_id); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_destroy_key failed! (Error: %d)\r\n", status); return APP_ERROR; } return APP_SUCCESS; } int generate_key(void) { psa_status_t status; BK_LOGI(TAG, "Generating random HMAC key...\r\n"); /* Configure the key attributes */ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_HASH); psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); psa_set_key_algorithm(&key_attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256)); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_HMAC); psa_set_key_bits(&key_attributes, 256); /* Generate a random key. The key is not exposed to the application, * we can use it to encrypt/decrypt using the key handle */ status = psa_generate_key(&key_attributes, &key_id); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_generate_key failed! (Error: %d)\r\n", status); return APP_ERROR; } /* After the key handle is acquired the attributes are not needed */ psa_reset_key_attributes(&key_attributes); BK_LOGI(TAG, "HMAC key generated successfully!\r\n"); return APP_SUCCESS; } int hmac_sign(void) { uint32_t olen; psa_status_t status; psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; BK_LOGI(TAG, "Signing using HMAC ...\r\n"); /* Initialize the HMAC signing operation */ status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256)); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_sign_setup failed! (Error: %d)\r\n", status); return APP_ERROR; } /* Perform the HMAC signing */ status = psa_mac_update(&operation, m_plain_text, sizeof(m_plain_text)); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_update failed! (Error: %d)\r\n", status); return APP_ERROR; } /* Finalize the HMAC signing */ status = psa_mac_sign_finish(&operation, hmac, sizeof(hmac), (size_t *)&olen); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_sign_finish failed! (Error: %d)\r\n", status); return APP_ERROR; } BK_LOGI(TAG, "Signing successful!\r\n"); return APP_SUCCESS; } int hmac_verify(void) { psa_status_t status; psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; BK_LOGI(TAG, "Verifying the HMAC signature...\r\n"); /* Initialize the HMAC verification operation */ status = psa_mac_verify_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256)); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_verify_setup failed! (Error: %d)\r\n", status); return APP_ERROR; } /* Perform the HMAC verification */ status = psa_mac_update(&operation, m_plain_text, sizeof(m_plain_text)); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_update failed! (Error: %d)\r\n", status); return APP_ERROR; } /* Finalize the HMAC verification */ status = psa_mac_verify_finish(&operation, hmac, sizeof(hmac)); if (status != PSA_SUCCESS) { BK_LOGI(TAG, "psa_mac_verify_finish failed! (Error: %d)\r\n", status); return APP_ERROR; } BK_LOGI(TAG, "HMAC verified successfully!\r\n"); return APP_SUCCESS; } int hmac_main(void) { int status; BK_LOGI(TAG, "Starting HMAC example...\r\n"); status = crypto_init(); if (status != APP_SUCCESS) { BK_LOGI(TAG, APP_ERROR_MESSAGE); return APP_ERROR; } status = generate_key(); if (status != APP_SUCCESS) { BK_LOGI(TAG, APP_ERROR_MESSAGE); return APP_ERROR; } status = hmac_sign(); if (status != APP_SUCCESS) { BK_LOGI(TAG, APP_ERROR_MESSAGE); return APP_ERROR; } status = hmac_verify(); if (status != APP_SUCCESS) { BK_LOGI(TAG, APP_ERROR_MESSAGE); return APP_ERROR; } status = crypto_finish(); if (status != APP_SUCCESS) { BK_LOGI(TAG, APP_ERROR_MESSAGE); return APP_ERROR; } BK_LOGI(TAG, APP_SUCCESS_MESSAGE); return APP_SUCCESS; }