- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/umac/src/hsu/hsu.c

Go to the documentation of this file.

    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     // First version doesn't include supported feature in revision register
    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 /********************* AES-CMAC **********************************************/
    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 /********************* TKIP-MIC **********************************************/
    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     // Initialize MIC value
    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 /********************* IP CHECKSUM *******************************************/
    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     /* Configure HSU for computation */
    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 /********************* SHA-X *************************************************/
    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     // Concatenate input buffers in a single buffer in SHARED RAM
    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 /********************* HMAC-SHA-X ********************************************/
    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     // Concatenate input buffers in a single buffer in SHARED RAM
    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 /* NX_HSU */