Home | History | Annotate | Line # | Download | only in test
cmactest.c revision 1.1.1.2
      1 /*
      2  * Copyright 1995-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  * CMAC low level APIs are deprecated for public use, but still ok for internal
     12  * use.
     13  */
     14 #include "internal/deprecated.h"
     15 
     16 #include <stdio.h>
     17 #include <string.h>
     18 #include <stdlib.h>
     19 
     20 #include "internal/nelem.h"
     21 
     22 #include <openssl/cmac.h>
     23 #include <openssl/aes.h>
     24 #include <openssl/evp.h>
     25 
     26 #include "testutil.h"
     27 
     28 static const char xtskey[32] = {
     29     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
     30     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     31     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
     32 };
     33 
     34 static struct test_st {
     35     const char key[32];
     36     int key_len;
     37     unsigned char data[4096];
     38     int data_len;
     39     const char *mac;
     40 } test[] = {
     41     { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     42           0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
     43         16,
     44         "My test data",
     45         12,
     46         "29cec977c48f63c200bd5c4a6881b224" },
     47     { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     48           0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
     49           0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
     50         32,
     51         "My test data",
     52         12,
     53         "db6493aa04e4761f473b2b453c031c9a" },
     54     { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     55           0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
     56           0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
     57         32,
     58         "My test data again",
     59         18,
     60         "65c11c75ecf590badd0a5e56cbb8af60" },
     61     /* for aes-128-cbc */
     62     {
     63         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     64             0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
     65         16,
     66         /* repeat the string below until filling 3072 bytes */
     67         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
     68         3072,
     69         "35da8a02a7afce90e5b711308cee2dee" },
     70     /* for aes-192-cbc */
     71     {
     72         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     73             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
     74             0x16, 0x17 },
     75         24,
     76         /* repeat the string below until filling 4095 bytes */
     77         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
     78         4095,
     79         "59053f4e81f3593610f987adb547c5b2" },
     80     /* for aes-256-cbc */
     81     {
     82         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     83             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
     84             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
     85         32,
     86         /* repeat the string below until filling 2560 bytes */
     87         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
     88         2560,
     89         "9c6cf85f7f4baca99725764a0df973a9" },
     90     /* for des-ede3-cbc */
     91     {
     92         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
     93             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
     94             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
     95         24,
     96         /* repeat the string below until filling 2048 bytes */
     97         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
     98         2048,
     99         "2c2fccc7fcc5d98a" },
    100     /* for sm4-cbc */
    101     {
    102         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
    103             0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
    104         16,
    105         /* repeat the string below until filling 2049 bytes */
    106         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
    107         2049,
    108         "c9a9cbc82a3b2d96074e386fce1216f2" },
    109 };
    110 
    111 static char *pt(unsigned char *md, unsigned int len);
    112 
    113 static int test_cmac_bad(void)
    114 {
    115     CMAC_CTX *ctx = NULL;
    116     int ret = 0;
    117 
    118     ctx = CMAC_CTX_new();
    119     if (!TEST_ptr(ctx)
    120         || !TEST_false(CMAC_Init(ctx, NULL, 0, NULL, NULL))
    121         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
    122         /* Should be able to pass cipher first, and then key */
    123         || !TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_128_cbc(), NULL))
    124         /* Must have a key */
    125         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
    126         /* Now supply the key */
    127         || !TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len, NULL, NULL))
    128         /* Update should now work */
    129         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
    130         /* XTS is not a suitable cipher to use */
    131         || !TEST_false(CMAC_Init(ctx, xtskey, sizeof(xtskey), EVP_aes_128_xts(),
    132             NULL))
    133         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len)))
    134         goto err;
    135 
    136     ret = 1;
    137 err:
    138     CMAC_CTX_free(ctx);
    139     return ret;
    140 }
    141 
    142 static int test_cmac_run(void)
    143 {
    144     char *p;
    145     CMAC_CTX *ctx = NULL;
    146     unsigned char buf[AES_BLOCK_SIZE];
    147     size_t len;
    148     int ret = 0;
    149     size_t case_idx = 0;
    150 
    151     ctx = CMAC_CTX_new();
    152 
    153     /* Construct input data, fill repeatedly until reaching data length */
    154     for (case_idx = 0; case_idx < OSSL_NELEM(test); case_idx++) {
    155         size_t str_len = strlen((char *)test[case_idx].data);
    156         size_t fill_len = test[case_idx].data_len - str_len;
    157         size_t fill_idx = str_len;
    158         while (fill_len > 0) {
    159             if (fill_len > str_len) {
    160                 memcpy(&test[case_idx].data[fill_idx], test[case_idx].data, str_len);
    161                 fill_len -= str_len;
    162                 fill_idx += str_len;
    163             } else {
    164                 memcpy(&test[case_idx].data[fill_idx], test[case_idx].data, fill_len);
    165                 fill_len = 0;
    166             }
    167         }
    168     }
    169 
    170     if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
    171             EVP_aes_128_cbc(), NULL))
    172         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
    173         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    174         goto err;
    175 
    176     p = pt(buf, len);
    177     if (!TEST_str_eq(p, test[0].mac))
    178         goto err;
    179 
    180     if (!TEST_true(CMAC_Init(ctx, test[1].key, test[1].key_len,
    181             EVP_aes_256_cbc(), NULL))
    182         || !TEST_true(CMAC_Update(ctx, test[1].data, test[1].data_len))
    183         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    184         goto err;
    185 
    186     p = pt(buf, len);
    187     if (!TEST_str_eq(p, test[1].mac))
    188         goto err;
    189 
    190     if (!TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
    191         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
    192         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    193         goto err;
    194     p = pt(buf, len);
    195     if (!TEST_str_eq(p, test[2].mac))
    196         goto err;
    197     /* Test reusing a key */
    198     if (!TEST_true(CMAC_Init(ctx, NULL, 0, NULL, NULL))
    199         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
    200         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    201         goto err;
    202     p = pt(buf, len);
    203     if (!TEST_str_eq(p, test[2].mac))
    204         goto err;
    205 
    206     /* Test setting the cipher and key separately */
    207     if (!TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_256_cbc(), NULL))
    208         || !TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
    209         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
    210         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    211         goto err;
    212     p = pt(buf, len);
    213     if (!TEST_str_eq(p, test[2].mac))
    214         goto err;
    215 
    216     /* Test data length is greater than 1 block length */
    217     if (!TEST_true(CMAC_Init(ctx, test[3].key, test[3].key_len,
    218             EVP_aes_128_cbc(), NULL))
    219         || !TEST_true(CMAC_Update(ctx, test[3].data, test[3].data_len))
    220         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    221         goto err;
    222     p = pt(buf, len);
    223     if (!TEST_str_eq(p, test[3].mac))
    224         goto err;
    225 
    226     if (!TEST_true(CMAC_Init(ctx, test[4].key, test[4].key_len,
    227             EVP_aes_192_cbc(), NULL))
    228         || !TEST_true(CMAC_Update(ctx, test[4].data, test[4].data_len))
    229         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    230         goto err;
    231     p = pt(buf, len);
    232     if (!TEST_str_eq(p, test[4].mac))
    233         goto err;
    234 
    235     if (!TEST_true(CMAC_Init(ctx, test[5].key, test[5].key_len,
    236             EVP_aes_256_cbc(), NULL))
    237         || !TEST_true(CMAC_Update(ctx, test[5].data, test[5].data_len))
    238         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    239         goto err;
    240     p = pt(buf, len);
    241     if (!TEST_str_eq(p, test[5].mac))
    242         goto err;
    243 
    244 #ifndef OPENSSL_NO_DES
    245     if (!TEST_true(CMAC_Init(ctx, test[6].key, test[6].key_len,
    246             EVP_des_ede3_cbc(), NULL))
    247         || !TEST_true(CMAC_Update(ctx, test[6].data, test[6].data_len))
    248         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    249         goto err;
    250     p = pt(buf, len);
    251     if (!TEST_str_eq(p, test[6].mac))
    252         goto err;
    253 #endif
    254 
    255 #ifndef OPENSSL_NO_SM4
    256     if (!TEST_true(CMAC_Init(ctx, test[7].key, test[7].key_len,
    257             EVP_sm4_cbc(), NULL))
    258         || !TEST_true(CMAC_Update(ctx, test[7].data, test[7].data_len))
    259         || !TEST_true(CMAC_Final(ctx, buf, &len)))
    260         goto err;
    261     p = pt(buf, len);
    262     if (!TEST_str_eq(p, test[7].mac))
    263         goto err;
    264 #endif
    265 
    266     ret = 1;
    267 err:
    268     CMAC_CTX_free(ctx);
    269     return ret;
    270 }
    271 
    272 static int test_cmac_copy(void)
    273 {
    274     char *p;
    275     CMAC_CTX *ctx = NULL, *ctx2 = NULL;
    276     unsigned char buf[AES_BLOCK_SIZE];
    277     size_t len;
    278     int ret = 0;
    279 
    280     ctx = CMAC_CTX_new();
    281     ctx2 = CMAC_CTX_new();
    282     if (!TEST_ptr(ctx) || !TEST_ptr(ctx2))
    283         goto err;
    284 
    285     if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
    286             EVP_aes_128_cbc(), NULL))
    287         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
    288         || !TEST_true(CMAC_CTX_copy(ctx2, ctx))
    289         || !TEST_true(CMAC_Final(ctx2, buf, &len)))
    290         goto err;
    291 
    292     p = pt(buf, len);
    293     if (!TEST_str_eq(p, test[0].mac))
    294         goto err;
    295 
    296     ret = 1;
    297 err:
    298     CMAC_CTX_free(ctx2);
    299     CMAC_CTX_free(ctx);
    300     return ret;
    301 }
    302 
    303 #define OSSL_HEX_CHARS_PER_BYTE 2
    304 static char *pt(unsigned char *md, unsigned int len)
    305 {
    306     unsigned int i;
    307     static char buf[81];
    308 
    309     for (i = 0; i < len && (i + 1) * OSSL_HEX_CHARS_PER_BYTE < sizeof(buf); i++)
    310         BIO_snprintf(buf + i * OSSL_HEX_CHARS_PER_BYTE,
    311             OSSL_HEX_CHARS_PER_BYTE + 1, "%02x", md[i]);
    312     return buf;
    313 }
    314 
    315 int setup_tests(void)
    316 {
    317     ADD_TEST(test_cmac_bad);
    318     ADD_TEST(test_cmac_run);
    319     ADD_TEST(test_cmac_copy);
    320     return 1;
    321 }
    322