md_hmac_demo.c (4685B)
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 OR GPL-2.0-or-later 24 */ 25 26 /* First include Mbed TLS headers to get the Mbed TLS configuration and 27 * platform definitions that we'll use in this program. Also include 28 * standard C headers for functions we'll use here. */ 29 #include "mbedtls/build_info.h" 30 31 #include "mbedtls/md.h" 32 33 #include "mbedtls/platform_util.h" // for mbedtls_platform_zeroize 34 35 #include <stdlib.h> 36 #include <stdio.h> 37 38 /* If the build options we need are not enabled, compile a placeholder. */ 39 #if !defined(MBEDTLS_MD_C) 40 int main(void) 41 { 42 printf("MBEDTLS_MD_C not defined\r\n"); 43 return 0; 44 } 45 #else 46 47 /* The real program starts here. */ 48 49 /* Dummy inputs for HMAC */ 50 const unsigned char msg1_part1[] = { 0x01, 0x02 }; 51 const unsigned char msg1_part2[] = { 0x03, 0x04 }; 52 const unsigned char msg2_part1[] = { 0x05, 0x05 }; 53 const unsigned char msg2_part2[] = { 0x06, 0x06 }; 54 55 /* Dummy key material - never do this in production! 56 * This example program uses SHA-256, so a 32-byte key makes sense. */ 57 const unsigned char key_bytes[32] = { 0 }; 58 59 /* Print the contents of a buffer in hex */ 60 static void print_buf(const char *title, unsigned char *buf, size_t len) 61 { 62 printf("%s:", title); 63 for (size_t i = 0; i < len; i++) { 64 printf(" %02x", buf[i]); 65 } 66 printf("\n"); 67 } 68 69 /* Run an Mbed TLS function and bail out if it fails. 70 * A string description of the error code can be recovered with: 71 * programs/util/strerror <value> */ 72 #define CHK(expr) \ 73 do \ 74 { \ 75 ret = (expr); \ 76 if (ret != 0) \ 77 { \ 78 printf("Error %d at line %d: %s\n", \ 79 ret, \ 80 __LINE__, \ 81 #expr); \ 82 goto exit; \ 83 } \ 84 } while (0) 85 86 /* 87 * This function demonstrates computation of the HMAC of two messages using 88 * the multipart API. 89 */ 90 static int hmac_demo(void) 91 { 92 int ret; 93 const mbedtls_md_type_t alg = MBEDTLS_MD_SHA256; 94 unsigned char out[MBEDTLS_MD_MAX_SIZE]; // safe but not optimal 95 96 mbedtls_md_context_t ctx; 97 98 mbedtls_md_init(&ctx); 99 100 /* prepare context and load key */ 101 // the last argument to setup is 1 to enable HMAC (not just hashing) 102 const mbedtls_md_info_t *info = mbedtls_md_info_from_type(alg); 103 CHK(mbedtls_md_setup(&ctx, info, 1)); 104 CHK(mbedtls_md_hmac_starts(&ctx, key_bytes, sizeof(key_bytes))); 105 106 /* compute HMAC(key, msg1_part1 | msg1_part2) */ 107 CHK(mbedtls_md_hmac_update(&ctx, msg1_part1, sizeof(msg1_part1))); 108 CHK(mbedtls_md_hmac_update(&ctx, msg1_part2, sizeof(msg1_part2))); 109 CHK(mbedtls_md_hmac_finish(&ctx, out)); 110 print_buf("msg1", out, mbedtls_md_get_size(info)); 111 112 /* compute HMAC(key, msg2_part1 | msg2_part2) */ 113 CHK(mbedtls_md_hmac_reset(&ctx)); // prepare for new operation 114 CHK(mbedtls_md_hmac_update(&ctx, msg2_part1, sizeof(msg2_part1))); 115 CHK(mbedtls_md_hmac_update(&ctx, msg2_part2, sizeof(msg2_part2))); 116 CHK(mbedtls_md_hmac_finish(&ctx, out)); 117 print_buf("msg2", out, mbedtls_md_get_size(info)); 118 119 exit: 120 mbedtls_md_free(&ctx); 121 mbedtls_platform_zeroize(out, sizeof(out)); 122 123 return ret; 124 } 125 126 int main(void) 127 { 128 int ret; 129 130 CHK(hmac_demo()); 131 132 exit: 133 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 134 } 135 136 #endif