diff --git a/core/net/llsec/ccm-star.c b/core/lib/ccm-star.c similarity index 67% rename from core/net/llsec/ccm-star.c rename to core/lib/ccm-star.c index faf79ba28..da4b9382a 100644 --- a/core/net/llsec/ccm-star.c +++ b/core/lib/ccm-star.c @@ -34,44 +34,41 @@ * \file * AES_128-based CCM* implementation. * \author - * Konrad Krentz + * Original: Konrad Krentz + * Generified version: Justin King-Lacroix */ -/** - * \addtogroup llsec802154 - * @{ - */ - -#include "net/llsec/ccm-star.h" -#include "net/llsec/llsec802154.h" -#include "net/packetbuf.h" +#include "ccm-star.h" #include "lib/aes-128.h" #include +/* see RFC 3610 */ +#define CCM_STAR_AUTH_FLAGS(Adata, M) ((Adata ? (1u << 6) : 0) | (((M - 2u) >> 1) << 3) | 1u) +#define CCM_STAR_ENCRYPTION_FLAGS 1 +#define CCM_STAR_NONCE_MAX_IV_LENGTH 13 + /*---------------------------------------------------------------------------*/ static void set_nonce(uint8_t *nonce, uint8_t flags, - const uint8_t *extended_source_address, + const uint8_t *iv, uint8_t iv_len, uint8_t counter) { /* 1 byte|| 8 bytes || 4 bytes || 1 byte || 2 bytes */ /* flags || extended_source_address || frame_counter || sec_lvl || counter */ - + + if(iv_len > CCM_STAR_NONCE_MAX_IV_LENGTH) + iv_len = CCM_STAR_NONCE_MAX_IV_LENGTH; + nonce[0] = flags; - memcpy(nonce + 1, extended_source_address, 8); - nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8; - nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff; - nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8; - nonce[12] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff; - nonce[13] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); - nonce[14] = 0; + memcpy(nonce + 1, iv, iv_len); + memset(nonce + iv_len + 1, 0, 16 - (1 + 1 + iv_len)); nonce[15] = counter; } /*---------------------------------------------------------------------------*/ /* XORs the block m[pos] ... m[pos + 15] with K_{counter} */ static void -ctr_step(const uint8_t *extended_source_address, +ctr_step(const uint8_t *iv, uint8_t iv_len, uint8_t pos, uint8_t *m_and_result, uint8_t m_len, @@ -80,7 +77,7 @@ ctr_step(const uint8_t *extended_source_address, uint8_t a[AES_128_BLOCK_SIZE]; uint8_t i; - set_nonce(a, CCM_STAR_ENCRYPTION_FLAGS, extended_source_address, counter); + set_nonce(a, CCM_STAR_ENCRYPTION_FLAGS, iv, iv_len, counter); AES_128.encrypt(a); for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) { @@ -89,43 +86,23 @@ ctr_step(const uint8_t *extended_source_address, } /*---------------------------------------------------------------------------*/ static void -mic(const uint8_t *extended_source_address, +mic(const uint8_t* m, uint8_t m_len, + const uint8_t* iv, uint8_t iv_len, + const uint8_t* a, uint8_t a_len, uint8_t *result, uint8_t mic_len) { uint8_t x[AES_128_BLOCK_SIZE]; uint8_t pos; uint8_t i; - uint8_t a_len; - uint8_t *a; -#if LLSEC802154_USES_ENCRYPTION - uint8_t shall_encrypt; - uint8_t m_len; - uint8_t *m; - shall_encrypt = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2); - if(shall_encrypt) { - a_len = packetbuf_hdrlen(); - m_len = packetbuf_datalen(); - } else { - a_len = packetbuf_totlen(); - m_len = 0; - } set_nonce(x, CCM_STAR_AUTH_FLAGS(a_len, mic_len), - extended_source_address, + iv, iv_len, m_len); -#else /* LLSEC802154_USES_ENCRYPTION */ - a_len = packetbuf_totlen(); - set_nonce(x, - CCM_STAR_AUTH_FLAGS(a_len, mic_len), - extended_source_address, - 0); -#endif /* LLSEC802154_USES_ENCRYPTION */ AES_128.encrypt(x); - a = packetbuf_hdrptr(); - if(a_len) { + if(a_len > 0) { x[1] = x[1] ^ a_len; for(i = 2; (i - 2 < a_len) && (i < AES_128_BLOCK_SIZE); i++) { x[i] ^= a[i - 2]; @@ -143,8 +120,7 @@ mic(const uint8_t *extended_source_address, } } -#if LLSEC802154_USES_ENCRYPTION - if(shall_encrypt) { + if(m_len > 0) { m = a + a_len; pos = 0; while(pos < m_len) { @@ -155,36 +131,33 @@ mic(const uint8_t *extended_source_address, AES_128.encrypt(x); } } -#endif /* LLSEC802154_USES_ENCRYPTION */ - ctr_step(extended_source_address, 0, x, AES_128_BLOCK_SIZE, 0); + ctr_step(iv, iv_len, 0, x, AES_128_BLOCK_SIZE, 0); memcpy(result, x, mic_len); } /*---------------------------------------------------------------------------*/ static void -ctr(const uint8_t *extended_source_address) +ctr(uint8_t* m, uint8_t m_len, const uint8_t* iv, uint8_t iv_len) { - uint8_t m_len; - uint8_t *m; uint8_t pos; uint8_t counter; - m_len = packetbuf_datalen(); - m = (uint8_t *) packetbuf_dataptr(); - pos = 0; counter = 1; while(pos < m_len) { - ctr_step(extended_source_address, pos, m, m_len, counter++); + ctr_step(iv, iv_len, pos, m, m_len, counter++); pos += AES_128_BLOCK_SIZE; } } /*---------------------------------------------------------------------------*/ +static void set_key(const uint8_t* key) { + AES_128.set_key((uint8_t*)key); +} +/*---------------------------------------------------------------------------*/ const struct ccm_star_driver ccm_star_driver = { mic, - ctr + ctr, + set_key }; /*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/core/net/llsec/ccm-star.h b/core/lib/ccm-star.h similarity index 63% rename from core/net/llsec/ccm-star.h rename to core/lib/ccm-star.h index 89a486075..90c9f7349 100644 --- a/core/net/llsec/ccm-star.h +++ b/core/lib/ccm-star.h @@ -34,23 +34,13 @@ * \file * CCM* header file. * \author - * Konrad Krentz + * Original: Konrad Krentz + * Generified version: Justin King-Lacroix */ - -/** - * \addtogroup llsec802154 - * @{ - */ - #ifndef CCM_STAR_H_ #define CCM_STAR_H_ #include "contiki.h" -#include "net/mac/frame802154.h" - -/* see RFC 3610 */ -#define CCM_STAR_AUTH_FLAGS(Adata, M) ((Adata ? (1 << 6) : 0) | (((M - 2) >> 1) << 3) | 1) -#define CCM_STAR_ENCRYPTION_FLAGS 1 #ifdef CCM_STAR_CONF #define CCM_STAR CCM_STAR_CONF @@ -64,22 +54,39 @@ struct ccm_star_driver { /** - * \brief Generates a MIC over the frame in the packetbuf. - * \param result The generated MIC will be put here - * \param mic_len <= 16; set to LLSEC802154_MIC_LENGTH to be compliant + * \brief Generates a MIC over the data supplied. + * \param data The data buffer to read. + * \param data_length The data buffer length. + * \param iv The IV to use. + * \param iv_length The IV's length. + * \param result The generated MIC will be put here + * \param mic_len The size of the MIC to be generated. <= 16. */ - void (* mic)(const uint8_t *extended_source_address, + void (* mic)(const uint8_t* data, uint8_t data_length, + const uint8_t* iv, uint8_t iv_len, + const uint8_t* add, uint8_t add_len, uint8_t *result, uint8_t mic_len); /** * \brief XORs the frame in the packetbuf with the key stream. + * \param data The data buffer to read. + * \param data_length The data buffer length. + * \param iv The IV to use. + * \param iv_length The IV's length. + * \param mic Output buffer to hold the MIC to be generated. + * \param mic_len The size of the MIC to be generated. <= 16. */ - void (* ctr)(const uint8_t *extended_source_address); + void (* ctr)( uint8_t* data, uint8_t data_length, + const uint8_t* iv, uint8_t iv_len); + + /** + * \brief Sets the key in use. Default implementation calls AES_128.set_key() + * \param key The key to use. + */ + void (* set_key)(const uint8_t* key); }; extern const struct ccm_star_driver CCM_STAR; #endif /* CCM_STAR_H_ */ - -/** @} */ diff --git a/core/net/llsec/ccm-star-packetbuf.c b/core/net/llsec/ccm-star-packetbuf.c new file mode 100644 index 000000000..95bfd1528 --- /dev/null +++ b/core/net/llsec/ccm-star-packetbuf.c @@ -0,0 +1,52 @@ +/** + * \file + * CCM* convenience functions for LLSEC use + * \author + * Justin King-Lacroix + */ + +#include "lib/ccm-star.h" +#include "net/packetbuf.h" +#include + +/*---------------------------------------------------------------------------*/ +void ccm_star_mic_packetbuf(const uint8_t *extended_source_address, + uint8_t *result, + uint8_t mic_len) +{ + uint8_t *dataptr = packetbuf_dataptr(); + uint8_t data_len = packetbuf_datalen(); + uint8_t *headerptr = packetbuf_hdrptr(); + uint8_t header_len = packetbuf_hdrlen(); + uint8_t iv[13]; + + memcpy(iv, extended_source_address, 8); + iv[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8; + iv[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff; + iv[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8; + iv[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff; + iv[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); + + if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) { + CCM_STAR.mic(dataptr, data_len, iv, 13, headerptr, header_len, result, mic_len); + } else { + CCM_STAR.mic(dataptr, 0, iv, 13, headerptr, packetbuf_totlen(), result, mic_len); + } +} +/*---------------------------------------------------------------------------*/ +void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address) +{ + uint8_t *dataptr = packetbuf_dataptr(); + uint8_t data_len = packetbuf_datalen(); + uint8_t iv[13]; + + memcpy(iv, extended_source_address, 8); + iv[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8; + iv[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff; + iv[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8; + iv[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff; + iv[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); + + CCM_STAR.ctr(dataptr, data_len, iv, 13); +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/llsec/ccm-star-packetbuf.h b/core/net/llsec/ccm-star-packetbuf.h new file mode 100644 index 000000000..3b6c43472 --- /dev/null +++ b/core/net/llsec/ccm-star-packetbuf.h @@ -0,0 +1,24 @@ +/** + * \file + * CCM* convenience functions for MAC security + * \author + * Justin King-Lacroix + */ + +#ifndef CCM_STAR_PACKETBUF_H_ +#define CCM_STAR_PACKETBUF_H_ + +/** + * \brief Calls CCM_STAR.mic with parameters appropriate for LLSEC. + */ +void ccm_star_mic_packetbuf(const uint8_t *extended_source_address, + uint8_t *result, + uint8_t mic_len); + +/** + * \brief Calls CCM_STAR.ctr with parameters appropriate for LLSEC. + */ +void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address); + +#endif /* CCM_STAR_PACKETBUF_H_ */ + diff --git a/core/net/llsec/noncoresec/noncoresec.c b/core/net/llsec/noncoresec/noncoresec.c index 8935d3375..e62ad2725 100644 --- a/core/net/llsec/noncoresec/noncoresec.c +++ b/core/net/llsec/noncoresec/noncoresec.c @@ -45,13 +45,13 @@ #include "net/llsec/noncoresec/noncoresec.h" #include "net/llsec/anti-replay.h" #include "net/llsec/llsec802154.h" -#include "net/llsec/ccm-star.h" +#include "net/llsec/ccm-star-packetbuf.h" #include "net/mac/frame802154.h" #include "net/netstack.h" #include "net/packetbuf.h" #include "net/nbr-table.h" #include "net/linkaddr.h" -#include "lib/aes-128.h" +#include "lib/ccm-star.h" #include #define WITH_ENCRYPTION (LLSEC802154_SECURITY_LEVEL & (1 << 2)) @@ -110,15 +110,12 @@ send(mac_callback_t sent, void *ptr) static int on_frame_created(void) { - uint8_t *dataptr; - uint8_t data_len; - - dataptr = packetbuf_dataptr(); - data_len = packetbuf_datalen(); - - CCM_STAR.mic(get_extended_address(&linkaddr_node_addr), dataptr + data_len, LLSEC802154_MIC_LENGTH); + uint8_t *dataptr = packetbuf_dataptr(); + uint8_t data_len = packetbuf_datalen(); + + ccm_star_mic_packetbuf(get_extended_address(&linkaddr_node_addr), dataptr + data_len, LLSEC802154_MIC_LENGTH); #if WITH_ENCRYPTION - CCM_STAR.ctr(get_extended_address(&linkaddr_node_addr)); + ccm_star_ctr_packetbuf(get_extended_address(&linkaddr_node_addr)); #endif /* WITH_ENCRYPTION */ packetbuf_set_datalen(data_len + LLSEC802154_MIC_LENGTH); @@ -132,6 +129,8 @@ input(void) uint8_t *received_mic; const linkaddr_t *sender; struct anti_replay_info* info; + uint8_t *dataptr = packetbuf_dataptr(); + uint8_t data_len = packetbuf_datalen(); if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != LLSEC802154_SECURITY_LEVEL) { PRINTF("noncoresec: received frame with wrong security level\n"); @@ -143,14 +142,15 @@ input(void) return; } - packetbuf_set_datalen(packetbuf_datalen() - LLSEC802154_MIC_LENGTH); + data_len -= LLSEC802154_MIC_LENGTH; + packetbuf_set_datalen(data_len); #if WITH_ENCRYPTION - CCM_STAR.ctr(get_extended_address(sender)); + ccm_star_ctr_packetbuf(get_extended_address(sender)); #endif /* WITH_ENCRYPTION */ - CCM_STAR.mic(get_extended_address(sender), generated_mic, LLSEC802154_MIC_LENGTH); + ccm_star_mic_packetbuf(get_extended_address(sender), generated_mic, LLSEC802154_MIC_LENGTH); - received_mic = ((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(); + received_mic = dataptr + data_len; if(memcmp(generated_mic, received_mic, LLSEC802154_MIC_LENGTH) != 0) { PRINTF("noncoresec: received nonauthentic frame %"PRIu32"\n", anti_replay_get_counter()); @@ -203,7 +203,7 @@ get_overhead(void) static void bootstrap(llsec_on_bootstrapped_t on_bootstrapped) { - AES_128.set_key(key); + CCM_STAR.set_key(key); nbr_table_register(anti_replay_table, NULL); on_bootstrapped(); } diff --git a/examples/llsec/ccm-star-tests/encryption/tests.c b/examples/llsec/ccm-star-tests/encryption/tests.c index 99999f819..b9cc58782 100644 --- a/examples/llsec/ccm-star-tests/encryption/tests.c +++ b/examples/llsec/ccm-star-tests/encryption/tests.c @@ -41,9 +41,9 @@ #include "net/packetbuf.h" #include "net/netstack.h" #include "net/llsec/llsec802154.h" -#include "net/llsec/ccm-star.h" +#include "lib/ccm-star.h" +#include "net/llsec/ccm-star-packetbuf.h" #include "net/mac/frame802154.h" -#include "lib/aes-128.h" #include #include @@ -86,8 +86,8 @@ test_sec_lvl_6() packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); packetbuf_hdrreduce(29); - AES_128.set_key(key); - CCM_STAR.mic(extended_source_address, mic, LLSEC802154_MIC_LENGTH); + CCM_STAR.set_key(key); + ccm_star_mic_packetbuf(extended_source_address, mic, LLSEC802154_MIC_LENGTH); if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { printf("Success\n"); @@ -97,7 +97,7 @@ test_sec_lvl_6() printf("Testing encryption ... "); - CCM_STAR.ctr(extended_source_address); + ccm_star_ctr_packetbuf(extended_source_address); if(((uint8_t *) packetbuf_hdrptr())[29] == 0xD8) { printf("Success\n"); } else { @@ -105,7 +105,7 @@ test_sec_lvl_6() } printf("Testing decryption ... "); - CCM_STAR.ctr(extended_source_address); + ccm_star_ctr_packetbuf(extended_source_address); if(((uint8_t *) packetbuf_hdrptr())[29] == 0xCE) { printf("Success\n"); } else { diff --git a/examples/llsec/ccm-star-tests/verification/tests.c b/examples/llsec/ccm-star-tests/verification/tests.c index 86d5952fc..d768ddeb6 100644 --- a/examples/llsec/ccm-star-tests/verification/tests.c +++ b/examples/llsec/ccm-star-tests/verification/tests.c @@ -41,9 +41,10 @@ #include "net/packetbuf.h" #include "net/netstack.h" #include "net/llsec/llsec802154.h" -#include "net/llsec/ccm-star.h" +#include "net/llsec/ccm-star-packetbuf.h" #include "net/mac/frame802154.h" #include "lib/aes-128.h" +#include "lib/ccm-star.h" #include #include @@ -112,8 +113,8 @@ test_sec_lvl_2() packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); packetbuf_hdrreduce(18); - AES_128.set_key(key); - CCM_STAR.mic(extended_source_address, mic, LLSEC802154_MIC_LENGTH); + CCM_STAR.set_key(key); + ccm_star_mic_packetbuf(extended_source_address,mic, LLSEC802154_MIC_LENGTH); if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { printf("Success\n");