diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index ee897ba50..67500f59b 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -35,17 +35,21 @@ typedef enum { CIPHERING_ALGORITHM_ID_EEA0 = 0, CIPHERING_ALGORITHM_ID_128_EEA1, CIPHERING_ALGORITHM_ID_128_EEA2, + CIPHERING_ALGORITHM_ID_128_EEA3, CIPHERING_ALGORITHM_ID_N_ITEMS, } CIPHERING_ALGORITHM_ID_ENUM; -static const char ciphering_algorithm_id_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = {"EEA0", "128-EEA1", "128-EEA2"}; +static const char ciphering_algorithm_id_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = { + "EEA0", "128-EEA1", "128-EEA2", "128-EEA3"}; typedef enum { INTEGRITY_ALGORITHM_ID_EIA0 = 0, INTEGRITY_ALGORITHM_ID_128_EIA1, INTEGRITY_ALGORITHM_ID_128_EIA2, + INTEGRITY_ALGORITHM_ID_128_EIA3, INTEGRITY_ALGORITHM_ID_N_ITEMS, } INTEGRITY_ALGORITHM_ID_ENUM; -static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"EIA0", "128-EIA1", "128-EIA2"}; +static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = { + "EIA0", "128-EIA1", "128-EIA2", "128-EIA3"}; typedef enum { SECURITY_DIRECTION_UPLINK = 0, diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 50eb0281c..8f5559aff 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -159,7 +159,7 @@ uint8_t security_128_eia2(uint8_t* key, uint32_t count, uint32_t bearer, uint8_t uint8_t security_128_eia3(uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac) { - return liblte_security_128_eia3(key, count, bearer, direction, msg, msg_len, mac); + return liblte_security_128_eia3(key, count, bearer, direction, msg, msg_len * 8, mac); } uint8_t security_md5(const uint8_t *input, size_t len, uint8_t *output) diff --git a/lib/src/upper/pdcp_entity_base.cc b/lib/src/upper/pdcp_entity_base.cc index da023feb5..7e9c2993b 100644 --- a/lib/src/upper/pdcp_entity_base.cc +++ b/lib/src/upper/pdcp_entity_base.cc @@ -79,6 +79,9 @@ void pdcp_entity_base::integrity_generate(uint8_t* msg, uint32_t msg_len, uint32 case INTEGRITY_ALGORITHM_ID_128_EIA2: security_128_eia2(&k_int[16], count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, mac); break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_int[16], count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, mac); + break; default: break; } @@ -113,6 +116,9 @@ bool pdcp_entity_base::integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t case INTEGRITY_ALGORITHM_ID_128_EIA2: security_128_eia2(&k_int[16], count, cfg.bearer_id - 1, cfg.rx_direction, msg, msg_len, mac_exp); break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_int[16], count, cfg.bearer_id - 1, cfg.rx_direction, msg, msg_len, mac_exp); + break; default: break; } @@ -169,6 +175,10 @@ void pdcp_entity_base::cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t c security_128_eea2(&(k_enc[16]), count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, ct_tmp); memcpy(ct, ct_tmp, msg_len); break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&(k_enc[16]), count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, ct_tmp); + memcpy(ct, ct_tmp, msg_len); + break; default: break; } @@ -204,6 +214,10 @@ void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t cou security_128_eea2(&k_enc[16], count, cfg.bearer_id - 1, cfg.rx_direction, ct, ct_len, msg_tmp); memcpy(msg, msg_tmp, ct_len); break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_enc[16], count, cfg.bearer_id - 1, cfg.rx_direction, ct, ct_len, msg_tmp); + memcpy(msg, msg_tmp, ct_len); + break; default: break; } diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index bf7e84ab4..7f57f50f8 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -1571,6 +1571,15 @@ bool nas::short_integrity_check(srslte::byte_buffer_t* pdu) 2, &exp_mac[0]); break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], + 2, + &exp_mac[0]); + break; default: break; } @@ -1616,6 +1625,15 @@ bool nas::integrity_check(srslte::byte_buffer_t* pdu) pdu->N_bytes - 5, &exp_mac[0]); break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; default: break; } @@ -1657,6 +1675,15 @@ void nas::integrity_generate(srslte::byte_buffer_t* pdu, uint8_t* mac) pdu->N_bytes - 5, mac); break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.dl_nas_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); + break; default: break; } @@ -1693,6 +1720,17 @@ void nas::cipher_decrypt(srslte::byte_buffer_t* pdu) m_nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + srslte::security_128_eea3(&m_sec_ctx.k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + m_nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + break; default: m_nas_log->error("Ciphering algorithms not known\n"); break; @@ -1727,6 +1765,17 @@ void nas::cipher_encrypt(srslte::byte_buffer_t* pdu) memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); m_nas_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + srslte::security_128_eea3(&m_sec_ctx.k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + srslte::SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + m_nas_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); + break; default: m_nas_log->error("Ciphering algorithm not known\n"); break; diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index eb67f2952..03220958d 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -956,6 +956,15 @@ void rrc::send_con_restablish_request() N_bytes, mac_key); break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_rrc_int[16], + 0xffffffff, // 32-bit all to ones + 0x1f, // 5-bit all to ones + 1, // 1-bit to one + varShortMAC_packed, + N_bytes, + mac_key); + break; default: rrc_log->info("Unsupported integrity algorithm during reestablishment\n"); } diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 719ee00b9..80c490edf 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -645,6 +645,15 @@ void nas::integrity_generate(uint8_t *key_128, msg_len, mac); break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(key_128, + count, + 0, // Bearer always 0 for NAS + direction, + msg, + msg_len, + mac); + break; default: break; } @@ -716,6 +725,16 @@ void nas::cipher_encrypt(byte_buffer_t* pdu) &pdu_tmp.msg[6]); memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + break; default: nas_log->error("Ciphering algorithm not known\n"); break; @@ -750,6 +769,17 @@ void nas::cipher_decrypt(byte_buffer_t* pdu) nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + break; default: nas_log->error("Ciphering algorithms not known\n"); break;