1e1051a39Sopenharmony_ci/*- 2e1051a39Sopenharmony_ci * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * Example of using EVP_MAC_ methods to calculate 12e1051a39Sopenharmony_ci * a HMAC of static buffers 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_ci#include <string.h> 16e1051a39Sopenharmony_ci#include <stdio.h> 17e1051a39Sopenharmony_ci#include <openssl/crypto.h> 18e1051a39Sopenharmony_ci#include <openssl/core_names.h> 19e1051a39Sopenharmony_ci#include <openssl/err.h> 20e1051a39Sopenharmony_ci#include <openssl/evp.h> 21e1051a39Sopenharmony_ci#include <openssl/hmac.h> 22e1051a39Sopenharmony_ci#include <openssl/params.h> 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci/* 25e1051a39Sopenharmony_ci * Hard coding the key into an application is very bad. 26e1051a39Sopenharmony_ci * It is done here solely for educational purposes. 27e1051a39Sopenharmony_ci */ 28e1051a39Sopenharmony_cistatic unsigned char key[] = { 29e1051a39Sopenharmony_ci 0x25, 0xfd, 0x12, 0x99, 0xdf, 0xad, 0x1a, 0x03, 30e1051a39Sopenharmony_ci 0x0a, 0x81, 0x3c, 0x2d, 0xcc, 0x05, 0xd1, 0x5c, 31e1051a39Sopenharmony_ci 0x17, 0x7a, 0x36, 0x73, 0x17, 0xef, 0x41, 0x75, 32e1051a39Sopenharmony_ci 0x71, 0x18, 0xe0, 0x1a, 0xda, 0x99, 0xc3, 0x61, 33e1051a39Sopenharmony_ci 0x38, 0xb5, 0xb1, 0xe0, 0x82, 0x2c, 0x70, 0xa4, 34e1051a39Sopenharmony_ci 0xc0, 0x8e, 0x5e, 0xf9, 0x93, 0x9f, 0xcf, 0xf7, 35e1051a39Sopenharmony_ci 0x32, 0x4d, 0x0c, 0xbd, 0x31, 0x12, 0x0f, 0x9a, 36e1051a39Sopenharmony_ci 0x15, 0xee, 0x82, 0xdb, 0x8d, 0x29, 0x54, 0x14, 37e1051a39Sopenharmony_ci}; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_cistatic const unsigned char data[] = 40e1051a39Sopenharmony_ci "To be, or not to be, that is the question,\n" 41e1051a39Sopenharmony_ci "Whether tis nobler in the minde to suffer\n" 42e1051a39Sopenharmony_ci "The ſlings and arrowes of outragious fortune,\n" 43e1051a39Sopenharmony_ci "Or to take Armes again in a sea of troubles,\n" 44e1051a39Sopenharmony_ci "And by opposing, end them, to die to sleep;\n" 45e1051a39Sopenharmony_ci "No more, and by a sleep, to say we end\n" 46e1051a39Sopenharmony_ci "The heart-ache, and the thousand natural shocks\n" 47e1051a39Sopenharmony_ci "That flesh is heir to? tis a consumation\n" 48e1051a39Sopenharmony_ci "Devoutly to be wished. To die to sleep,\n" 49e1051a39Sopenharmony_ci "To sleepe, perchance to dreame, Aye, there's the rub,\n" 50e1051a39Sopenharmony_ci "For in that sleep of death what dreams may come\n" 51e1051a39Sopenharmony_ci "When we haue shuffled off this mortal coil\n" 52e1051a39Sopenharmony_ci "Must give us pause. There's the respect\n" 53e1051a39Sopenharmony_ci "That makes calamity of so long life:\n" 54e1051a39Sopenharmony_ci "For who would bear the Ships and Scorns of time,\n" 55e1051a39Sopenharmony_ci "The oppressor's wrong, the proud man's Contumely,\n" 56e1051a39Sopenharmony_ci "The pangs of dispised love, the Law's delay,\n" 57e1051a39Sopenharmony_ci; 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci/* The known value of the HMAC/SHA3-512 MAC of the above soliloqy */ 60e1051a39Sopenharmony_cistatic const unsigned char expected_output[] = { 61e1051a39Sopenharmony_ci 0x3b, 0x77, 0x5f, 0xf1, 0x4f, 0x9e, 0xb9, 0x23, 62e1051a39Sopenharmony_ci 0x8f, 0xdc, 0xa0, 0x68, 0x15, 0x7b, 0x8a, 0xf1, 63e1051a39Sopenharmony_ci 0x96, 0x23, 0xaa, 0x3c, 0x1f, 0xe9, 0xdc, 0x89, 64e1051a39Sopenharmony_ci 0x11, 0x7d, 0x58, 0x07, 0xe7, 0x96, 0x17, 0xe3, 65e1051a39Sopenharmony_ci 0x44, 0x8b, 0x03, 0x37, 0x91, 0xc0, 0x6e, 0x06, 66e1051a39Sopenharmony_ci 0x7c, 0x54, 0xe4, 0xa4, 0xcc, 0xd5, 0x16, 0xbb, 67e1051a39Sopenharmony_ci 0x5e, 0x4d, 0x64, 0x7d, 0x88, 0x23, 0xc9, 0xb7, 68e1051a39Sopenharmony_ci 0x25, 0xda, 0xbe, 0x4b, 0xe4, 0xd5, 0x34, 0x30, 69e1051a39Sopenharmony_ci}; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci/* 72e1051a39Sopenharmony_ci * A property query used for selecting the MAC implementation. 73e1051a39Sopenharmony_ci */ 74e1051a39Sopenharmony_cistatic const char *propq = NULL; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ciint main(void) 77e1051a39Sopenharmony_ci{ 78e1051a39Sopenharmony_ci int rv = EXIT_FAILURE; 79e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context = NULL; 80e1051a39Sopenharmony_ci EVP_MAC *mac = NULL; 81e1051a39Sopenharmony_ci EVP_MAC_CTX *mctx = NULL; 82e1051a39Sopenharmony_ci EVP_MD_CTX *digest_context = NULL; 83e1051a39Sopenharmony_ci unsigned char *out = NULL; 84e1051a39Sopenharmony_ci size_t out_len = 0; 85e1051a39Sopenharmony_ci OSSL_PARAM params[4], *p = params; 86e1051a39Sopenharmony_ci char digest_name[] = "SHA3-512"; 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 89e1051a39Sopenharmony_ci if (library_context == NULL) { 90e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 91e1051a39Sopenharmony_ci goto end; 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci /* Fetch the HMAC implementation */ 95e1051a39Sopenharmony_ci mac = EVP_MAC_fetch(library_context, "HMAC", propq); 96e1051a39Sopenharmony_ci if (mac == NULL) { 97e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_fetch() returned NULL\n"); 98e1051a39Sopenharmony_ci goto end; 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci /* Create a context for the HMAC operation */ 102e1051a39Sopenharmony_ci mctx = EVP_MAC_CTX_new(mac); 103e1051a39Sopenharmony_ci if (mctx == NULL) { 104e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_CTX_new() returned NULL\n"); 105e1051a39Sopenharmony_ci goto end; 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci /* The underlying digest to be used */ 109e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_name, 110e1051a39Sopenharmony_ci sizeof(digest_name)); 111e1051a39Sopenharmony_ci *p = OSSL_PARAM_construct_end(); 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci /* Initialise the HMAC operation */ 114e1051a39Sopenharmony_ci if (!EVP_MAC_init(mctx, key, sizeof(key), params)) { 115e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_init() failed\n"); 116e1051a39Sopenharmony_ci goto end; 117e1051a39Sopenharmony_ci } 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci /* Make one or more calls to process the data to be authenticated */ 120e1051a39Sopenharmony_ci if (!EVP_MAC_update(mctx, data, sizeof(data))) { 121e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_update() failed\n"); 122e1051a39Sopenharmony_ci goto end; 123e1051a39Sopenharmony_ci } 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci /* Make a call to the final with a NULL buffer to get the length of the MAC */ 126e1051a39Sopenharmony_ci if (!EVP_MAC_final(mctx, NULL, &out_len, 0)) { 127e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_final() failed\n"); 128e1051a39Sopenharmony_ci goto end; 129e1051a39Sopenharmony_ci } 130e1051a39Sopenharmony_ci out = OPENSSL_malloc(out_len); 131e1051a39Sopenharmony_ci if (out == NULL) { 132e1051a39Sopenharmony_ci fprintf(stderr, "malloc failed\n"); 133e1051a39Sopenharmony_ci goto end; 134e1051a39Sopenharmony_ci } 135e1051a39Sopenharmony_ci /* Make one call to the final to get the MAC */ 136e1051a39Sopenharmony_ci if (!EVP_MAC_final(mctx, out, &out_len, out_len)) { 137e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_final() failed\n"); 138e1051a39Sopenharmony_ci goto end; 139e1051a39Sopenharmony_ci } 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci printf("Generated MAC:\n"); 142e1051a39Sopenharmony_ci BIO_dump_indent_fp(stdout, out, out_len, 2); 143e1051a39Sopenharmony_ci putchar('\n'); 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (out_len != sizeof(expected_output)) { 146e1051a39Sopenharmony_ci fprintf(stderr, "Generated MAC has an unexpected length\n"); 147e1051a39Sopenharmony_ci goto end; 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) { 151e1051a39Sopenharmony_ci fprintf(stderr, "Generated MAC does not match expected value\n"); 152e1051a39Sopenharmony_ci goto end; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci rv = EXIT_SUCCESS; 156e1051a39Sopenharmony_ciend: 157e1051a39Sopenharmony_ci if (rv != EXIT_SUCCESS) 158e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 159e1051a39Sopenharmony_ci /* OpenSSL free functions will ignore NULL arguments */ 160e1051a39Sopenharmony_ci OPENSSL_free(out); 161e1051a39Sopenharmony_ci EVP_MD_CTX_free(digest_context); 162e1051a39Sopenharmony_ci EVP_MAC_CTX_free(mctx); 163e1051a39Sopenharmony_ci EVP_MAC_free(mac); 164e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 165e1051a39Sopenharmony_ci return rv; 166e1051a39Sopenharmony_ci} 167