/* Copyright (c) (2012,2013,2015,2016,2018,2019) Apple Inc. All rights reserved. * * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which * is contained in the License.txt file distributed with corecrypto) and only to * people who accept that license. IMPORTANT: Any license rights granted to you by * Apple Inc. (if any) are limited to internal use within your organization only on * devices and computers you own or control, for the sole purpose of verifying the * security characteristics and correct functioning of the Apple Software. You may * not, directly or indirectly, redistribute the Apple Software or any portions thereof. */ #include "testmore.h" #include "testbyteBuffer.h" #include "testccnBuffer.h" #include "cc_priv.h" static int verbose = 0; #if (CCCMAC == 0) entryPoint(cccmac_tests,"cccmac test") #else #include "crypto_test_cmac.h" /* Currently, cccmac and friends won't work when length == 0 and the * data pointer is NULL. */ int showBytesAreEqual(byteBuffer bb1, byteBuffer bb2, char *label) { ok(bytesAreEqual(bb1, bb2), label); if(bytesAreEqual(bb1, bb2) == 0) { printByteBuffer(bb1, "Want"); printByteBuffer(bb2, "Got "); return 0; } return 1; } int test_cmac_answer(char *mode_name, const test_vector *vector, void*answer, char *test_type) { byteBuffer answer_bb; byteBuffer correct_answer_bb; int isEqual; if(vector->Mac == NULL) { answer_bb = bytesToBytes(answer, CMAC_BLOCKSIZE); diag("/* CMAC-%d test %d */", vector->Key_len*8, vector->Count); diag("\t\t\"%s\",\n", bytesToHexString(answer_bb)); return 1; } else { correct_answer_bb = hexStringToBytes((char *) vector->Mac); answer_bb = bytesToBytes(answer, correct_answer_bb->len); } isEqual=bytesAreEqual(correct_answer_bb, answer_bb); ok((isEqual && vector->Result==0) || (!isEqual && vector->Result!=0), "compare memory of answer"); if(!isEqual && vector->Result==0) { diag("Failed Test (%d) for CMAC-%d-%s %s", vector->Count, vector->Key_len*8, mode_name, test_type); printByteBuffer(correct_answer_bb, "Correct Answer"); printByteBuffer(answer_bb, "Provided Answer"); } free(correct_answer_bb); free(answer_bb); return 1; } /* ============================================================================= Test for new CMAC ==============================================================================*/ static int test_oneshot(const struct ccmode_cbc *cbc, char *mode_name, const test_vector *vector) { uint8_t answer[CMAC_BLOCKSIZE]; byteBuffer key = hexStringToBytes(vector->Key); byteBuffer in = hexStringToBytes(vector->Msg); byteBuffer expected_answer = hexStringToBytes(vector->Mac); if (vector->Result==0) { is(cccmac_one_shot_generate(cbc, key->len, key->bytes, in->len, in->bytes, expected_answer->len, answer),0,"generate cmac"); ok(test_cmac_answer(mode_name, vector, answer, "one-shot"), "check answer"); is(cccmac_one_shot_verify(cbc, key->len, key->bytes, in->len, in->bytes, expected_answer->len, expected_answer->bytes),0,"valid cmac"); } else { isnt(cccmac_one_shot_verify(cbc, key->len, key->bytes, in->len, in->bytes, expected_answer->len, expected_answer->bytes),0,"detect invalid cmac"); ok(test_cmac_answer(mode_name, vector, answer, "one-shot"), "check answer"); } free(key); free(in); free(expected_answer); return 1; } static int test_discrete(const struct ccmode_cbc *cbc, char *mode_name, const test_vector *vector) { uint8_t answer[CMAC_BLOCKSIZE]; cccmac_mode_decl(cbc, cmac); byteBuffer key = hexStringToBytes(vector->Key); byteBuffer in = hexStringToBytes(vector->Msg); size_t nbytes = in->len; uint8_t *data = in->bytes; is(cccmac_init(cbc, cmac, key->len, key->bytes),0,"init"); byteBuffer correct_answer_k1 = hexStringToBytes(vector->SubKey1); byteBuffer correct_answer_k2 = hexStringToBytes(vector->SubKey2); byteBuffer answer_k1 = bytesToBytes(cccmac_k1(cmac), 16); byteBuffer answer_k2 = bytesToBytes(cccmac_k2(cmac), 16); byteBuffer expected_answer = hexStringToBytes(vector->Mac); if (correct_answer_k1->len) { showBytesAreEqual(correct_answer_k1, answer_k1, "Subkey K1 is correct"); } if (correct_answer_k2->len) { showBytesAreEqual(correct_answer_k2, answer_k2, "Subkey K2 is correct"); } // Process some bytes size_t rbytes=cc_rand(32); size_t i; for(i=0; (i= blockchunck*CMAC_BLOCKSIZE) { is(cccmac_update(cmac, blockchunck*CMAC_BLOCKSIZE, data), 0, "update 2 blocks"); data += blockchunck*CMAC_BLOCKSIZE; nbytes -= blockchunck*CMAC_BLOCKSIZE; } else pass("update 2 blocks"); // Process the rest is(cccmac_update(cmac, nbytes, data),0,"update"); if (vector->Result==0) { cccmac_mode_decl(cbc, cmac2); memcpy(cmac2, cmac, cccmac_ctx_size(cccmac_cbc(cmac))); // Test generate is(cccmac_final_generate(cmac, expected_answer->len, answer),0,"final_generate"); ok(test_cmac_answer(mode_name, vector, answer, "one-shot"), "check answer"); // Test verify is(cccmac_final_verify(cmac2, expected_answer->len, expected_answer->bytes),0,"final_generate"); } else { isnt(cccmac_final_verify(cmac, expected_answer->len, expected_answer->bytes),0,"detect invalid cmac"); } free(key); free(in); free(correct_answer_k1); free(correct_answer_k2); free(answer_k1); free(answer_k2); free(expected_answer); return 1; } static int test_negative(const struct ccmode_cbc *cbc) { uint8_t key[32]; cccmac_mode_decl(cbc, cmac); isnt(cccmac_init(cbc, cmac, 15,key),0,"init"); return 0; } static int test_cmac(const struct ccmode_cbc *cbc, char *mode_name) { static const test_vector vector[] = { #define keystr128 "000102030405060708090a0b0c0d0e0f" #include "../test_vectors/CMACGenAES128.inc" #include "../test_vectors/CMACVerAES128.inc" #include "../test_vectors/CMACGenAES192.inc" #include "../test_vectors/CMACVerAES192.inc" #include "../test_vectors/CMACGenAES256.inc" #include "../test_vectors/CMACVerAES256.inc" { .Count = 1, // cnt .Key_len = 16, .Key = "2b7e151628aed2a6abf7158809cf4f3c", // keyStr .SubKey1 = "fbeed618357133667c85e08f7236a8de", // k1Str .SubKey2 = "f7ddac306ae266ccf90bc11ee46d513b", // k2Str .Msg = "", // in .Mac = "bb1d6929e95937287fa37d129b756746", // out .Result = 0 }, { .Count = 2, // cnt .Key_len = 16, .Key = "2b7e151628aed2a6abf7158809cf4f3c", // keyStr .SubKey1 = "fbeed618357133667c85e08f7236a8de", // k1Str .SubKey2 = "f7ddac306ae266ccf90bc11ee46d513b", // k2Str .Msg = "6bc1bee22e409f96e93d7e117393172a", // in .Mac = "070a16b46b4d4144f79bdd9dd04a287c", // out .Result = 0 }, { .Count = 3, // cnt .Key_len = 16, .Key = "2b7e151628aed2a6abf7158809cf4f3c", // keyStr .SubKey1 = "fbeed618357133667c85e08f7236a8de", // k1Str .SubKey2 = "f7ddac306ae266ccf90bc11ee46d513b", // k2Str .Msg = "6bc1bee22e409f96e93d7e117393172a"\ "ae2d8a571e03ac9c9eb76fac45af8e51"\ "30c81c46a35ce411", // in .Mac = "dfa66747de9ae63030ca32611497c827", // out .Result = 0 }, { .Count = 4, // cnt .Key_len = 16, .Key = "2b7e151628aed2a6abf7158809cf4f3c", // keyStr .SubKey1 = "fbeed618357133667c85e08f7236a8de", // k1Str .SubKey2 = "f7ddac306ae266ccf90bc11ee46d513b", // k2Str .Msg = "6bc1bee22e409f96e93d7e117393172a"\ "ae2d8a571e03ac9c9eb76fac45af8e51"\ "30c81c46a35ce411e5fbc1191a0a52ef"\ "f69f2445df4f9b17ad2b417be66c3710", // in .Mac = "51f0bebf7e3b9d92fc49741779363cfe", // out .Result = 0 }, { .Count = 5, // cnt .Key_len = 16, .Key = "2b7e151628aed2a6abf7158809cf4f3c", // keyStr .SubKey1 = "fbeed618357133667c85e08f7236a8de", // k1Str .SubKey2 = "f7ddac306ae266ccf90bc11ee46d513b", // k2Str .Msg = "00000000000000000000000000000001", // in .Mac = "d9fa25e90d2fa42543939a85b543e233", // out .Result = 0 }, }; size_t vector_size = sizeof (vector) / sizeof (test_vector); for(size_t i = 0; i < vector_size; i++) { ok(test_oneshot(cbc, mode_name, &vector[i]), "test one-shot AES%d_CMAC",vector[i].Key_len*8); ok(test_discrete(cbc, mode_name, &vector[i]), "test discrete AES%d_CMAC",vector[i].Key_len*8); } test_negative(cbc); return 1; } int cccmac_tests(TM_UNUSED int argc, TM_UNUSED char *const *argv) { plan_tests(50469); if(verbose) diag("Starting cmac tests"); ok(test_cmac(ccaes_cbc_encrypt_mode(), "system cbc di"), "CMAC Tests"); return 0; } #endif