Home | History | Annotate | Line # | Download | only in mac
      1 /*-
      2  * Copyright 2022-2023 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 /*
     11  * Example of using EVP_MAC_ methods to calculate
     12  * a CMAC of static buffers
     13  */
     14 
     15 #include <string.h>
     16 #include <stdio.h>
     17 #include <openssl/crypto.h>
     18 #include <openssl/core_names.h>
     19 #include <openssl/err.h>
     20 #include <openssl/evp.h>
     21 #include <openssl/cmac.h>
     22 #include <openssl/params.h>
     23 
     24 /*
     25  * Hard coding the key into an application is very bad.
     26  * It is done here solely for educational purposes.
     27  */
     28 static unsigned char key[] = {
     29     0x6c,
     30     0xde,
     31     0x14,
     32     0xf5,
     33     0xd5,
     34     0x2a,
     35     0x4a,
     36     0xdf,
     37     0x12,
     38     0x39,
     39     0x1e,
     40     0xbf,
     41     0x36,
     42     0xf9,
     43     0x6a,
     44     0x46,
     45     0x48,
     46     0xd0,
     47     0xb6,
     48     0x51,
     49     0x89,
     50     0xfc,
     51     0x24,
     52     0x85,
     53     0xa8,
     54     0x8d,
     55     0xdf,
     56     0x7e,
     57     0x80,
     58     0x14,
     59     0xc8,
     60     0xce,
     61 };
     62 
     63 static const unsigned char data[] = "To be, or not to be, that is the question,\n"
     64                                     "Whether tis nobler in the minde to suffer\n"
     65                                     "The lings and arrowes of outragious fortune,\n"
     66                                     "Or to take Armes again in a sea of troubles,\n"
     67                                     "And by opposing, end them, to die to sleep;\n"
     68                                     "No more, and by a sleep, to say we end\n"
     69                                     "The heart-ache, and the thousand natural shocks\n"
     70                                     "That flesh is heir to? tis a consumation\n"
     71                                     "Devoutly to be wished. To die to sleep,\n"
     72                                     "To sleepe, perchance to dreame, Aye, there's the rub,\n"
     73                                     "For in that sleep of death what dreams may come\n"
     74                                     "When we haue shuffled off this mortal coil\n"
     75                                     "Must give us pause. There's the respect\n"
     76                                     "That makes calamity of so long life:\n"
     77                                     "For who would bear the Ships and Scorns of time,\n"
     78                                     "The oppressor's wrong, the proud man's Contumely,\n"
     79                                     "The pangs of dispised love, the Law's delay,\n";
     80 
     81 /* The known value of the CMAC/AES256 MAC of the above soliloqy */
     82 static const unsigned char expected_output[] = {
     83     0x67,
     84     0x92,
     85     0x32,
     86     0x23,
     87     0x50,
     88     0x3d,
     89     0xc5,
     90     0xba,
     91     0x78,
     92     0xd4,
     93     0x6d,
     94     0x63,
     95     0xf2,
     96     0x2b,
     97     0xe9,
     98     0x56,
     99 };
    100 
    101 /*
    102  * A property query used for selecting the MAC implementation.
    103  */
    104 static const char *propq = NULL;
    105 
    106 int main(void)
    107 {
    108     int ret = EXIT_FAILURE;
    109     OSSL_LIB_CTX *library_context = NULL;
    110     EVP_MAC *mac = NULL;
    111     EVP_MAC_CTX *mctx = NULL;
    112     unsigned char *out = NULL;
    113     size_t out_len = 0;
    114     OSSL_PARAM params[4], *p = params;
    115     char cipher_name[] = "AES-256-CBC";
    116 
    117     library_context = OSSL_LIB_CTX_new();
    118     if (library_context == NULL) {
    119         fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
    120         goto end;
    121     }
    122 
    123     /* Fetch the CMAC implementation */
    124     mac = EVP_MAC_fetch(library_context, "CMAC", propq);
    125     if (mac == NULL) {
    126         fprintf(stderr, "EVP_MAC_fetch() returned NULL\n");
    127         goto end;
    128     }
    129 
    130     /* Create a context for the CMAC operation */
    131     mctx = EVP_MAC_CTX_new(mac);
    132     if (mctx == NULL) {
    133         fprintf(stderr, "EVP_MAC_CTX_new() returned NULL\n");
    134         goto end;
    135     }
    136 
    137     /* The underlying cipher to be used */
    138     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name,
    139         sizeof(cipher_name));
    140     *p = OSSL_PARAM_construct_end();
    141 
    142     /* Initialise the CMAC operation */
    143     if (!EVP_MAC_init(mctx, key, sizeof(key), params)) {
    144         fprintf(stderr, "EVP_MAC_init() failed\n");
    145         goto end;
    146     }
    147 
    148     /* Make one or more calls to process the data to be authenticated */
    149     if (!EVP_MAC_update(mctx, data, sizeof(data))) {
    150         fprintf(stderr, "EVP_MAC_update() failed\n");
    151         goto end;
    152     }
    153 
    154     /* Make a call to the final with a NULL buffer to get the length of the MAC */
    155     if (!EVP_MAC_final(mctx, NULL, &out_len, 0)) {
    156         fprintf(stderr, "EVP_MAC_final() failed\n");
    157         goto end;
    158     }
    159     out = OPENSSL_malloc(out_len);
    160     if (out == NULL) {
    161         fprintf(stderr, "malloc failed\n");
    162         goto end;
    163     }
    164     /* Make one call to the final to get the MAC */
    165     if (!EVP_MAC_final(mctx, out, &out_len, out_len)) {
    166         fprintf(stderr, "EVP_MAC_final() failed\n");
    167         goto end;
    168     }
    169 
    170     printf("Generated MAC:\n");
    171     BIO_dump_indent_fp(stdout, out, out_len, 2);
    172     putchar('\n');
    173 
    174     if (out_len != sizeof(expected_output)) {
    175         fprintf(stderr, "Generated MAC has an unexpected length\n");
    176         goto end;
    177     }
    178 
    179     if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) {
    180         fprintf(stderr, "Generated MAC does not match expected value\n");
    181         goto end;
    182     }
    183 
    184     ret = EXIT_SUCCESS;
    185 end:
    186     if (ret != EXIT_SUCCESS)
    187         ERR_print_errors_fp(stderr);
    188     /* OpenSSL free functions will ignore NULL arguments */
    189     OPENSSL_free(out);
    190     EVP_MAC_CTX_free(mctx);
    191     EVP_MAC_free(mac);
    192     OSSL_LIB_CTX_free(library_context);
    193     return ret;
    194 }
    195