-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNASHelperS1AP_SecurityModeCommand.cpp
More file actions
139 lines (121 loc) · 5.35 KB
/
NASHelperS1AP_SecurityModeCommand.cpp
File metadata and controls
139 lines (121 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "NASHelperS1AP.hpp"
#include <utility>
namespace {
bool appendTlvFixedTotalOptional(const std::uint8_t* ie,
std::size_t n,
std::size_t& i,
std::uint8_t expectedIei,
std::size_t totalOctets,
NASHelperS1AP::SecurityModeCommandInformationElementsParse& out) {
if (i + totalOctets > n || ie[i] != expectedIei) {
return false;
}
const std::uint8_t len = ie[i + 1];
if (2U + static_cast<std::size_t>(len) != totalOctets) {
return false;
}
NASHelperS1AP::SecurityModeCommandOptionalInformationElement opt{};
opt.iei = expectedIei;
opt.encoding = NASHelperS1AP::SecurityModeCommandOptionalInformationElement::Encoding::Tlv;
opt.value.assign(ie + i + 2U, ie + i + totalOctets);
out.optionals.push_back(std::move(opt));
i += totalOctets;
return true;
}
bool appendTvFixedOptional(const std::uint8_t* ie,
std::size_t n,
std::size_t& i,
std::uint8_t expectedIei,
std::size_t totalOctets,
NASHelperS1AP::SecurityModeCommandInformationElementsParse& out) {
if (i + totalOctets > n || ie[i] != expectedIei) {
return false;
}
NASHelperS1AP::SecurityModeCommandOptionalInformationElement opt{};
opt.iei = expectedIei;
opt.encoding = NASHelperS1AP::SecurityModeCommandOptionalInformationElement::Encoding::TvFixed;
if (totalOctets > 1U) {
opt.value.assign(ie + i + 1U, ie + i + totalOctets);
}
out.optionals.push_back(std::move(opt));
i += totalOctets;
return true;
}
bool appendHalfOctetTvOptional(std::uint8_t b,
std::size_t& i,
NASHelperS1AP::SecurityModeCommandInformationElementsParse& out) {
NASHelperS1AP::SecurityModeCommandOptionalInformationElement opt{};
opt.iei = static_cast<std::uint8_t>(b & 0xF0U);
opt.encoding = NASHelperS1AP::SecurityModeCommandOptionalInformationElement::Encoding::TvHalfOctetIei;
opt.tv_half_octet = b;
out.optionals.push_back(std::move(opt));
i += 1U;
return true;
}
bool isSecurityModeCommandHalfOctetType1TvCOrD(std::uint8_t b) {
const unsigned h = b >> 4U;
return h == 0xCU || h == 0xDU;
}
} // namespace
bool NASHelperS1AP::tryParseSecurityModeCommandInformationElements(const std::uint8_t* const informationElements,
const std::size_t informationElementOctetCount,
SecurityModeCommandInformationElementsParse& out) {
out = SecurityModeCommandInformationElementsParse{};
if (informationElements == nullptr || informationElementOctetCount < 3U) {
return false;
}
const std::uint8_t nasAlg = informationElements[0];
const std::uint8_t ksiSpare = informationElements[1];
const std::uint8_t capLen = informationElements[2];
const std::size_t lvTotal = 1U + static_cast<std::size_t>(capLen);
if (lvTotal < SecurityModeCommandMandatoryFields::kReplayedUeSecurityCapabilitiesLvMinTotalOctets ||
lvTotal > SecurityModeCommandMandatoryFields::kReplayedUeSecurityCapabilitiesLvMaxTotalOctets) {
return false;
}
const std::size_t mandatoryTotal = 2U + lvTotal;
if (informationElementOctetCount < mandatoryTotal) {
return false;
}
out.mandatory.selected_nas_security_algorithms_octet = nasAlg;
out.mandatory.nas_key_set_identifier_and_spare_octet = ksiSpare;
out.mandatory.replayed_ue_security_capabilities_value = informationElements + 3U;
out.mandatory.replayed_ue_security_capabilities_value_octet_count = static_cast<std::size_t>(capLen);
out.mandatory.mandatory_total_octets = mandatoryTotal;
std::size_t i = mandatoryTotal;
while (i < informationElementOctetCount) {
const std::uint8_t b = informationElements[i];
bool consumed = false;
switch (b) {
case 0x55U:
case 0x56U:
consumed = appendTvFixedOptional(informationElements, informationElementOctetCount, i, b, 5U, out);
break;
case 0x4FU:
consumed = appendTlvFixedTotalOptional(informationElements, informationElementOctetCount, i, 0x4FU, 10U,
out);
break;
case 0x6FU:
consumed = appendTlvFixedTotalOptional(informationElements, informationElementOctetCount, i, 0x6FU, 6U,
out);
break;
case 0x37U:
consumed = appendTlvFixedTotalOptional(informationElements, informationElementOctetCount, i, 0x37U, 3U,
out);
break;
default:
break;
}
if (consumed) {
continue;
}
if (isSecurityModeCommandHalfOctetType1TvCOrD(b)) {
appendHalfOctetTvOptional(b, i, out);
continue;
}
break;
}
out.unparsed_begin = informationElements + i;
out.unparsed_octet_count = informationElementOctetCount - i;
out.ok = true;
return true;
}