1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #define _POSIX_C_SOURCE 200112L
23 #include "srmutility.h"
24 #include "srmresourcestrings.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
29 #include "doxmresource.h"
30 #include "credresource.h"
31 #include "pstatresource.h"
33 #include "casecurityinterface.h"
34 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
35 #include "pkix_interface.h"
38 #define TAG "OIC_SRM_UTILITY"
40 void ParseQueryIterInit(const unsigned char * query, OicParseQueryIter_t * parseIter)
42 OIC_LOG(INFO, TAG, "Initializing coap iterator");
43 if ((NULL == query) || (NULL == parseIter))
48 parseIter->attrPos = NULL;
49 parseIter->attrLen = 0;
50 parseIter->valPos = NULL;
51 parseIter->valLen = 0;
52 coap_parse_iterator_init((unsigned char *)query, strlen((char *)query),
53 (unsigned char *)OIC_SEC_REST_QUERY_SEPARATOR,
54 (unsigned char *) "", 0, &parseIter->pi);
57 OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter)
59 OIC_LOG(INFO, TAG, "Getting Next Query");
60 if (NULL == parseIter)
65 unsigned char * qrySeg = NULL;
68 // Get the next query. Querys are separated by OIC_SEC_REST_QUERY_SEPARATOR.
69 qrySeg = coap_parse_next(&parseIter->pi);
73 delimPos = strchr((char *)qrySeg, OIC_SEC_REST_QUERY_DELIMETER);
76 parseIter->attrPos = parseIter->pi.pos;
77 parseIter->attrLen = (unsigned char *)delimPos - parseIter->pi.pos;
78 parseIter->valPos = (unsigned char *)delimPos + 1;
79 parseIter->valLen = &qrySeg[parseIter->pi.segment_length] - parseIter->valPos;
86 // TODO This functionality is replicated in all SVR's and therefore we need
87 // to encapsulate it in a common method. However, this may not be the right
88 // file for this method.
89 OCStackResult AddUuidArray(const cJSON* jsonRoot, const char* arrayItem,
90 size_t *numUuids, OicUuid_t** uuids)
93 cJSON* jsonObj = cJSON_GetObjectItem((cJSON *)jsonRoot, arrayItem);
94 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
95 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
97 *numUuids = (size_t)cJSON_GetArraySize(jsonObj);
98 VERIFY_SUCCESS(TAG, *numUuids > 0, ERROR);
99 *uuids = (OicUuid_t*)OICCalloc(*numUuids, sizeof(OicUuid_t));
100 VERIFY_NON_NULL(TAG, *uuids, ERROR);
104 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {0};
106 B64Result b64Ret = B64_OK;
108 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
109 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
110 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
113 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
114 sizeof(base64Buff), &outLen);
116 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof((*uuids)[idxx].id)),
118 memcpy((*uuids)[idxx].id, base64Buff, outLen);
119 } while ( ++idxx < *numUuids);
124 return OC_STACK_ERROR;
129 * Function to getting string of ownership transfer method
131 * @prarm oxmType ownership transfer method
133 * @return string value of ownership transfer method
135 const char* GetOxmString(OicSecOxm_t oxmType)
140 return OXM_JUST_WORKS;
141 case OIC_RANDOM_DEVICE_PIN:
142 return OXM_RANDOM_DEVICE_PIN;
143 case OIC_MANUFACTURER_CERTIFICATE:
144 return OXM_MANUFACTURER_CERTIFICATE;
145 case OIC_RAW_PUB_KEY:
146 return OXM_RAW_PUBLIC_KEY;
147 #ifdef MULTIPLE_OWNER
148 case OIC_PRECONFIG_PIN:
149 return OXM_PRECONF_PIN;
150 #endif //MULTIPLE_OWNER
151 case OIC_MV_JUST_WORKS:
152 return OXM_MV_JUST_WORKS;
153 case OIC_CON_MFG_CERT:
154 return OXM_CON_MFG_CERT;
160 OCStackResult ConvertUuidToStr(const OicUuid_t* uuid, char** strUuid)
162 if(NULL == uuid || NULL == strUuid || NULL != *strUuid)
164 OIC_LOG(ERROR, TAG, "ConvertUuidToStr : Invalid param");
165 return OC_STACK_INVALID_PARAM;
170 const size_t urnBufSize = (UUID_LENGTH * 2) + 4 + 1;
171 char* convertedUrn = (char*)OICCalloc(urnBufSize, sizeof(char));
172 VERIFY_NON_NULL(TAG, convertedUrn, ERROR);
174 for(uuidIdx=0, urnIdx=0; uuidIdx < UUID_LENGTH && urnIdx < urnBufSize; uuidIdx++, urnIdx+=2)
176 // canonical format for UUID has '8-4-4-4-12'
177 if(uuidIdx==4 || uuidIdx==6 || uuidIdx==8 || uuidIdx==10)
179 snprintf(convertedUrn + urnIdx, 2, "%c", '-');
182 snprintf(convertedUrn + urnIdx, 3, "%02x", (uint8_t)(uuid->id[uuidIdx]));
184 convertedUrn[urnBufSize - 1] = '\0';
186 *strUuid = convertedUrn;
190 return OC_STACK_NO_MEMORY;
193 OCStackResult ConvertStrToUuid(const char* strUuid, OicUuid_t* uuid)
195 if(NULL == strUuid || NULL == uuid)
197 OIC_LOG(ERROR, TAG, "ConvertStrToUuid : Invalid param");
198 return OC_STACK_INVALID_PARAM;
203 size_t strUuidLen = 0;
204 char convertedUuid[UUID_LENGTH * 2] = {0};
206 strUuidLen = strlen(strUuid);
209 OIC_LOG(INFO, TAG, "The empty string detected, The UUID will be converted to "\
210 "\"00000000-0000-0000-0000-000000000000\"");
212 else if(UUID_LENGTH * 2 + 4 == strUuidLen)
214 for(uuidIdx=0, urnIdx=0; uuidIdx < UUID_LENGTH ; uuidIdx++, urnIdx+=2)
216 if(*(strUuid + urnIdx) == '-')
220 sscanf(strUuid + urnIdx, "%2hhx", &convertedUuid[uuidIdx]);
225 OIC_LOG(ERROR, TAG, "Invalid string uuid format, Please set the uuid as correct format");
226 OIC_LOG(ERROR, TAG, "e.g) \"72616E64-5069-6E44-6576-557569643030\" (4-2-2-2-6)");
227 OIC_LOG(ERROR, TAG, "e.g) \"\"");
229 return OC_STACK_INVALID_PARAM;
232 memcpy(uuid->id, convertedUuid, UUID_LENGTH);
237 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
238 OCStackResult SetDeviceIdSeed(const uint8_t* seed, size_t seedSize)
240 return SetDoxmDeviceIDSeed(seed, seedSize);
243 static OicSecOtmEventHandler_t gOtmEventHandler = NULL;
244 static char ptAddr[256] = {0};
245 static uint16_t ptPort = 0;
247 void SetOtmEventHandler(OicSecOtmEventHandler_t otmEventHandler)
249 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
251 memset(ptAddr, 0x00, sizeof(ptAddr));
253 gOtmEventHandler = otmEventHandler;
254 OIC_LOG_V(DEBUG, TAG, "Out%s", __func__);
258 * Function to handle the handshake result in OTM.
259 * This function will be invoked after DTLS handshake
260 * @param endPoint [IN] The remote endpoint.
261 * @param errorInfo [IN] Error information from the endpoint.
264 static void DTLSHandshakeServerCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
266 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
267 if(NULL != endpoint && NULL != info)
269 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
270 endpoint->addr, endpoint->port, info->result);
272 //We can't know about PT's secure port, so compare only adress to identify the PT.
273 if (strncmp(endpoint->addr, ptAddr, strlen(ptAddr)) == 0)
275 OIC_LOG_V(INFO, TAG, "Normal port is [%s:%d]", ptAddr, ptPort);
277 //If DTLS handshake error occurred, revert secure resource and notify error event to application.
278 if (CA_STATUS_OK != info->result)
280 OIC_LOG(ERROR, TAG, "Failed to establish a secure session with owner device.");
281 OIC_LOG(ERROR, TAG, "Doxm/Pstat resource will be reverted to init state.");
282 RestoreDoxmToInitState();
283 RestorePstatToInitState();
284 InvokeOtmEventHandler(endpoint->addr, endpoint->port, NULL, OIC_OTM_ERROR);
289 OIC_LOG_V(WARNING, TAG, "[%s:%d] is not a owner device", endpoint->addr, endpoint->port);
294 OIC_LOG(WARNING, TAG, "Invalid param.");
296 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
300 void InvokeOtmEventHandler(const char* addr, uint16_t port,
301 const OicUuid_t* uuid, OicSecOtmEvent_t event)
303 char* strUuid = NULL;
304 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
306 //addr can be NULL for init state
307 //port can be '0' for BLE and init state
308 //uuid can be NULL for init state & coap
313 case OIC_OTM_STARTED:
316 OICStrcpy(ptAddr, sizeof(ptAddr), addr);
321 memset(ptAddr, 0x00, sizeof(ptAddr));
324 //Register TLS event handler to catch the tls event while handshake
325 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(DTLSHandshakeServerCB))
327 OIC_LOG(WARNING, TAG, "Failed to register (D)TLS handshake callback.");
332 memset(ptAddr, 0x00, sizeof(ptAddr));
334 //Register TLS event handler to catch the tls event while handshake
335 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
337 OIC_LOG(WARNING, TAG, "Failed to register (D)TLS handshake callback.");
339 //Restore Pkix handler to initial state
340 CAregisterPkixInfoHandler(GetPkixInfo);
341 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
342 CAregisterPskCredentialsHandler(GetDtlsPskCredentials);
345 OIC_LOG_V(ERROR, TAG, "Unknow OTM event : %d", event);
351 if(OC_STACK_OK != ConvertUuidToStr(uuid, &strUuid))
353 OIC_LOG(ERROR, TAG, "Failed to convert UUID to String.");
358 OIC_LOG(DEBUG, TAG, "=================================");
359 OIC_LOG(DEBUG, TAG, "[OTM Event]");
360 OIC_LOG_V(DEBUG, TAG, "PT UUID : %s", (strUuid ? strUuid : "NULL"));
361 OIC_LOG_V(DEBUG, TAG, "PT Addr=%s:%d", (addr ? addr : "NULL"), port);
362 OIC_LOG_V(DEBUG, TAG, "Event Code=%d", event);
363 OIC_LOG(DEBUG, TAG, "=================================");
365 if (NULL == gOtmEventHandler)
367 OIC_LOG(WARNING, TAG, "OTM event handler is not registered.");
371 OIC_LOG(DEBUG, TAG, "Invoking callback to notify OTM state..");
372 gOtmEventHandler(addr, port, strUuid, (int)event);
379 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
382 const OicUuid_t THE_NIL_UUID = {.id={0000000000000000}};
385 * Compares two OicUuid_t structs.
387 * @return true if the two OicUuid_t structs are equal, else false.
389 bool UuidCmp(const OicUuid_t *firstId, const OicUuid_t *secondId)
392 VERIFY_NON_NULL(TAG, firstId, ERROR);
393 VERIFY_NON_NULL(TAG, secondId, ERROR);
395 if (0 == memcmp(firstId, secondId, sizeof(OicUuid_t)))
401 OIC_LOG_V(DEBUG, TAG, "%s: returning %s.", __func__, ret?"true":"false");
406 * Compares OicUuid_t to Nil UUID {.id={0000000000000000}}
408 * @return true if the OicUuid_t is the Nil UUID.
410 bool IsNilUuid(const OicUuid_t *uuid)
413 char *strUuid = NULL;
414 ConvertUuidToStr(uuid, &strUuid);
417 OIC_LOG_V(DEBUG, TAG, "%s: uuid: %s.", __func__, strUuid);
421 return UuidCmp(uuid, &THE_NIL_UUID);