e2363ad4638928d1a171b107af9f7b8e5a79a0b8
[iotivity.git] / resource / csdk / security / src / verresource.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include "iotivity_config.h"
22 #include <stdlib.h>
23 #include <string.h>
24
25 #ifdef HAVE_STRINGS_H
26 #include <strings.h>
27 #endif
28
29 #include "ocstack.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
32 #include "logger.h"
33 #include "payload_logging.h"
34 #include "ocpayload.h"
35 #include "ocpayloadcbor.h"
36 #include "cainterface.h"
37 #include "ocserverrequest.h"
38 #include "resourcemanager.h"
39 #include "verresource.h"
40 #include "doxmresource.h"
41 #include "psinterface.h"
42 #include "srmresourcestrings.h"
43 #include "securevirtualresourcetypes.h"
44 #include "srmutility.h"
45
46 #define TAG  "OIC_SEC_VER"
47
48 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
49  * The value of payload size is increased until reaching belox max cbor size. */
50 static const uint8_t CBOR_SIZE = 255;
51
52 /** Max cbor size payload. */
53 static const uint16_t CBOR_MAX_SIZE = 4400;
54
55 /** VER Map size - Number of mandatory items. */
56 static const uint8_t VER_MAP_SIZE = 2;
57
58 static OCResourceHandle    gVerHandle = NULL;
59
60 /** Security version is mapped with iotivity release version */
61 const char* SECURITY_VERSION = IOTIVITY_VERSION;
62
63 static OicSecVer_t gVer =
64 {
65     {0},                  /* char *secv */
66     {.id = {0}},         /* OicUuid_t deviceID */
67 };
68
69 void DeleteVerBinData(OicSecVer_t* ver)
70 {
71     if (ver)
72     {
73         //Clean ver itself
74         OICFree(ver);
75     }
76 }
77
78 OCStackResult VerToCBORPayload(const OicSecVer_t *ver, uint8_t **payload, size_t *size)
79 {
80     if (NULL == ver || NULL == payload || NULL != *payload || NULL == size)
81     {
82         return OC_STACK_INVALID_PARAM;
83     }
84     size_t cborLen = *size;
85     if (0 == cborLen)
86     {
87         cborLen = CBOR_SIZE;
88     }
89     *payload = NULL;
90     *size = 0;
91
92     OCStackResult ret = OC_STACK_ERROR;
93
94     CborEncoder encoder;
95     CborEncoder verMap;
96
97     int64_t cborEncoderResult = CborNoError;
98     uint8_t mapSize = VER_MAP_SIZE;
99     char* strUuid = NULL;
100
101     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
102     VERIFY_NON_NULL(TAG, outPayload, ERROR);
103     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
104
105     cborEncoderResult |= cbor_encoder_create_map(&encoder, &verMap, mapSize);
106     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Ver Map.");
107
108     //SecV -- Mandatory
109     cborEncoderResult |= cbor_encode_text_string(&verMap, OIC_JSON_SEC_V_NAME,
110         strlen(OIC_JSON_SEC_V_NAME));
111     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SecV Tag.");
112     cborEncoderResult |= cbor_encode_text_string(&verMap, ver->secv, strlen(ver->secv));
113     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SecV Value.");
114
115     //DeviceId -- Mandatory
116     cborEncoderResult = cbor_encode_text_string(&verMap, OIC_JSON_DEVICE_ID_NAME,
117         strlen(OIC_JSON_DEVICE_ID_NAME));
118     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
119     ret = ConvertUuidToStr(&ver->deviceID, &strUuid);
120     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
121     cborEncoderResult = cbor_encode_text_string(&verMap, strUuid, strlen(strUuid));
122     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
123     OICFree(strUuid);
124     strUuid = NULL;
125
126
127     // Close ver(first) container
128     cborEncoderResult |= cbor_encoder_close_container(&encoder, &verMap);
129     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing VerMap.");
130
131     if (CborNoError == cborEncoderResult)
132     {
133         *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
134         *payload = outPayload;
135         ret = OC_STACK_OK;
136     }
137 exit:
138     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
139     {
140         OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
141         // reallocate and try again!
142         OICFree(outPayload);
143         // Since the allocated initial memory failed, double the memory.
144         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
145         OIC_LOG_V(DEBUG, TAG, "Ver reallocation size : %zd.", cborLen);
146         cborEncoderResult = CborNoError;
147         ret = VerToCBORPayload(ver, payload, &cborLen);
148         *size = cborLen;
149     }
150
151     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
152     {
153        OICFree(outPayload);
154        outPayload = NULL;
155        *payload = NULL;
156        *size = 0;
157        ret = OC_STACK_ERROR;
158     }
159
160     return ret;
161 }
162
163 OCStackResult CBORPayloadToVer(const uint8_t *cborPayload, size_t size,
164                                 OicSecVer_t **secVer)
165 {
166     if (NULL == cborPayload || NULL == secVer || NULL != *secVer || 0 == size)
167     {
168         return OC_STACK_INVALID_PARAM;
169     }
170
171     OCStackResult ret = OC_STACK_ERROR;
172     *secVer = NULL;
173     char *strUuid = NULL;
174
175     CborParser parser = { .end = NULL};
176     CborError cborFindResult = CborNoError;
177     size_t len = 0;
178     CborValue verCbor = { .parser = NULL };
179     cbor_parser_init(cborPayload, size, 0, &parser, &verCbor);
180     CborValue verMap = { .parser = NULL };
181     OicSecVer_t *ver = (OicSecVer_t *)OICCalloc(1, sizeof(OicSecVer_t));
182     VERIFY_NON_NULL(TAG, ver, ERROR);
183
184
185     cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_SEC_V_NAME, &verMap);
186     if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap))
187     {
188         char *version = NULL;
189         cborFindResult = cbor_value_dup_text_string(&verMap, &version, &len, NULL);
190         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Security Version Value.");
191         memcpy(ver->secv, version, len);
192         OICFree(version);
193     }
194
195     cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_DEVICE_ID_NAME, &verMap);
196     if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap))
197     {
198         cborFindResult = cbor_value_dup_text_string(&verMap, &strUuid , &len, NULL);
199         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
200         ret = ConvertStrToUuid(strUuid , &ver->deviceID);
201         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
202         OICFree(strUuid );
203         strUuid  = NULL;
204     }
205
206     *secVer = ver;
207     ret = OC_STACK_OK;
208
209 exit:
210     if (CborNoError != cborFindResult)
211     {
212         OIC_LOG (ERROR, TAG, "CBORPayloadToVer failed!!!");
213         DeleteVerBinData(ver);
214         ret = OC_STACK_ERROR;
215     }
216     return ret;
217 }
218
219 static OCEntityHandlerResult HandleVerGetRequest (const OCEntityHandlerRequest * ehRequest)
220 {
221     OCEntityHandlerResult ehRet = OC_EH_OK;
222
223     OIC_LOG(DEBUG, TAG, "Ver EntityHandle processing GET request");
224
225     /*
226      * For GET request return ver resource CBOR payload.
227      * For non-valid query return NULL json payload.
228      * The version is static built-in information, so VerToCBORPayload will
229      * return valid ver resource json.
230      */
231     uint8_t *payload = NULL;
232     size_t size = 0;
233     if (OC_STACK_OK != VerToCBORPayload(&gVer, &payload, &size))
234     {
235         payload = NULL;
236     }
237
238     // Send response payload to request originator
239     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
240     {
241         ehRet = OC_EH_ERROR;
242         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleVerGetRequest");
243     }
244
245     OICFree(payload);
246
247     return ehRet;
248 }
249
250 OCEntityHandlerResult VerEntityHandler(OCEntityHandlerFlag flag,
251                                         OCEntityHandlerRequest * ehRequest,
252                                         void* callbackParam)
253 {
254     (void)callbackParam;
255     OCEntityHandlerResult ehRet = OC_EH_ERROR;
256
257     if(NULL == ehRequest)
258     {
259         return ehRet;
260     }
261
262     if (flag & OC_REQUEST_FLAG)
263     {
264         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
265
266         switch (ehRequest->method)
267         {
268             case OC_REST_GET:
269                 ehRet = HandleVerGetRequest(ehRequest);
270                 break;
271
272             default:
273                 ehRet = OC_EH_ERROR;
274                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
275                 break;
276         }
277     }
278
279     return ehRet;
280 }
281
282 OCStackResult CreateVerResource()
283 {
284     OCStackResult ret = OCCreateResource(&gVerHandle,
285                                          OIC_RSRC_TYPE_SEC_VER,
286                                          OC_RSRVD_INTERFACE_DEFAULT,
287                                          OIC_RSRC_VER_URI,
288                                          VerEntityHandler,
289                                          NULL,
290                                          OC_SECURE);
291
292     if (OC_STACK_OK != ret)
293     {
294         OIC_LOG (FATAL, TAG, "Unable to instantiate Ver resource");
295         DeInitVerResource();
296     }
297     return ret;
298 }
299
300 /**
301  * Get the security version.
302  *
303  * @return the version string of security.
304  */
305 const char* GetSecVersion()
306 {
307     OIC_LOG(DEBUG, TAG, "GetSecVersion");
308     return gVer.secv;
309 }
310
311 const OicSecVer_t* GetVerResourceData()
312 {
313     return &gVer;
314 }
315
316 OCStackResult InitVerResource()
317 {
318     OCStackResult ret = OC_STACK_ERROR;
319
320     OICStrcpy(gVer.secv, OIC_SEC_MAX_VER_LEN, SECURITY_VERSION);
321
322     //Read device id from doxm
323     OicUuid_t deviceID = {.id={0}};
324     ret = GetDoxmDeviceID(&deviceID);
325     if (OC_STACK_OK != ret)
326     {
327         OIC_LOG(ERROR, TAG, "Error while retrieving doxm device ID");
328         return ret;
329     }
330     memcpy(&gVer.deviceID, &deviceID, sizeof(OicUuid_t));
331
332     //Instantiate 'oic.sec.ver'
333     ret = CreateVerResource();
334     if (OC_STACK_OK != ret)
335     {
336         OIC_LOG(ERROR, TAG, "Error while creating VER resource");
337     }
338
339     return ret;
340 }
341
342 OCStackResult DeInitVerResource()
343 {
344     OCStackResult ret = OCDeleteResource(gVerHandle);
345
346     memset(&gVer, 0, sizeof(gVer));
347
348     if (OC_STACK_OK == ret)
349     {
350         return OC_STACK_OK;
351     }
352     else
353     {
354         return OC_STACK_ERROR;
355     }
356 }