1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2021 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#include <stdio.h> 11e1051a39Sopenharmony_ci#include <stdlib.h> 12e1051a39Sopenharmony_ci#include <openssl/core_names.h> 13e1051a39Sopenharmony_ci#include <openssl/evp.h> 14e1051a39Sopenharmony_ci#include <openssl/params.h> 15e1051a39Sopenharmony_ci#include <openssl/err.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci/* 18e1051a39Sopenharmony_ci * Taken from NIST's GCM Test Vectors 19e1051a39Sopenharmony_ci * http://csrc.nist.gov/groups/STM/cavp/ 20e1051a39Sopenharmony_ci */ 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci/* 23e1051a39Sopenharmony_ci * Hard coding the key into an application is very bad. 24e1051a39Sopenharmony_ci * It is done here solely for educational purposes. 25e1051a39Sopenharmony_ci */ 26e1051a39Sopenharmony_cistatic unsigned char key[] = { 27e1051a39Sopenharmony_ci 0x77, 0xbe, 0x63, 0x70, 0x89, 0x71, 0xc4, 0xe2, 28e1051a39Sopenharmony_ci 0x40, 0xd1, 0xcb, 0x79, 0xe8, 0xd7, 0x7f, 0xeb 29e1051a39Sopenharmony_ci}; 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci/* 32e1051a39Sopenharmony_ci * The initialisation vector (IV) is better not being hard coded too. 33e1051a39Sopenharmony_ci * Repeating password/IV pairs compromises the integrity of GMAC. 34e1051a39Sopenharmony_ci * The IV is not considered secret information and is safe to store with 35e1051a39Sopenharmony_ci * an encrypted password. 36e1051a39Sopenharmony_ci */ 37e1051a39Sopenharmony_cistatic unsigned char iv[] = { 38e1051a39Sopenharmony_ci 0xe0, 0xe0, 0x0f, 0x19, 0xfe, 0xd7, 0xba, 39e1051a39Sopenharmony_ci 0x01, 0x36, 0xa7, 0x97, 0xf3 40e1051a39Sopenharmony_ci}; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_cistatic unsigned char data[] = { 43e1051a39Sopenharmony_ci 0x7a, 0x43, 0xec, 0x1d, 0x9c, 0x0a, 0x5a, 0x78, 44e1051a39Sopenharmony_ci 0xa0, 0xb1, 0x65, 0x33, 0xa6, 0x21, 0x3c, 0xab 45e1051a39Sopenharmony_ci}; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_cistatic const unsigned char expected_output[] = { 48e1051a39Sopenharmony_ci 0x20, 0x9f, 0xcc, 0x8d, 0x36, 0x75, 0xed, 0x93, 49e1051a39Sopenharmony_ci 0x8e, 0x9c, 0x71, 0x66, 0x70, 0x9d, 0xd9, 0x46 50e1051a39Sopenharmony_ci}; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci/* 53e1051a39Sopenharmony_ci * A property query used for selecting the GMAC implementation and the 54e1051a39Sopenharmony_ci * underlying GCM mode cipher. 55e1051a39Sopenharmony_ci */ 56e1051a39Sopenharmony_cistatic char *propq = NULL; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ciint main(int argc, char **argv) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci int rv = EXIT_FAILURE; 61e1051a39Sopenharmony_ci EVP_MAC *mac = NULL; 62e1051a39Sopenharmony_ci EVP_MAC_CTX *mctx = NULL; 63e1051a39Sopenharmony_ci unsigned char out[16]; 64e1051a39Sopenharmony_ci OSSL_PARAM params[4], *p = params; 65e1051a39Sopenharmony_ci OSSL_LIB_CTX *library_context = NULL; 66e1051a39Sopenharmony_ci size_t out_len = 0; 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci library_context = OSSL_LIB_CTX_new(); 69e1051a39Sopenharmony_ci if (library_context == NULL) { 70e1051a39Sopenharmony_ci fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 71e1051a39Sopenharmony_ci goto end; 72e1051a39Sopenharmony_ci } 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci /* Fetch the GMAC implementation */ 75e1051a39Sopenharmony_ci mac = EVP_MAC_fetch(library_context, "GMAC", propq); 76e1051a39Sopenharmony_ci if (mac == NULL) { 77e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_fetch() returned NULL\n"); 78e1051a39Sopenharmony_ci goto end; 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci /* Create a context for the GMAC operation */ 82e1051a39Sopenharmony_ci mctx = EVP_MAC_CTX_new(mac); 83e1051a39Sopenharmony_ci if (mctx == NULL) { 84e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_CTX_new() returned NULL\n"); 85e1051a39Sopenharmony_ci goto end; 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci /* GMAC requries a GCM mode cipher to be specified */ 89e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, 90e1051a39Sopenharmony_ci "AES-128-GCM", 0); 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci /* 93e1051a39Sopenharmony_ci * If a non-default property query is required when fetching the GCM mode 94e1051a39Sopenharmony_ci * cipher, it needs to be specified too. 95e1051a39Sopenharmony_ci */ 96e1051a39Sopenharmony_ci if (propq != NULL) 97e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, 98e1051a39Sopenharmony_ci propq, 0); 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci /* Set the initialisation vector (IV) */ 101e1051a39Sopenharmony_ci *p++ = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_IV, 102e1051a39Sopenharmony_ci iv, sizeof(iv)); 103e1051a39Sopenharmony_ci *p = OSSL_PARAM_construct_end(); 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci /* Initialise the GMAC operation */ 106e1051a39Sopenharmony_ci if (!EVP_MAC_init(mctx, key, sizeof(key), params)) { 107e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_init() failed\n"); 108e1051a39Sopenharmony_ci goto end; 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci /* Make one or more calls to process the data to be authenticated */ 112e1051a39Sopenharmony_ci if (!EVP_MAC_update(mctx, data, sizeof(data))) { 113e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_update() failed\n"); 114e1051a39Sopenharmony_ci goto end; 115e1051a39Sopenharmony_ci } 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci /* Make one call to the final to get the MAC */ 118e1051a39Sopenharmony_ci if (!EVP_MAC_final(mctx, out, &out_len, sizeof(out))) { 119e1051a39Sopenharmony_ci fprintf(stderr, "EVP_MAC_final() failed\n"); 120e1051a39Sopenharmony_ci goto end; 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci printf("Generated MAC:\n"); 124e1051a39Sopenharmony_ci BIO_dump_indent_fp(stdout, out, out_len, 2); 125e1051a39Sopenharmony_ci putchar('\n'); 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ci if (out_len != sizeof(expected_output)) { 128e1051a39Sopenharmony_ci fprintf(stderr, "Generated MAC has an unexpected length\n"); 129e1051a39Sopenharmony_ci goto end; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) { 133e1051a39Sopenharmony_ci fprintf(stderr, "Generated MAC does not match expected value\n"); 134e1051a39Sopenharmony_ci goto end; 135e1051a39Sopenharmony_ci } 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci rv = EXIT_SUCCESS; 138e1051a39Sopenharmony_ciend: 139e1051a39Sopenharmony_ci EVP_MAC_CTX_free(mctx); 140e1051a39Sopenharmony_ci EVP_MAC_free(mac); 141e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(library_context); 142e1051a39Sopenharmony_ci if (rv != EXIT_SUCCESS) 143e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 144e1051a39Sopenharmony_ci return rv; 145e1051a39Sopenharmony_ci} 146