18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * One-key CBC MAC (OMAC1) hash with AES-128 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/** 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: 128-bit key for the hash operation 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_elem: Number of elements in the data vector 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Pointers to the data areas 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Lengths of the data blocks 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (SP) 800-38B. 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint omac1_aes_128_vector(const u8 *key, size_t num_elem, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[], const size_t *len, u8 *mac) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, e, left, total_len; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx = aes_encrypt_init(key, 16); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cbc, 0, AES_BLOCK_SIZE); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt total_len = 0; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (e = 0; e < num_elem; e++) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt total_len += len[e]; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = total_len; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e = 0; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[0]; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[0]; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left >= AES_BLOCK_SIZE) { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < AES_BLOCK_SIZE; i++) { 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[i] ^= *pos++; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos >= end) { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e++; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[e]; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[e]; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > AES_BLOCK_SIZE) 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, cbc, cbc); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= AES_BLOCK_SIZE; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pad, 0, AES_BLOCK_SIZE); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, pad, pad); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gf_mulx(pad); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left || total_len == 0) { 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < left; i++) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[i] ^= *pos++; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos >= end) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt e++; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = addr[e]; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len[e]; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cbc[left] ^= 0x80; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gf_mulx(pad); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < AES_BLOCK_SIZE; i++) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad[i] ^= cbc[i]; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt(ctx, pad, mac); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_encrypt_deinit(ctx); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: 128-bit key for the hash operation 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data buffer for which a MAC is determined 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data_len: Length of data buffer in bytes 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is a mode for using block cipher (AES in this case) for authentication. 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (SP) 800-38B. 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 119