1/** 2 * MD API multi-part HMAC demonstration. 3 * 4 * This programs computes the HMAC of two messages using the multi-part API. 5 * 6 * This is a companion to psa/hmac_demo.c, doing the same operations with the 7 * legacy MD API. The goal is that comparing the two programs will help people 8 * migrating to the PSA Crypto API. 9 * 10 * When it comes to multi-part HMAC operations, the `mbedtls_md_context` 11 * serves a dual purpose (1) hold the key, and (2) save progress information 12 * for the current operation. With PSA those roles are held by two disinct 13 * objects: (1) a psa_key_id_t to hold the key, and (2) a psa_operation_t for 14 * multi-part progress. 15 * 16 * This program and its companion psa/hmac_demo.c illustrate this by doing the 17 * same sequence of multi-part HMAC computation with both APIs; looking at the 18 * two side by side should make the differences and similarities clear. 19 */ 20 21/* 22 * Copyright The Mbed TLS Contributors 23 * SPDX-License-Identifier: Apache-2.0 24 * 25 * Licensed under the Apache License, Version 2.0 (the "License"); you may 26 * not use this file except in compliance with the License. 27 * You may obtain a copy of the License at 28 * 29 * http://www.apache.org/licenses/LICENSE-2.0 30 * 31 * Unless required by applicable law or agreed to in writing, software 32 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 33 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 * See the License for the specific language governing permissions and 35 * limitations under the License. 36 */ 37 38/* First include Mbed TLS headers to get the Mbed TLS configuration and 39 * platform definitions that we'll use in this program. Also include 40 * standard C headers for functions we'll use here. */ 41#include "mbedtls/build_info.h" 42 43#include "mbedtls/md.h" 44 45#include "mbedtls/platform_util.h" // for mbedtls_platform_zeroize 46 47#include <stdlib.h> 48#include <stdio.h> 49 50/* If the build options we need are not enabled, compile a placeholder. */ 51#if !defined(MBEDTLS_MD_C) 52int main(void) 53{ 54 printf("MBEDTLS_MD_C not defined\r\n"); 55 return 0; 56} 57#else 58 59/* The real program starts here. */ 60 61/* Dummy inputs for HMAC */ 62const unsigned char msg1_part1[] = { 0x01, 0x02 }; 63const unsigned char msg1_part2[] = { 0x03, 0x04 }; 64const unsigned char msg2_part1[] = { 0x05, 0x05 }; 65const unsigned char msg2_part2[] = { 0x06, 0x06 }; 66 67/* Dummy key material - never do this in production! 68 * This example program uses SHA-256, so a 32-byte key makes sense. */ 69const unsigned char key_bytes[32] = { 0 }; 70 71/* Print the contents of a buffer in hex */ 72void print_buf(const char *title, unsigned char *buf, size_t len) 73{ 74 printf("%s:", title); 75 for (size_t i = 0; i < len; i++) { 76 printf(" %02x", buf[i]); 77 } 78 printf("\n"); 79} 80 81/* Run an Mbed TLS function and bail out if it fails. 82 * A string description of the error code can be recovered with: 83 * programs/util/strerror <value> */ 84#define CHK(expr) \ 85 do \ 86 { \ 87 ret = (expr); \ 88 if (ret != 0) \ 89 { \ 90 printf("Error %d at line %d: %s\n", \ 91 ret, \ 92 __LINE__, \ 93 #expr); \ 94 goto exit; \ 95 } \ 96 } while (0) 97 98/* 99 * This function demonstrates computation of the HMAC of two messages using 100 * the multipart API. 101 */ 102int hmac_demo(void) 103{ 104 int ret; 105 const mbedtls_md_type_t alg = MBEDTLS_MD_SHA256; 106 unsigned char out[MBEDTLS_MD_MAX_SIZE]; // safe but not optimal 107 108 mbedtls_md_context_t ctx; 109 110 mbedtls_md_init(&ctx); 111 112 /* prepare context and load key */ 113 // the last argument to setup is 1 to enable HMAC (not just hashing) 114 const mbedtls_md_info_t *info = mbedtls_md_info_from_type(alg); 115 CHK(mbedtls_md_setup(&ctx, info, 1)); 116 CHK(mbedtls_md_hmac_starts(&ctx, key_bytes, sizeof(key_bytes))); 117 118 /* compute HMAC(key, msg1_part1 | msg1_part2) */ 119 CHK(mbedtls_md_hmac_update(&ctx, msg1_part1, sizeof(msg1_part1))); 120 CHK(mbedtls_md_hmac_update(&ctx, msg1_part2, sizeof(msg1_part2))); 121 CHK(mbedtls_md_hmac_finish(&ctx, out)); 122 print_buf("msg1", out, mbedtls_md_get_size(info)); 123 124 /* compute HMAC(key, msg2_part1 | msg2_part2) */ 125 CHK(mbedtls_md_hmac_reset(&ctx)); // prepare for new operation 126 CHK(mbedtls_md_hmac_update(&ctx, msg2_part1, sizeof(msg2_part1))); 127 CHK(mbedtls_md_hmac_update(&ctx, msg2_part2, sizeof(msg2_part2))); 128 CHK(mbedtls_md_hmac_finish(&ctx, out)); 129 print_buf("msg2", out, mbedtls_md_get_size(info)); 130 131exit: 132 mbedtls_md_free(&ctx); 133 mbedtls_platform_zeroize(out, sizeof(out)); 134 135 return ret; 136} 137 138int main(void) 139{ 140 int ret; 141 142 CHK(hmac_demo()); 143 144exit: 145 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 146} 147 148#endif 149