18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * One-key CBC MAC (OMAC1) hash with AES 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes_wrap.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void gf_mulx(u8 *pad) 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, carry; 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt carry = pad[0] & 0x80; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < AES_BLOCK_SIZE - 1; i++) 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad[AES_BLOCK_SIZE - 1] <<= 1; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (carry) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad[AES_BLOCK_SIZE - 1] ^= 0x87; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES 3140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @key: Key for the hash operation 3240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @key_len: Key length in octets 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_elem: Number of elements in the data vector 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Pointers to the data areas 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Lengths of the data blocks 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (SP) 800-38B. 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidtint omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, 4440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt const u8 *addr[], const size_t *len, u8 *mac) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, e, left, total_len; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (TEST_FAIL()) 52d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 53d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 5440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt ctx = aes_encrypt_init(key, key_len); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cbc, 0, AES_BLOCK_SIZE); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt total_len = 0; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (e = 0; e < num_elem; e++) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt total_len += len[e]; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = total_len; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e = 0; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[0]; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[0]; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left >= AES_BLOCK_SIZE) { 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < AES_BLOCK_SIZE; i++) { 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[i] ^= *pos++; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos >= end) { 72fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt /* 73fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * Stop if there are no more bytes to process 74fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * since there are no more entries in the array. 75fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt */ 76fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (i + 1 == AES_BLOCK_SIZE && 77fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt left == AES_BLOCK_SIZE) 78fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt break; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e++; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[e]; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[e]; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > AES_BLOCK_SIZE) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, cbc, cbc); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= AES_BLOCK_SIZE; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pad, 0, AES_BLOCK_SIZE); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, pad, pad); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gf_mulx(pad); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left || total_len == 0) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < left; i++) { 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[i] ^= *pos++; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos >= end) { 97fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt /* 98fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * Stop if there are no more bytes to process 99fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * since there are no more entries in the array. 100fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt */ 101fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (i + 1 == left) 102fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt break; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e++; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[e]; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[e]; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[left] ^= 0x80; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gf_mulx(pad); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < AES_BLOCK_SIZE; i++) 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad[i] ^= cbc[i]; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, pad, mac); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt_deinit(ctx); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 12140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 12240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @key: 128-bit key for the hash operation 12340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @num_elem: Number of elements in the data vector 12440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @addr: Pointers to the data areas 12540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @len: Lengths of the data blocks 12640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 12740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Returns: 0 on success, -1 on failure 12840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * 12940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 13040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 13140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * (SP) 800-38B. 13240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt */ 13340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidtint omac1_aes_128_vector(const u8 *key, size_t num_elem, 13440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt const u8 *addr[], const size_t *len, u8 *mac) 13540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt{ 13640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt return omac1_aes_vector(key, 16, num_elem, addr, len, mac); 13740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt} 13840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt 13940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt 14040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt/** 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: 128-bit key for the hash operation 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data buffer for which a MAC is determined 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data_len: Length of data buffer in bytes 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (SP) 800-38B. 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt 15740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt 15840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt/** 15940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC) 16040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @key: 256-bit key for the hash operation 16140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @data: Data buffer for which a MAC is determined 16240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @data_len: Length of data buffer in bytes 16340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 16440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Returns: 0 on success, -1 on failure 16540b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * 16640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 16740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 16840b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * (SP) 800-38B. 16940b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt */ 17040b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidtint omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 17140b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt{ 17240b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); 17340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt} 174