blob: 8dfff864c063c85052630a21deba9ad839782067 [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301/*
2 * Copyright (c) 2003-2018, Great Software Laboratory Pvt. Ltd.
3 * Copyright (c) 2017 Intel Corporation
4 * Copyright (c) 2019, Infosys Ltd.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <pthread.h>
22#include <string.h>
23#include <unistd.h>
24#include <stdint.h>
25
26#include "err_codes.h"
27#include "message_queues.h"
28#include "ipc_api.h"
29#include "log.h"
30#include "main.h"
31#include "s1ap.h"
32#include "sctp_conn.h"
33#include "msgType.h"
34#include "snow_3g.h"
35
36/**
37* Get ProtocolIE value for Sec Request sent by mme-app
38*/
39static int
40get_secreq_protoie_value(struct proto_IE *value, struct sec_mode_Q_msg * g_secReqInfo)
41{
42 value->no_of_IEs = SEC_MODE_NO_OF_IES;
43
44 value->data = (proto_IEs *) malloc(SEC_MODE_NO_OF_IES *
45 sizeof(proto_IEs));
46
47 value->data[0].val.mme_ue_s1ap_id = g_secReqInfo->ue_idx;
48 value->data[1].val.enb_ue_s1ap_id = g_secReqInfo->enb_s1ap_ue_id;
49
50 value->data[2].val.nas.header.security_header_type =
51 IntegrityProtectedEPSSecCntxt;
52
53 value->data[2].val.nas.header.proto_discriminator =
54 EPSMobilityManagementMessages;
55
56 /* placeholder for mac. mac value will be calculated later */
57 uint8_t mac[MAC_SIZE] = {0};
58 memcpy(value->data[2].val.nas.header.mac, mac, MAC_SIZE);
59
60 value->data[2].val.nas.header.seq_no = g_secReqInfo->dl_seq_no;
61
62 value->data[2].val.nas.header.message_type = SecurityModeCommand;
63
64 value->data[2].val.nas.header.security_encryption_algo = Algo_EEA0;
65
66 value->data[2].val.nas.header.security_integrity_algo = Algo_128EIA1;
67
68 /* Security Param (1 octet) =
69 * Spare half octet, Type of Security, NAS KSI
70 * TODO: Remove hard coded value
71 */
72 value->data[2].val.nas.header.nas_security_param = AUTHREQ_NAS_SECURITY_PARAM;
73
74 value->data[2].val.nas.elements_len = SEC_MODE_NO_OF_NAS_IES;
75
76 value->data[2].val.nas.elements = (nas_pdu_elements *)
77 malloc(SEC_MODE_NO_OF_NAS_IES * sizeof(nas_pdu_elements));
78
79 value->data[2].val.nas.elements->pduElement.ue_network.len =
80 g_secReqInfo->ue_network.len;
81 if(g_secReqInfo->ue_network.len >= 4)
82 {
83 /*Copy first 4 bytes of security algo info*/
84 memcpy(value->data[2].val.nas.elements->pduElement.ue_network.capab,
85 g_secReqInfo->ue_network.capab, 4);
86
87 log_msg(LOG_DEBUG, "UE network length : %d", g_secReqInfo->ue_network.len);
88 if(g_secReqInfo->ms_net_capab.pres == true)
89 {
90 /*The MS Network capability contains the GEA
91 * capability. The MSB of 1st Byte and the 2nd to
92 * 7th Bit of 2nd byte contain the GEA info.
93 * Thus the masks 0x7F : for GEA/1
94 * and mask 0x7D: for GEA2 -GEA7
95 */
96 log_msg(LOG_DEBUG, "MS network present");
97 value->data[2].val.nas.elements->pduElement.ue_network.len = 5;
98 unsigned char val = 0x00;
99 val = g_secReqInfo->ms_net_capab.capab[0]&0x80;
100 val |= g_secReqInfo->ms_net_capab.capab[1]&0x7E;
101 val >>= 1;
102 value->data[2].val.nas.elements->pduElement.ue_network.capab[4] = val;
103 }
104 else
105 {
106 /*If MS capability is not present. Then only
107 * Capability till UMTS Algorithms is sent.*/
108 log_msg(LOG_DEBUG, "MS network not present");
109 value->data[2].val.nas.elements->pduElement.ue_network.len = 4;
110 }
111 }
112 else
113 {
114 /*Copy as much info of UE network capability
115 * as received.
116 */
117 log_msg(LOG_DEBUG, "UE network length again: %d", g_secReqInfo->ue_network.len);
118 memcpy(value->data[2].val.nas.elements->pduElement.ue_network.capab,
119 g_secReqInfo->ue_network.capab, g_secReqInfo->ue_network.len);
120 }
121
122 return SUCCESS;
123}
124
125
126/**
127* Stage specific message processing.
128*/
129static int
130secreq_processing(struct sec_mode_Q_msg * g_secReqInfo)
131{
132 Buffer g_sec_buffer;
133 Buffer g_sec_value_buffer;
134 Buffer g_sec_nas_buffer;
135
136 unsigned char tmpStr[4];
137 struct s1ap_PDU s1apPDU= {0};
138 uint8_t mac_data_pos;
139
140 s1apPDU.procedurecode = id_downlinkNASTransport;
141 s1apPDU.criticality = CRITICALITY_IGNORE;
142
143 get_secreq_protoie_value(&s1apPDU.value, g_secReqInfo);
144
145 /* Copy values to g_sec_nas_buffer */
146
147 /* id-NAS-PDU */
148 g_sec_nas_buffer.pos = 0;
149 nasPDU nas = s1apPDU.value.data[2].val.nas;
150
151 unsigned char value = (nas.header.security_header_type << 4 |
152 nas.header.proto_discriminator);
153
154 buffer_copy(&g_sec_nas_buffer, &value, sizeof(value));
155
156 /* placeholder for mac. mac value will be calculated later */
157 buffer_copy(&g_sec_nas_buffer, &nas.header.mac, MAC_SIZE);
158
159 mac_data_pos = g_sec_nas_buffer.pos;
160
161 buffer_copy(&g_sec_nas_buffer, &nas.header.seq_no,
162 sizeof(nas.header.seq_no));
163
164 nas.header.security_header_type = Plain;
165 value = nas.header.security_header_type |
166 nas.header.proto_discriminator;
167 buffer_copy(&g_sec_nas_buffer, &value, sizeof(value));
168
169 buffer_copy(&g_sec_nas_buffer, &nas.header.message_type,
170 sizeof(nas.header.message_type));
171
172 value = (nas.header.security_encryption_algo << 4 |
173 nas.header.security_integrity_algo);
174 buffer_copy(&g_sec_nas_buffer, &value, sizeof(value));
175
176 buffer_copy(&g_sec_nas_buffer, &nas.header.nas_security_param,
177 sizeof(nas.header.nas_security_param));
178
179 buffer_copy(&g_sec_nas_buffer, &nas.elements->pduElement.ue_network.len,
180 sizeof(nas.elements->pduElement.ue_network.len));
181
182 buffer_copy(&g_sec_nas_buffer, &nas.elements->pduElement.ue_network.capab,
183 nas.elements->pduElement.ue_network.len);
184
185 /* Calculate mac */
186 uint8_t direction = 1;
187 uint8_t bearer = 0;
188
189 calculate_mac(g_secReqInfo->int_key, nas.header.seq_no,
190 direction, bearer, &g_sec_nas_buffer.buf[mac_data_pos],
191 g_sec_nas_buffer.pos - mac_data_pos,
192 &g_sec_nas_buffer.buf[mac_data_pos - MAC_SIZE]);
193
194 /* Copy values in g_sec_value_buffer */
195 g_sec_value_buffer.pos = 0;
196
197 /* TODO remove hardcoded values */
198 char chProtoIENo[3] = {0,0,3};
199 buffer_copy(&g_sec_value_buffer, chProtoIENo, 3);
200
201 /* id-MME-UE-S1AP-ID */
202 uint16_t protocolIe_Id = id_MME_UE_S1AP_ID;
203 copyU16(tmpStr, protocolIe_Id);
204 buffer_copy(&g_sec_value_buffer, tmpStr,
205 sizeof(protocolIe_Id));
206
207 unsigned char protocolIe_criticality = CRITICALITY_REJECT;
208 buffer_copy(&g_sec_value_buffer, &protocolIe_criticality,
209 sizeof(protocolIe_criticality));
210
211 unsigned char datalen = 2;
212
213 /* TODO need to add proper handling*/
214 unsigned char mme_ue_id[3];
215 datalen = copyU16(mme_ue_id, s1apPDU.value.data[0].val.mme_ue_s1ap_id);
216 buffer_copy(&g_sec_value_buffer, &datalen, sizeof(datalen));
217 buffer_copy(&g_sec_value_buffer, mme_ue_id, datalen);
218
219 /* id-eNB-UE-S1AP-ID */
220 protocolIe_Id = id_eNB_UE_S1AP_ID;
221 copyU16(tmpStr, protocolIe_Id);
222 buffer_copy(&g_sec_value_buffer, tmpStr,
223 sizeof(protocolIe_Id));
224
225 buffer_copy(&g_sec_value_buffer, &protocolIe_criticality,
226 sizeof(protocolIe_criticality));
227
228 /* TODO needs proper handling*/
229 unsigned char enb_ue_id[3];
230 datalen = copyU16(enb_ue_id, s1apPDU.value.data[1].val.enb_ue_s1ap_id);
231 buffer_copy(&g_sec_value_buffer, &datalen, sizeof(datalen));
232 buffer_copy(&g_sec_value_buffer, enb_ue_id, datalen);
233
234 /* id-NAS-PDU */
235 protocolIe_Id = id_NAS_PDU;
236 copyU16(tmpStr, protocolIe_Id);
237 buffer_copy(&g_sec_value_buffer, tmpStr,
238 sizeof(protocolIe_Id));
239
240 buffer_copy(&g_sec_value_buffer, &protocolIe_criticality,
241 sizeof(protocolIe_criticality));
242
243
244 datalen = g_sec_nas_buffer.pos + 1;
245 buffer_copy(&g_sec_value_buffer, &datalen,
246 sizeof(datalen));
247
248 buffer_copy(&g_sec_value_buffer, &g_sec_nas_buffer.pos,
249 sizeof(g_sec_nas_buffer.pos));
250
251 buffer_copy(&g_sec_value_buffer, &g_sec_nas_buffer,
252 g_sec_nas_buffer.pos);
253
254 /* Copy values in g_sec_buffer */
255 g_sec_buffer.pos = 0;
256
257 unsigned char initiating_message = 0; /* TODO: Add enum */
258 buffer_copy(&g_sec_buffer, &initiating_message,
259 sizeof(initiating_message));
260
261 buffer_copy(&g_sec_buffer, &s1apPDU.procedurecode,
262 sizeof(s1apPDU.procedurecode));
263
264 buffer_copy(&g_sec_buffer, &s1apPDU.criticality,
265 sizeof(s1apPDU.criticality));
266
267 buffer_copy(&g_sec_buffer, &g_sec_value_buffer.pos,
268 sizeof(g_sec_value_buffer.pos));
269
270 buffer_copy(&g_sec_buffer, &g_sec_value_buffer,
271 g_sec_value_buffer.pos);
272
273 free(s1apPDU.value.data[2].val.nas.elements);
274 free(s1apPDU.value.data);
275 //STIMER_GET_CURRENT_TP(g_attach_stats[s1apPDU.value.data[1].enb_ue_s1ap_id].secreq_out);
276
277 send_sctp_msg(g_secReqInfo->enb_fd, g_sec_buffer.buf, g_sec_buffer.pos, 1);
278
279 return SUCCESS;
280}
281
282/**
283* Thread function for stage.
284*/
285void*
286secreq_handler(void *data)
287{
288 log_msg(LOG_INFO, "SecReq handler ready.\n");
289
290 secreq_processing((struct sec_mode_Q_msg *)data);
291
292 return NULL;
293}