00001
00017
00018
00019
00020
00021
00022 #include "me_mic.h"
00023 #include "co_utils.h"
00024 #include "dbg_assert.h"
00025 #if NX_HSU
00026 #include "hsu.h"
00027 #endif
00028
00029
00030
00031
00032
00033
00039 #define MIC_END_SIGNATURE (0x0000005A)
00040
00044 #define MIC_TID_MASK (0x00000007)
00045
00046
00047 #if NX_HSU < 2
00048
00049
00050
00051
00052
00053
00065 #define ROR32(L,Q) ( ( (uint32_t)(L) >> (Q) ) | ( (uint32_t)(L) << (32-(Q)) ) )
00066
00078 #define ROL32(L,Q) ( ( (uint32_t)(L) << (Q) ) | ( (uint32_t)(L) >> (32-(Q)) ) )
00079
00090 #define XSWAP32(L) ( ( ( L & 0xFF00FF00 ) >> 8 ) | \
00091 ( ( L & 0x00FF00FF ) << 8 ) )
00092
00111 #define LEN_IN_BITS(X) ( (X) << 3 )
00112
00123 #define SHIFTR(X, S) (((S) == 32)? 0 : ((X) >> (S)) )
00124
00125
00126
00127
00128
00129
00159 static void michael_block(struct mic_calc *mic_calc_ptr, uint32_t block)
00160 {
00161 uint32_t l = mic_calc_ptr->mic_key_least;
00162 uint32_t r = mic_calc_ptr->mic_key_most;
00163
00164 l ^= block;
00165 r ^= ROL32(l, 17);
00166 l += r;
00167 r ^= XSWAP32(l);
00168 l += r;
00169 r ^= ROL32(l, 3);
00170 l += r;
00171 r ^= ROR32(l, 2);
00172 l += r;
00173
00174 mic_calc_ptr->mic_key_most = r;
00175 mic_calc_ptr->mic_key_least = l;
00176 }
00177
00188 static void michael_init(struct mic_calc *mic_calc_ptr, uint32_t *mic_key_ptr,
00189 uint32_t *aad)
00190 {
00191
00192 mic_calc_ptr->mic_key_least = mic_key_ptr[0];
00193 mic_calc_ptr->mic_key_most = mic_key_ptr[1];
00194 mic_calc_ptr->last_m_i = 0;
00195 mic_calc_ptr->last_m_i_len = 0;
00196
00197
00198 michael_block(mic_calc_ptr, aad[0]);
00199 michael_block(mic_calc_ptr, aad[1]);
00200 michael_block(mic_calc_ptr, aad[2]);
00201 michael_block(mic_calc_ptr, aad[3]);
00202 }
00203
00215 static void michael_calc(struct mic_calc *mic_calc_ptr, uint32_t start_ptr,
00216 uint32_t data_len)
00217 {
00218
00219 uint32_t m_i;
00220
00221 uint32_t rem_len = data_len;
00222
00223 uint32_t nb_blocks;
00224
00225 uint32_t *u32_ptr = HW2CPU(start_ptr & ~0x03);
00226 uint32_t val = *u32_ptr++;
00227 uint8_t cut = start_ptr & 0x03;
00228 uint8_t valid = 4 - cut;
00229 uint32_t last_m_i_len = mic_calc_ptr->last_m_i_len;
00230 uint32_t last_m_i = mic_calc_ptr->last_m_i;
00231
00232 val >>= LEN_IN_BITS(cut);
00233 if (data_len < valid)
00234 {
00235 val &= 0xFFFFFFFF >> LEN_IN_BITS(4 - data_len);
00236 valid = data_len;
00237 rem_len = 0;
00238 }
00239 else
00240 {
00241 rem_len -= valid;
00242 }
00243
00244 if ((last_m_i_len + valid) < 4)
00245 {
00246 last_m_i |= val << LEN_IN_BITS(last_m_i_len);
00247 last_m_i_len += valid;
00248 }
00249 else
00250 {
00251 m_i = last_m_i | (val << LEN_IN_BITS(last_m_i_len));
00252
00253 last_m_i = SHIFTR(val, LEN_IN_BITS(4 - last_m_i_len));
00254 last_m_i_len += valid - 4;
00255
00256
00257 michael_block(mic_calc_ptr, m_i);
00258 }
00259
00260
00261 nb_blocks = (rem_len >> 2);
00262
00263 for (uint32_t block_cnt = 0; block_cnt < nb_blocks; block_cnt++)
00264 {
00265
00266 val = *u32_ptr++;
00267
00268
00269 m_i = last_m_i | (val << LEN_IN_BITS(last_m_i_len));
00270
00271
00272 last_m_i = SHIFTR(val, LEN_IN_BITS(4 - last_m_i_len));
00273
00274
00275 michael_block(mic_calc_ptr, m_i);
00276 }
00277
00278
00279 if (rem_len > (nb_blocks << 2))
00280 {
00281 uint32_t add_bytes = rem_len - (nb_blocks << 2);
00282
00283 val = (*u32_ptr) & (SHIFTR(0xFFFFFFFF, LEN_IN_BITS(4 - add_bytes)));
00284 if ((last_m_i_len + add_bytes) > 3)
00285 {
00286
00287 m_i = last_m_i | (val << LEN_IN_BITS(last_m_i_len));
00288
00289
00290 last_m_i = SHIFTR(val, LEN_IN_BITS(4 - last_m_i_len));
00291 last_m_i_len += add_bytes - 4;
00292
00293
00294 michael_block(mic_calc_ptr, m_i);
00295 }
00296 else
00297 {
00298 last_m_i |= val << LEN_IN_BITS(last_m_i_len);
00299 last_m_i_len += add_bytes;
00300 }
00301 }
00302
00303 mic_calc_ptr->last_m_i = last_m_i;
00304 mic_calc_ptr->last_m_i_len = last_m_i_len;
00305 }
00306
00316 static void michael_end(struct mic_calc *mic_calc_ptr)
00317 {
00318
00319 uint32_t m_n_2 = mic_calc_ptr->last_m_i;
00320
00321 ASSERT_ERR(mic_calc_ptr->last_m_i_len < 4);
00322
00323 m_n_2 |= (MIC_END_SIGNATURE << LEN_IN_BITS(mic_calc_ptr->last_m_i_len));
00324
00325
00326 michael_block(mic_calc_ptr, m_n_2);
00327
00328 michael_block(mic_calc_ptr, 0);
00329 }
00330 #endif
00331
00332
00333
00334
00335
00336
00337 #if NX_HSU
00340 uint32_t mic_aad[4] __SHAREDRAM;
00341 #endif
00342
00343 void me_mic_init(struct mic_calc *mic_calc_ptr, uint32_t *mic_key_ptr,
00344 struct mac_addr *da, struct mac_addr *sa, uint8_t tid)
00345 {
00346 #if !NX_HSU
00347 uint32_t mic_aad[4];
00348 #endif
00349
00350
00351 mic_aad[0] = (uint32_t)da->array[0] | (((uint32_t)da->array[1]) << 16);
00352 mic_aad[1] = (uint32_t)da->array[2] | (((uint32_t)sa->array[0]) << 16);
00353 mic_aad[2] = (uint32_t)sa->array[1] | (((uint32_t)sa->array[2]) << 16);
00354 if (tid == 0xFF)
00355 mic_aad[3] = 0;
00356 else
00357 mic_aad[3] = (uint32_t)tid & MIC_TID_MASK;
00358
00359 #if NX_HSU
00360 if (hsu_michael_init(mic_calc_ptr, mic_key_ptr, mic_aad))
00361 return;
00362 #endif
00363
00364 #if NX_HSU < 2
00365 michael_init(mic_calc_ptr, mic_key_ptr, mic_aad);
00366 #endif
00367 }
00368
00369 void me_mic_calc(struct mic_calc *mic_calc_ptr, uint32_t start_ptr,
00370 uint32_t data_len)
00371 {
00372 #if NX_HSU
00373 if (hsu_michael_calc(mic_calc_ptr, start_ptr, data_len))
00374 return;
00375 #endif
00376
00377 #if NX_HSU < 2
00378 michael_calc(mic_calc_ptr, start_ptr, data_len);
00379 #endif
00380 }
00381
00382 void me_mic_end(struct mic_calc *mic_calc_ptr)
00383 {
00384 #if NX_HSU
00385 if (hsu_michael_end(mic_calc_ptr))
00386 return;
00387 #endif
00388
00389 #if NX_HSU < 2
00390 michael_end(mic_calc_ptr);
00391 #endif
00392 }
00393