00001
00011 #include "rwnx_config.h"
00012
00013 #if NX_HSU
00014 #include "reg_hsu.h"
00015 #include "me_mic.h"
00016 #include "trace.h"
00017
00026 enum hsu_modes {
00027 HSU_MODE_TKIP_MIC = 0,
00028 HSU_MODE_AES_128_CMAC = 1,
00029 HSU_MODE_IP_CHK = 2,
00030 HSU_MODE_SHA_1 = 3,
00031 HSU_MODE_SHA_256 = 4,
00032 HSU_MODE_SHA_224 = 5,
00033 HSU_MODE_HMAC_SHA1 = 6,
00034 HSU_MODE_HMAC_SHA256 = 7,
00035 HSU_MODE_HMAC_SHA224 = 8,
00036 HSU_MODE_SHA_512 = 9,
00037 HSU_MODE_SHA_384 = 10,
00038 HSU_MODE_HMAC_SHA512 = 11,
00039 HSU_MODE_HMAC_SHA384 = 12,
00040 };
00041
00043 static uint32_t hsu_status = 0;
00044
00046 #define HSU_SUPPORT(m) (hsu_status & HSU_##m##_BIT)
00047
00048 #if NX_FULLY_HOSTED
00050 static bool hsu_locked;
00051
00055 #define HSU_LOCK() \
00056 { \
00057 bool res = false; \
00058 GLOBAL_INT_DISABLE(); \
00059 if (!hsu_locked) \
00060 { \
00061 res = true; \
00062 hsu_locked = true; \
00063 } \
00064 GLOBAL_INT_RESTORE(); \
00065 if (!res) \
00066 return false; \
00067 }
00068
00070 #define HSU_UNLOCK() { hsu_locked = false; }
00071 #else
00073 #define HSU_LOCK()
00075 #define HSU_UNLOCK()
00076 #endif
00077
00079 #define HSU_MODE(m) (hsu_mode(HSU_MODE_##m))
00080
00087 __INLINE uint32_t hsu_mode(int mode)
00088 {
00089 if ((hsu_status & HSU_VERSION_MASK) >= 7)
00090 return mode << HSU_MODE_LSB;
00091 else
00092 return mode << 1;
00093 }
00094
00095 void hsu_init(void)
00096 {
00097 uint32_t hsu_version;
00098 hsu_status = hsu_revision_get();
00099
00100 if (hsu_status >= 0xdead0000)
00101 {
00102 hsu_status = 0;
00103 #if NX_HSU == 2
00104 ASSERT_ERR(0);
00105 #endif
00106 return;
00107 }
00108
00109 hsu_version = hsu_status & HSU_VERSION_MASK;
00110
00111 if (hsu_version < 5)
00112 {
00113 hsu_status |= ( HSU_TKIP_MIC_BIT |
00114 HSU_AES_128_CMAC_BIT );
00115 if (hsu_version > 1)
00116 hsu_status |= HSU_IP_CHK_BIT;
00117 if (hsu_version > 2)
00118 hsu_status |= HSU_SHA_1_BIT;
00119 }
00120
00121 HSU_UNLOCK();
00122 }
00123
00124
00125
00126 uint64_t hsu_aes_cmac(uint32_t *key, int nb_elem, uint32_t addr[], int len[])
00127 {
00128 uint64_t mic;
00129 int i;
00130 uint32_t ctrl = (HSU_MODE(AES_128_CMAC) |
00131 HSU_FIRST_BUFFER_BIT |
00132 HSU_START_BIT);
00133
00134 if (!HSU_SUPPORT(AES_128_CMAC) || (nb_elem == 0))
00135 return 0;
00136
00137 for (i = 0; i < nb_elem; i++)
00138 {
00139 if (addr[i] == 0 || TST_SHRAM_PTR(HW2CPU(addr[i])))
00140 {
00141 ASSERT_WARN(0);
00142 return 0;
00143 }
00144 }
00145
00146 HSU_LOCK();
00147 for (i = 0; i < 4; i++)
00148 {
00149 hsu_key_tab_set(i, key[i]);
00150 }
00151
00152 for (i = 0; i < nb_elem - 1; i++, addr++, len++)
00153 {
00154 hsu_source_addr_set(*addr);
00155 hsu_length_set(*len);
00156 hsu_status_clear_set(1);
00157 hsu_control_set(ctrl);
00158 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00159 ctrl &= ~HSU_FIRST_BUFFER_BIT;
00160 }
00161
00162 ctrl |= HSU_LAST_BUFFER_BIT;
00163 hsu_source_addr_set(*addr);
00164 hsu_length_set(*len);
00165 hsu_status_clear_set(1);
00166 hsu_control_set(ctrl);
00167 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00168
00169 mic = hsu_mic_tab_get(1);
00170 mic <<= 32;
00171 mic |= hsu_mic_tab_get(0);
00172 HSU_UNLOCK();
00173
00174 return mic;
00175 }
00176
00177
00178
00195 static bool hsu_michael(uint32_t ctrl, struct mic_calc *mic_calc,
00196 uint32_t data, uint32_t data_len)
00197 {
00198 if (!HSU_SUPPORT(TKIP_MIC))
00199 {
00200 return false;
00201 }
00202
00203 if (data_len && TST_SHRAM_PTR(HW2CPU(data)))
00204 {
00205 ASSERT_WARN(0);
00206 return false;
00207 }
00208
00209 HSU_LOCK();
00210 hsu_mic_tab_set(0, mic_calc->mic_key_least);
00211 hsu_mic_tab_set(1, mic_calc->mic_key_most);
00212 hsu_remaining_set(mic_calc->last_m_i);
00213
00214 hsu_source_addr_set(data);
00215 hsu_length_set(data_len);
00216 hsu_status_clear_set(1);
00217 hsu_control_set(ctrl);
00218 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00219
00220 mic_calc->mic_key_least = hsu_mic_tab_get(0);
00221 mic_calc->mic_key_most = hsu_mic_tab_get(1);
00222 mic_calc->last_m_i = hsu_remaining_get();
00223 HSU_UNLOCK();
00224
00225 return true;
00226 }
00227
00228
00229 bool hsu_michael_init(struct mic_calc *mic_calc, uint32_t *mic_key,
00230 uint32_t *aad)
00231 {
00232 uint32_t ctrl = (HSU_MODE(TKIP_MIC) |
00233 HSU_START_BIT);
00234
00235 if (!HSU_SUPPORT(TKIP_MIC))
00236 {
00237 return false;
00238 }
00239
00240
00241 mic_calc->mic_key_least = mic_key[0];
00242 mic_calc->mic_key_most = mic_key[1];
00243 mic_calc->last_m_i = 0;
00244 mic_calc->last_m_i_len = 0;
00245
00246 return hsu_michael(ctrl, mic_calc, CPU2HW(aad), 16);
00247 }
00248
00249 bool hsu_michael_calc(struct mic_calc *mic_calc, uint32_t data,
00250 uint32_t data_len)
00251 {
00252 uint32_t ctrl = (HSU_MODE(TKIP_MIC) |
00253 HSU_START_BIT);
00254
00255 return hsu_michael(ctrl, mic_calc, data, data_len);
00256 }
00257
00258 bool hsu_michael_end(struct mic_calc *mic_calc)
00259 {
00260 uint32_t ctrl = (HSU_MODE(TKIP_MIC) |
00261 HSU_LAST_BUFFER_BIT |
00262 HSU_START_BIT);
00263
00264 return hsu_michael(ctrl, mic_calc, 0, 0);
00265 }
00266
00267
00268
00269 bool hsu_ip_checksum(uint32_t addr, uint16_t len, uint16_t *checksum)
00270 {
00271 uint32_t ctrl = (HSU_MODE(IP_CHK) |
00272 HSU_LAST_BUFFER_BIT |
00273 HSU_START_BIT);
00274
00275 if (!HSU_SUPPORT(IP_CHK) || TST_SHRAM_PTR(HW2CPU(addr)))
00276 {
00277 return false;
00278 }
00279
00280
00281 HSU_LOCK();
00282 hsu_source_addr_set(addr);
00283 hsu_length_set(len);
00284 hsu_status_clear_set(HSU_DONE_SET_BIT);
00285 hsu_control_set(ctrl);
00286 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00287
00288 *checksum = hsu_mic_tab_get(0) & 0xFFFF;
00289 HSU_UNLOCK();
00290
00291 return true;
00292 }
00293
00294
00295
00297 #define HSU_SHA_MAX_LEN 512
00298
00300 static uint8_t hsu_sha_buf[HSU_SHA_MAX_LEN] __SHAREDRAM;
00301
00322 static bool hsu_sha_x(uint32_t hsu_sha_mode, int nb_elem, const uint8_t *addr[],
00323 const size_t *len, int sha_size, uint32_t *sha)
00324 {
00325 int i, length = 0;
00326 uint32_t ctrl = (hsu_sha_mode |
00327 HSU_FIRST_BUFFER_BIT |
00328 HSU_LAST_BUFFER_BIT |
00329 HSU_START_BIT);
00330
00331 for (i = 0 ; i < nb_elem; i++)
00332 {
00333 length += len[i];
00334 }
00335
00336 if (length > HSU_SHA_MAX_LEN)
00337 {
00338 TRACE_LMAC(ERR, "Temporary buffer for SHA computation not big enough (need %d)", length);
00339 return false;
00340 }
00341
00342 HSU_LOCK();
00343
00344 length = 0;
00345 for (i = 0 ; i < nb_elem; i++)
00346 {
00347 memcpy(&hsu_sha_buf[length], addr[i], len[i]);
00348 length += len[i];
00349 }
00350
00351 hsu_source_addr_set(CPU2HW(hsu_sha_buf));
00352 hsu_length_set(length);
00353 hsu_status_clear_set(HSU_DONE_SET_BIT);
00354 hsu_control_set(ctrl);
00355 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00356
00357 for (i = 0; i < sha_size; i ++)
00358 {
00359 *sha++ = hsu_sha_tab_get(i);
00360 }
00361 HSU_UNLOCK();
00362
00363 return true;
00364 }
00365
00366 bool hsu_sha1(int nb_elem, const uint8_t *addr[], const size_t *len, uint32_t *sha)
00367 {
00368 if (!HSU_SUPPORT(SHA_1))
00369 return false;
00370 return hsu_sha_x(HSU_MODE(SHA_1), nb_elem, addr, len, 160/32, sha);
00371 }
00372
00373 bool hsu_sha224(int nb_elem, const uint8_t *addr[], const size_t *len, uint32_t *sha)
00374 {
00375 if (!HSU_SUPPORT(SHA_256_224))
00376 return false;
00377 return hsu_sha_x(HSU_MODE(SHA_224), nb_elem, addr, len, 224/32, sha);
00378 }
00379
00380 bool hsu_sha256(int nb_elem, const uint8_t *addr[], const size_t *len, uint32_t *sha)
00381 {
00382 if (!HSU_SUPPORT(SHA_256_224))
00383 return false;
00384 return hsu_sha_x(HSU_MODE(SHA_256), nb_elem, addr, len, 256/32, sha);
00385 }
00386
00387 bool hsu_sha384(int nb_elem, const uint8_t *addr[], const size_t *len, uint32_t *sha)
00388 {
00389 if (!HSU_SUPPORT(SHA_512_384))
00390 return false;
00391 return hsu_sha_x(HSU_MODE(SHA_384), nb_elem, addr, len, 384/32, sha);
00392 }
00393
00394 bool hsu_sha512(int nb_elem, const uint8_t *addr[], const size_t *len, uint32_t *sha)
00395 {
00396 if (!HSU_SUPPORT(SHA_512_384))
00397 return false;
00398 return hsu_sha_x(HSU_MODE(SHA_512), nb_elem, addr, len, 512/32, sha);
00399 }
00400
00401
00424 bool hsu_hmac_sha_x(uint32_t hsu_hmac_mode, const uint8_t key[],
00425 const size_t key_len, int nb_elem, const uint8_t *addr[],
00426 const size_t *len, int mac_size, uint32_t *mac)
00427 {
00428 int i, length = 0;
00429 uint32_t ctrl = (hsu_hmac_mode |
00430 HSU_FIRST_BUFFER_BIT |
00431 HSU_START_BIT);
00432
00433 for (i = 0 ; i < nb_elem; i++)
00434 {
00435 length += len[i];
00436 }
00437 if ((length > HSU_SHA_MAX_LEN) || (key_len > HSU_SHA_MAX_LEN))
00438 {
00439 TRACE_LMAC(ERR, "Temporary buffer for HMAC computation not big enough (need %d)", length);
00440 return false;
00441 }
00442
00443 HSU_LOCK();
00444
00445 memcpy(&hsu_sha_buf[0], key, key_len);
00446 hsu_source_addr_set(CPU2HW(hsu_sha_buf));
00447 hsu_length_set(key_len);
00448 hsu_status_clear_set(HSU_DONE_SET_BIT);
00449 hsu_control_set(ctrl);
00450 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00451
00452
00453 length = 0;
00454 for (i = 0 ; i < nb_elem; i++)
00455 {
00456 memcpy(&hsu_sha_buf[length], addr[i], len[i]);
00457 length += len[i];
00458 }
00459
00460 ctrl &= ~(HSU_FIRST_BUFFER_BIT);
00461 ctrl |= HSU_LAST_BUFFER_BIT;
00462 hsu_source_addr_set(CPU2HW(hsu_sha_buf));
00463 hsu_length_set(length);
00464 hsu_status_clear_set(HSU_DONE_SET_BIT);
00465 hsu_control_set(ctrl);
00466 while (!(hsu_status_set_get() & HSU_DONE_SET_BIT)) {}
00467
00468 for (i = 0; i < mac_size; i ++)
00469 {
00470 *mac++ = hsu_sha_tab_get(i);
00471 }
00472 HSU_UNLOCK();
00473
00474 return true;
00475 }
00476
00477 bool hsu_hmac_sha1(const uint8_t key[], const size_t key_len, int nb_elem,
00478 const uint8_t *addr[], const size_t *len, uint32_t *mac)
00479 {
00480 if (!HSU_SUPPORT(HMAC_SHA1))
00481 return false;
00482 return hsu_hmac_sha_x(HSU_MODE(HMAC_SHA1), key, key_len, nb_elem,
00483 addr, len, 160/32, mac);
00484 }
00485
00486 bool hsu_hmac_sha224(const uint8_t key[], const size_t key_len, int nb_elem,
00487 const uint8_t *addr[], const size_t *len, uint32_t *mac)
00488 {
00489 if (!HSU_SUPPORT(HMAC_SHA256_SHA224))
00490 return false;
00491 return hsu_hmac_sha_x(HSU_MODE(HMAC_SHA224), key, key_len, nb_elem,
00492 addr, len, 224/32, mac);
00493 }
00494
00495 bool hsu_hmac_sha256(const uint8_t key[], const size_t key_len, int nb_elem,
00496 const uint8_t *addr[], const size_t *len, uint32_t *mac)
00497 {
00498 if (!HSU_SUPPORT(HMAC_SHA256_SHA224))
00499 return false;
00500 return hsu_hmac_sha_x(HSU_MODE(HMAC_SHA256), key, key_len, nb_elem,
00501 addr, len, 256/32, mac);
00502 }
00503
00504 bool hsu_hmac_sha384(const uint8_t key[], const size_t key_len, int nb_elem,
00505 const uint8_t *addr[], const size_t *len, uint32_t *mac)
00506 {
00507 if (!HSU_SUPPORT(HMAC_SHA512_SHA384))
00508 return false;
00509 return hsu_hmac_sha_x(HSU_MODE(HMAC_SHA384), key, key_len, nb_elem,
00510 addr, len, 384/32, mac);
00511 }
00512
00513 bool hsu_hmac_sha512(const uint8_t key[], const size_t key_len, int nb_elem,
00514 const uint8_t *addr[], const size_t *len, uint32_t *mac)
00515 {
00516 if (!HSU_SUPPORT(HMAC_SHA512_SHA384))
00517 return false;
00518 return hsu_hmac_sha_x(HSU_MODE(HMAC_SHA512), key, key_len, nb_elem,
00519 addr, len, 512/32, mac);
00520 }
00521
00525 #endif