BeRTOS
|
00001 00037 #include "omac.h" 00038 #include <cfg/macros.h> 00039 #include <sec/util.h> 00040 00041 static void omac_set_key(Mac *ctx_, const void* key, size_t len) 00042 { 00043 OmacContext *ctx = (OmacContext *)ctx_; 00044 cipher_set_vkey(ctx->c, key, len); 00045 } 00046 00047 static void omac_begin(Mac *ctx_) 00048 { 00049 OmacContext *ctx = (OmacContext *)ctx_; 00050 00051 ctx->acc = 0; 00052 00053 memset(ctx->Y, 0, cipher_block_len(ctx->c)); 00054 cipher_cbc_begin(ctx->c, ctx->Y); 00055 } 00056 00057 static void omac_update(Mac *ctx_, const void *data_, size_t len) 00058 { 00059 OmacContext *ctx = (OmacContext *)ctx_; 00060 size_t blen = cipher_block_len(ctx->c); 00061 const uint8_t *data = (const uint8_t *)data_; 00062 00063 while (len) 00064 { 00065 ASSERT(ctx->acc <= blen); 00066 if (ctx->acc == blen) 00067 { 00068 cipher_cbc_encrypt(ctx->c, ctx->accum); 00069 ctx->acc = 0; 00070 } 00071 00072 size_t L = MIN(len, blen - ctx->acc); 00073 memcpy(ctx->accum + ctx->acc, data, L); 00074 data += L; 00075 len -= L; 00076 ctx->acc += L; 00077 } 00078 } 00079 00080 static void omac_shift_left(uint8_t *L, size_t len) 00081 { 00082 int firstbit = L[0] >> 7; 00083 size_t i; 00084 00085 for (i=0; i<len-1; ++i) 00086 L[i] = (L[i] << 1) | (L[i+1] >> 7); 00087 L[i] <<= 1; 00088 00089 if (firstbit) 00090 { 00091 if (len == 16) 00092 L[i] ^= 0x87; 00093 else if (len == 8) 00094 L[i] ^= 0x1B; 00095 else 00096 ASSERT(0); 00097 } 00098 } 00099 00100 static void omac_shift_right(uint8_t *L, size_t len) 00101 { 00102 int firstbit = L[len-1] & 1; 00103 size_t i; 00104 00105 for (i=len-1; i>0; --i) 00106 L[i] = (L[i] >> 1) | (L[i-1] << 7); 00107 L[i] >>= 1; 00108 00109 if (firstbit) 00110 { 00111 L[i] |= 0x80; 00112 if (len == 16) 00113 L[len-1] ^= 0x43; 00114 else if (len == 8) 00115 L[len-1] ^= 0x0D; 00116 else 00117 ASSERT(0); 00118 } 00119 } 00120 00121 static uint8_t *omac1_final(Mac *ctx_) 00122 { 00123 OmacContext *ctx = (OmacContext *)ctx_; 00124 size_t blen = cipher_block_len(ctx->c); 00125 00126 uint8_t L[blen]; 00127 memset(L, 0, blen); 00128 cipher_ecb_encrypt(ctx->c, L); 00129 00130 omac_shift_left(L, blen); 00131 if (ctx->acc < blen) 00132 { 00133 ctx->accum[ctx->acc++] = 0x80; 00134 memset(ctx->accum + ctx->acc, 0, blen - ctx->acc); 00135 omac_shift_left(L, blen); 00136 } 00137 00138 xor_block(ctx->accum, ctx->accum, L, blen); 00139 cipher_cbc_encrypt(ctx->c, ctx->accum); 00140 return ctx->accum; 00141 } 00142 00143 static uint8_t *omac2_final(Mac *ctx_) 00144 { 00145 OmacContext *ctx = (OmacContext *)ctx_; 00146 size_t blen = cipher_block_len(ctx->c); 00147 00148 uint8_t L[blen]; 00149 memset(L, 0, blen); 00150 cipher_ecb_encrypt(ctx->c, L); 00151 00152 if (ctx->acc < blen) 00153 { 00154 ctx->accum[ctx->acc++] = 0x80; 00155 memset(ctx->accum + ctx->acc, 0, blen - ctx->acc); 00156 omac_shift_right(L, blen); 00157 } 00158 else 00159 omac_shift_left(L, blen); 00160 00161 xor_block(ctx->accum, ctx->accum, L, blen); 00162 cipher_cbc_encrypt(ctx->c, ctx->accum); 00163 return ctx->accum; 00164 } 00165 00166 00167 /****************************************************************************/ 00168 00169 static void omac_init(OmacContext *ctx, BlockCipher *c) 00170 { 00171 ctx->mac.set_key = omac_set_key; 00172 ctx->mac.begin = omac_begin; 00173 ctx->mac.update = omac_update; 00174 ctx->mac.key_len = cipher_key_len(c); 00175 ctx->mac.digest_len = cipher_block_len(c); 00176 ctx->c = c; 00177 00178 ASSERT(cipher_block_len(c) == 8 || cipher_block_len(c) == 16); 00179 ASSERT(sizeof(ctx->Y) >= cipher_block_len(c)); 00180 ASSERT(sizeof(ctx->accum) >= cipher_block_len(c)); 00181 } 00182 00183 void omac1_init(OmacContext *ctx, BlockCipher *c) 00184 { 00185 omac_init(ctx, c); 00186 ctx->mac.final = omac1_final; 00187 } 00188 00189 void omac2_init(OmacContext *ctx, BlockCipher *c) 00190 { 00191 omac_init(ctx, c); 00192 ctx->mac.final = omac2_final; 00193 }