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