1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * One-key CBC MAC (OMAC1) hash with AES 3e5b75505Sopenharmony_ci * 4e5b75505Sopenharmony_ci * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 5e5b75505Sopenharmony_ci * 6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 7e5b75505Sopenharmony_ci * See README for more details. 8e5b75505Sopenharmony_ci */ 9e5b75505Sopenharmony_ci 10e5b75505Sopenharmony_ci#include "includes.h" 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "aes.h" 14e5b75505Sopenharmony_ci#include "aes_wrap.h" 15e5b75505Sopenharmony_ci 16e5b75505Sopenharmony_cistatic void gf_mulx(u8 *pad) 17e5b75505Sopenharmony_ci{ 18e5b75505Sopenharmony_ci int i, carry; 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_ci carry = pad[0] & 0x80; 21e5b75505Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE - 1; i++) 22e5b75505Sopenharmony_ci pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); 23e5b75505Sopenharmony_ci pad[AES_BLOCK_SIZE - 1] <<= 1; 24e5b75505Sopenharmony_ci if (carry) 25e5b75505Sopenharmony_ci pad[AES_BLOCK_SIZE - 1] ^= 0x87; 26e5b75505Sopenharmony_ci} 27e5b75505Sopenharmony_ci 28e5b75505Sopenharmony_ci 29e5b75505Sopenharmony_ci/** 30e5b75505Sopenharmony_ci * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES 31e5b75505Sopenharmony_ci * @key: Key for the hash operation 32e5b75505Sopenharmony_ci * @key_len: Key length in octets 33e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector 34e5b75505Sopenharmony_ci * @addr: Pointers to the data areas 35e5b75505Sopenharmony_ci * @len: Lengths of the data blocks 36e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 37e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure 38e5b75505Sopenharmony_ci * 39e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication. 40e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 41e5b75505Sopenharmony_ci * (SP) 800-38B. 42e5b75505Sopenharmony_ci */ 43e5b75505Sopenharmony_ciint omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, 44e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 45e5b75505Sopenharmony_ci{ 46e5b75505Sopenharmony_ci void *ctx; 47e5b75505Sopenharmony_ci u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 48e5b75505Sopenharmony_ci const u8 *pos, *end; 49e5b75505Sopenharmony_ci size_t i, e, left, total_len; 50e5b75505Sopenharmony_ci 51e5b75505Sopenharmony_ci if (TEST_FAIL()) 52e5b75505Sopenharmony_ci return -1; 53e5b75505Sopenharmony_ci 54e5b75505Sopenharmony_ci ctx = aes_encrypt_init(key, key_len); 55e5b75505Sopenharmony_ci if (ctx == NULL) 56e5b75505Sopenharmony_ci return -1; 57e5b75505Sopenharmony_ci os_memset(cbc, 0, AES_BLOCK_SIZE); 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_ci total_len = 0; 60e5b75505Sopenharmony_ci for (e = 0; e < num_elem; e++) 61e5b75505Sopenharmony_ci total_len += len[e]; 62e5b75505Sopenharmony_ci left = total_len; 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci e = 0; 65e5b75505Sopenharmony_ci pos = addr[0]; 66e5b75505Sopenharmony_ci end = pos + len[0]; 67e5b75505Sopenharmony_ci 68e5b75505Sopenharmony_ci while (left >= AES_BLOCK_SIZE) { 69e5b75505Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE; i++) { 70e5b75505Sopenharmony_ci cbc[i] ^= *pos++; 71e5b75505Sopenharmony_ci if (pos >= end) { 72e5b75505Sopenharmony_ci /* 73e5b75505Sopenharmony_ci * Stop if there are no more bytes to process 74e5b75505Sopenharmony_ci * since there are no more entries in the array. 75e5b75505Sopenharmony_ci */ 76e5b75505Sopenharmony_ci if (i + 1 == AES_BLOCK_SIZE && 77e5b75505Sopenharmony_ci left == AES_BLOCK_SIZE) 78e5b75505Sopenharmony_ci break; 79e5b75505Sopenharmony_ci e++; 80e5b75505Sopenharmony_ci pos = addr[e]; 81e5b75505Sopenharmony_ci end = pos + len[e]; 82e5b75505Sopenharmony_ci } 83e5b75505Sopenharmony_ci } 84e5b75505Sopenharmony_ci if (left > AES_BLOCK_SIZE) 85e5b75505Sopenharmony_ci aes_encrypt(ctx, cbc, cbc); 86e5b75505Sopenharmony_ci left -= AES_BLOCK_SIZE; 87e5b75505Sopenharmony_ci } 88e5b75505Sopenharmony_ci 89e5b75505Sopenharmony_ci os_memset(pad, 0, AES_BLOCK_SIZE); 90e5b75505Sopenharmony_ci aes_encrypt(ctx, pad, pad); 91e5b75505Sopenharmony_ci gf_mulx(pad); 92e5b75505Sopenharmony_ci 93e5b75505Sopenharmony_ci if (left || total_len == 0) { 94e5b75505Sopenharmony_ci for (i = 0; i < left; i++) { 95e5b75505Sopenharmony_ci cbc[i] ^= *pos++; 96e5b75505Sopenharmony_ci if (pos >= end) { 97e5b75505Sopenharmony_ci /* 98e5b75505Sopenharmony_ci * Stop if there are no more bytes to process 99e5b75505Sopenharmony_ci * since there are no more entries in the array. 100e5b75505Sopenharmony_ci */ 101e5b75505Sopenharmony_ci if (i + 1 == left) 102e5b75505Sopenharmony_ci break; 103e5b75505Sopenharmony_ci e++; 104e5b75505Sopenharmony_ci pos = addr[e]; 105e5b75505Sopenharmony_ci end = pos + len[e]; 106e5b75505Sopenharmony_ci } 107e5b75505Sopenharmony_ci } 108e5b75505Sopenharmony_ci cbc[left] ^= 0x80; 109e5b75505Sopenharmony_ci gf_mulx(pad); 110e5b75505Sopenharmony_ci } 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_ci for (i = 0; i < AES_BLOCK_SIZE; i++) 113e5b75505Sopenharmony_ci pad[i] ^= cbc[i]; 114e5b75505Sopenharmony_ci aes_encrypt(ctx, pad, mac); 115e5b75505Sopenharmony_ci aes_encrypt_deinit(ctx); 116e5b75505Sopenharmony_ci return 0; 117e5b75505Sopenharmony_ci} 118e5b75505Sopenharmony_ci 119e5b75505Sopenharmony_ci 120e5b75505Sopenharmony_ci/** 121e5b75505Sopenharmony_ci * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 122e5b75505Sopenharmony_ci * @key: 128-bit key for the hash operation 123e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector 124e5b75505Sopenharmony_ci * @addr: Pointers to the data areas 125e5b75505Sopenharmony_ci * @len: Lengths of the data blocks 126e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 127e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure 128e5b75505Sopenharmony_ci * 129e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication. 130e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 131e5b75505Sopenharmony_ci * (SP) 800-38B. 132e5b75505Sopenharmony_ci */ 133e5b75505Sopenharmony_ciint omac1_aes_128_vector(const u8 *key, size_t num_elem, 134e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 135e5b75505Sopenharmony_ci{ 136e5b75505Sopenharmony_ci return omac1_aes_vector(key, 16, num_elem, addr, len, mac); 137e5b75505Sopenharmony_ci} 138e5b75505Sopenharmony_ci 139e5b75505Sopenharmony_ci 140e5b75505Sopenharmony_ci/** 141e5b75505Sopenharmony_ci * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) 142e5b75505Sopenharmony_ci * @key: 128-bit key for the hash operation 143e5b75505Sopenharmony_ci * @data: Data buffer for which a MAC is determined 144e5b75505Sopenharmony_ci * @data_len: Length of data buffer in bytes 145e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 146e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure 147e5b75505Sopenharmony_ci * 148e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication. 149e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 150e5b75505Sopenharmony_ci * (SP) 800-38B. 151e5b75505Sopenharmony_ci */ 152e5b75505Sopenharmony_ciint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 153e5b75505Sopenharmony_ci{ 154e5b75505Sopenharmony_ci return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 155e5b75505Sopenharmony_ci} 156e5b75505Sopenharmony_ci 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci/** 159e5b75505Sopenharmony_ci * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC) 160e5b75505Sopenharmony_ci * @key: 256-bit key for the hash operation 161e5b75505Sopenharmony_ci * @data: Data buffer for which a MAC is determined 162e5b75505Sopenharmony_ci * @data_len: Length of data buffer in bytes 163e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 164e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure 165e5b75505Sopenharmony_ci * 166e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication. 167e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 168e5b75505Sopenharmony_ci * (SP) 800-38B. 169e5b75505Sopenharmony_ci */ 170e5b75505Sopenharmony_ciint omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 171e5b75505Sopenharmony_ci{ 172e5b75505Sopenharmony_ci return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); 173e5b75505Sopenharmony_ci} 174