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