1 /* *****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
21 #include "iotivity_config.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
32 #include "payload_logging.h"
33 #include "ocpayload.h"
34 #include "ocpayloadcbor.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"
45 #define TAG "OIC_SEC_VER"
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;
51 /** Max cbor size payload. */
52 static const uint16_t CBOR_MAX_SIZE = 4400;
54 /** VER Map size - Number of mandatory items. */
55 static const uint8_t VER_MAP_SIZE = 2;
57 static OCResourceHandle gVerHandle = NULL;
59 /** Security version is mapped with iotivity release version */
60 const char* SECURITY_VERSION = IOTIVITY_VERSION;
62 static OicSecVer_t gVer =
65 {.id = {0}}, /* OicUuid_t deviceID */
68 void DeleteVerBinData(OicSecVer_t* ver)
77 OCStackResult VerToCBORPayload(const OicSecVer_t *ver, uint8_t **payload, size_t *size)
79 if (NULL == ver || NULL == payload || NULL != *payload || NULL == size)
81 return OC_STACK_INVALID_PARAM;
83 size_t cborLen = *size;
91 OCStackResult ret = OC_STACK_ERROR;
96 int64_t cborEncoderResult = CborNoError;
97 uint8_t mapSize = VER_MAP_SIZE;
100 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
101 VERIFY_NON_NULL(TAG, outPayload, ERROR);
102 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
104 cborEncoderResult |= cbor_encoder_create_map(&encoder, &verMap, mapSize);
105 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Ver Map.");
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.");
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.");
126 // Close ver(first) container
127 cborEncoderResult |= cbor_encoder_close_container(&encoder, &verMap);
128 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing VerMap.");
130 if (CborNoError == cborEncoderResult)
132 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
133 *payload = outPayload;
137 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
139 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
140 // reallocate and try again!
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);
151 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
157 ret = OC_STACK_ERROR;
163 OCStackResult CBORPayloadToVer(const uint8_t *cborPayload, size_t size,
164 OicSecVer_t **secVer)
166 if (NULL == cborPayload || NULL == secVer || NULL != *secVer || 0 == size)
168 return OC_STACK_INVALID_PARAM;
171 OCStackResult ret = OC_STACK_ERROR;
173 char *strUuid = NULL;
175 CborParser parser = { .end = NULL};
176 CborError cborFindResult = CborNoError;
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);
185 cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_SEC_V_NAME, &verMap);
186 if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap))
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);
195 cborFindResult = cbor_value_map_find_value(&verCbor, OIC_JSON_DEVICE_ID_NAME, &verMap);
196 if (CborNoError == cborFindResult && cbor_value_is_text_string(&verMap))
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);
210 if (CborNoError != cborFindResult)
212 OIC_LOG (ERROR, TAG, "CBORPayloadToVer failed!!!");
213 DeleteVerBinData(ver);
214 ret = OC_STACK_ERROR;
219 static OCEntityHandlerResult HandleVerGetRequest (const OCEntityHandlerRequest * ehRequest)
221 OCEntityHandlerResult ehRet = OC_EH_OK;
223 OIC_LOG(DEBUG, TAG, "Ver EntityHandle processing GET request");
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.
231 uint8_t *payload = NULL;
233 if (OC_STACK_OK != VerToCBORPayload(&gVer, &payload, &size))
238 // Send response payload to request originator
239 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
242 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleVerGetRequest");
250 OCEntityHandlerResult VerEntityHandler(OCEntityHandlerFlag flag,
251 OCEntityHandlerRequest * ehRequest,
255 OCEntityHandlerResult ehRet = OC_EH_ERROR;
257 if(NULL == ehRequest)
262 if (flag & OC_REQUEST_FLAG)
264 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
266 switch (ehRequest->method)
269 ehRet = HandleVerGetRequest(ehRequest);
274 SendSRMResponse(ehRequest, ehRet, NULL, 0);
282 OCStackResult CreateVerResource()
284 OCStackResult ret = OCCreateResource(&gVerHandle,
285 OIC_RSRC_TYPE_SEC_VER,
286 OC_RSRVD_INTERFACE_DEFAULT,
292 if (OC_STACK_OK != ret)
294 OIC_LOG (FATAL, TAG, "Unable to instantiate Ver resource");
301 * Get the security version.
303 * @return the version string of security.
305 const char* GetSecVersion()
307 OIC_LOG(DEBUG, TAG, "GetSecVersion");
311 const OicSecVer_t* GetVerResourceData()
316 OCStackResult InitVerResource()
318 OCStackResult ret = OC_STACK_ERROR;
320 OICStrcpy(gVer.secv, OIC_SEC_MAX_VER_LEN, SECURITY_VERSION);
322 //Read device id from doxm
323 OicUuid_t deviceID = {.id={0}};
324 ret = GetDoxmDeviceID(&deviceID);
325 if (OC_STACK_OK != ret)
327 OIC_LOG(ERROR, TAG, "Error while retrieving doxm device ID");
330 memcpy(&gVer.deviceID, &deviceID, sizeof(OicUuid_t));
332 //Instantiate 'oic.sec.ver'
333 ret = CreateVerResource();
334 if (OC_STACK_OK != ret)
336 OIC_LOG(ERROR, TAG, "Error while creating VER resource");
342 OCStackResult DeInitVerResource()
344 OCStackResult ret = OCDeleteResource(gVerHandle);
346 memset(&gVer, 0, sizeof(gVer));
348 if (OC_STACK_OK == ret)
354 return OC_STACK_ERROR;