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