I found there is an issue with packing Security Mode Command in function liblte_mme_pack_ue_security_capabilities_ie.
Current code does not folow 3gpp spec (9.9.3.36 UE security capability):
1) Octets 5, 6, and 7 are optional.
2) If octet 5 is included, then also octet 6 shall be included and octet 7 may be included.
3) If the UE did not indicate support of any security algorithm for Iu mode but indicated support of a security algorithm for
Gb mode, octets 5, 6, and 7 shall be included. In this case octets 5 and 6 are filled with the value of zeroes. - in this case issue could be observed.
Hello Ben,
I found there is an issue with packing Security Mode Command in function liblte_mme_pack_ue_security_capabilities_ie.
Current code does not folow 3gpp spec (9.9.3.36 UE security capability):
1) Octets 5, 6, and 7 are optional.
2) If octet 5 is included, then also octet 6 shall be included and octet 7 may be included.
3) If the UE did not indicate support of any security algorithm for Iu mode but indicated support of a security algorithm for
Gb mode, octets 5, 6, and 7 shall be included. In this case octets 5 and 6 are filled with the value of zeroes. - in this case issue could be observed.
Solution:
LIBLTE_ERROR_ENUM liblte_mme_pack_ue_security_capabilities_ie(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT ue_sec_cap,
uint8_t *ie_ptr)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint32_t idx;
if (ue_sec_cap->gea_present)
{
(ie_ptr)[0] = 5;
}
else if (ue_sec_cap->uea_present ||
ue_sec_cap->uia_present)
{
(ie_ptr)[0] = 4;
}
else
{
(ie_ptr)[0] = 2;
}
idx = 1;
(ie_ptr)[idx] = ue_sec_cap->eea[0] << 7;
(ie_ptr)[idx] |= ue_sec_cap->eea[1] << 6;
(ie_ptr)[idx] |= ue_sec_cap->eea[2] << 5;
(ie_ptr)[idx] |= ue_sec_cap->eea[3] << 4;
(ie_ptr)[idx] |= ue_sec_cap->eea[4] << 3;
(ie_ptr)[idx] |= ue_sec_cap->eea[5] << 2;
(ie_ptr)[idx] |= ue_sec_cap->eea[6] << 1;
(ie_ptr)[idx] |= ue_sec_cap->eea[7];
idx++;
(ie_ptr)[idx] = ue_sec_cap->eia[0] << 7;
(ie_ptr)[idx] |= ue_sec_cap->eia[1] << 6;
(ie_ptr)[idx] |= ue_sec_cap->eia[2] << 5;
(ie_ptr)[idx] |= ue_sec_cap->eia[3] << 4;
(ie_ptr)[idx] |= ue_sec_cap->eia[4] << 3;
(ie_ptr)[idx] |= ue_sec_cap->eia[5] << 2;
(ie_ptr)[idx] |= ue_sec_cap->eia[6] << 1;
(ie_ptr)[idx] |= ue_sec_cap->eia[7];
idx++;
if (ue_sec_cap->gea_present ||
ue_sec_cap->uea_present ||
ue_sec_cap->uia_present)
{
(ie_ptr)[idx] = ue_sec_cap->uea[0] << 7;
(ie_ptr)[idx] |= ue_sec_cap->uea[1] << 6;
(ie_ptr)[idx] |= ue_sec_cap->uea[2] << 5;
(ie_ptr)[idx] |= ue_sec_cap->uea[3] << 4;
(ie_ptr)[idx] |= ue_sec_cap->uea[4] << 3;
(ie_ptr)[idx] |= ue_sec_cap->uea[5] << 2;
(ie_ptr)[idx] |= ue_sec_cap->uea[6] << 1;
(ie_ptr)[idx] |= ue_sec_cap->uea[7];
idx++;
(ie_ptr)[idx] = ue_sec_cap->uia[1] << 6;
(ie_ptr)[idx] |= ue_sec_cap->uia[2] << 5;
(ie_ptr)[idx] |= ue_sec_cap->uia[3] << 4;
(ie_ptr)[idx] |= ue_sec_cap->uia[4] << 3;
(ie_ptr)[idx] |= ue_sec_cap->uia[5] << 2;
(ie_ptr)[idx] |= ue_sec_cap->uia[6] << 1;
(ie_ptr)[idx] |= ue_sec_cap->uia[7];
idx++;
}
if (ue_sec_cap->gea_present)
{
(ie_ptr)[idx] = ue_sec_cap->gea[1] << 6;
(ie_ptr)[idx] |= ue_sec_cap->gea[2] << 5;
(ie_ptr)[idx] |= ue_sec_cap->gea[3] << 4;
(ie_ptr)[idx] |= ue_sec_cap->gea[4] << 3;
(ie_ptr)[idx] |= ue_sec_cap->gea[5] << 2;
(ie_ptr)[idx] |= ue_sec_cap->gea[6] << 1;
(ie_ptr)[idx] |= ue_sec_cap->gea[7];
idx++;
}
ie_ptr += idx;
}
Best regards,
Przemek
PS. You may use this code in next release. :)