$search
00001 /* 00002 * One-key CBC MAC (OMAC1) hash with AES-128 00003 * 00004 * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License version 2 as 00008 * published by the Free Software Foundation. 00009 * 00010 * Alternatively, this software may be distributed under the terms of BSD 00011 * license. 00012 * 00013 * See README and COPYING for more details. 00014 */ 00015 00016 #include "includes.h" 00017 00018 #include "common.h" 00019 #include "aes.h" 00020 #include "aes_wrap.h" 00021 00022 static void gf_mulx(u8 *pad) 00023 { 00024 int i, carry; 00025 00026 carry = pad[0] & 0x80; 00027 for (i = 0; i < AES_BLOCK_SIZE - 1; i++) 00028 pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); 00029 pad[AES_BLOCK_SIZE - 1] <<= 1; 00030 if (carry) 00031 pad[AES_BLOCK_SIZE - 1] ^= 0x87; 00032 } 00033 00034 00048 int omac1_aes_128_vector(const u8 *key, size_t num_elem, 00049 const u8 *addr[], const size_t *len, u8 *mac) 00050 { 00051 void *ctx; 00052 u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 00053 const u8 *pos, *end; 00054 size_t i, e, left, total_len; 00055 00056 ctx = aes_encrypt_init(key, 16); 00057 if (ctx == NULL) 00058 return -1; 00059 os_memset(cbc, 0, AES_BLOCK_SIZE); 00060 00061 total_len = 0; 00062 for (e = 0; e < num_elem; e++) 00063 total_len += len[e]; 00064 left = total_len; 00065 00066 e = 0; 00067 pos = addr[0]; 00068 end = pos + len[0]; 00069 00070 while (left >= AES_BLOCK_SIZE) { 00071 for (i = 0; i < AES_BLOCK_SIZE; i++) { 00072 cbc[i] ^= *pos++; 00073 if (pos >= end) { 00074 e++; 00075 pos = addr[e]; 00076 end = pos + len[e]; 00077 } 00078 } 00079 if (left > AES_BLOCK_SIZE) 00080 aes_encrypt(ctx, cbc, cbc); 00081 left -= AES_BLOCK_SIZE; 00082 } 00083 00084 os_memset(pad, 0, AES_BLOCK_SIZE); 00085 aes_encrypt(ctx, pad, pad); 00086 gf_mulx(pad); 00087 00088 if (left || total_len == 0) { 00089 for (i = 0; i < left; i++) { 00090 cbc[i] ^= *pos++; 00091 if (pos >= end) { 00092 e++; 00093 pos = addr[e]; 00094 end = pos + len[e]; 00095 } 00096 } 00097 cbc[left] ^= 0x80; 00098 gf_mulx(pad); 00099 } 00100 00101 for (i = 0; i < AES_BLOCK_SIZE; i++) 00102 pad[i] ^= cbc[i]; 00103 aes_encrypt(ctx, pad, mac); 00104 aes_encrypt_deinit(ctx); 00105 return 0; 00106 } 00107 00108 00121 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) 00122 { 00123 return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 00124 }