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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #define __STDC_LIMIT_MACROS
24 #include "oic_malloc.h"
26 #include "resourcemanager.h"
27 #include "psinterface.h"
29 #include "srmresourcestrings.h"
30 #include "credresource.h"
32 #include "doxmresource.h"
34 #include "srmutility.h"
35 #include "cainterface.h"
45 #define TAG "SRM-CREDL"
48 static OicSecCred_t *gCred = NULL;
49 static OCResourceHandle gCredHandle = NULL;
52 * This function frees OicSecCred_t object's fields and object itself.
54 static void FreeCred(OicSecCred_t *cred)
58 OC_LOG (INFO, TAG, "Invalid Parameter");
61 //Note: Need further clarification on roleID data type
64 OICFree(cred->roleIds);
68 OICFree(cred->publicData.data);
71 OICFree(cred->privateData.data);
74 OICFree(cred->period);
77 OICFree(cred->owners);
79 //Clean Cred node itself
83 void DeleteCredList(OicSecCred_t* cred)
87 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
88 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
90 LL_DELETE(cred, credTmp1);
97 * This function converts credential data into JSON format.
98 * Caller needs to invoke 'free' when done using
100 * @param cred pointer to instance of OicSecCred_t structure.
103 * pointer to JSON credential representation - if credential for subjectId found
104 * NULL - if credential for subjectId not found
106 char * BinToCredJSON(const OicSecCred_t * cred)
108 cJSON *jsonRoot = NULL;
109 char *jsonStr = NULL;
113 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
115 B64Result b64Ret = B64_OK;
117 jsonRoot = cJSON_CreateObject();
118 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
120 cJSON *jsonCredArray = NULL;
121 cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
122 jsonCredArray = cJSON_CreateArray());
123 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
127 cJSON *jsonCred = cJSON_CreateObject();
128 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
130 //CredID -- Mandatory
131 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
133 //Subject -- Mandatory
135 memset(base64Buff, 0, sizeof(base64Buff));
136 b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
137 sizeof(base64Buff), &outLen);
138 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
139 cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECT_NAME, base64Buff);
141 //Note: Need further clarification on roleID data type
143 //RoleId -- Not Mandatory
144 if(cred->roleIdsLen > 0)
146 cJSON *jsonRoleIdsArray = NULL;
147 cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
148 jsonRoleIdsArray = cJSON_CreateArray());
149 VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
150 for (size_t i = 0; i < cred->roleIdsLen; i++)
152 cJSON_AddItemToArray (jsonRoleIdsArray,
153 cJSON_CreateString((char *)cred->roleIds[i].id));
158 //CredType -- Mandatory
159 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
162 //PublicData -- Not Mandatory
163 if(cred->publicData.data)
165 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
168 //PrivateData -- Not Mandatory
169 if(cred->privateData.data)
171 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
174 //Period -- Not Mandatory
177 cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
181 //Owners -- Mandatory
182 cJSON *jsonOwnrArray = NULL;
183 cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
184 jsonOwnrArray = cJSON_CreateArray());
185 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
186 for (size_t i = 0; i < cred->ownersLen; i++)
189 memset(base64Buff, 0, sizeof(base64Buff));
190 b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
191 base64Buff, sizeof(base64Buff), &outLen);
192 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
193 cJSON_AddItemToArray (jsonOwnrArray,
194 cJSON_CreateString((char *)(base64Buff)));
197 /* Attach current cred node to cred Array */
198 cJSON_AddItemToArray(jsonCredArray, jsonCred);
202 jsonStr = cJSON_PrintUnformatted(jsonRoot);
208 cJSON_Delete(jsonRoot);
214 * This internal method converts JSON cred into binary cred.
216 OicSecCred_t * JSONToCredBin(const char * jsonStr)
218 OCStackResult ret = OC_STACK_ERROR;
219 OicSecCred_t * headCred = NULL;
220 OicSecCred_t * prevCred = NULL;
221 cJSON *jsonCredArray = NULL;
223 cJSON *jsonRoot = cJSON_Parse(jsonStr);
224 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
226 jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
227 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
228 if (cJSON_Array == jsonCredArray->type)
230 int numCred = cJSON_GetArraySize(jsonCredArray);
233 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
235 B64Result b64Ret = B64_OK;
237 VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
240 cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
241 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
243 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
244 VERIFY_NON_NULL(TAG, cred, ERROR);
246 headCred = (headCred) ? headCred : cred;
249 prevCred->next = cred;
251 size_t jsonObjLen = 0;
252 cJSON *jsonObj = NULL;
254 //CredId -- Mandatory
255 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
258 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
259 cred->credId = jsonObj->valueint;
262 //subject -- Mandatory
263 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECT_NAME);
264 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
265 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
267 memset(base64Buff, 0, sizeof(base64Buff));
268 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
269 base64Buff, sizeof(base64Buff), &outLen);
270 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
272 memcpy(cred->subject.id, base64Buff, outLen);
274 //CredType -- Mandatory
275 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
276 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
277 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
278 cred->credType = jsonObj->valueint;
280 //PrivateData is mandatory for some of the credential types listed below.
281 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
282 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
283 (cred->credType & SYMMETRIC_GROUP_KEY) ||
284 (cred->credType & PIN_PASSWORD))
286 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
287 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
289 if(jsonObj && cJSON_String == jsonObj->type)
291 jsonObjLen = strlen(jsonObj->valuestring) + 1;
292 cred->privateData.data = (char *)OICMalloc(jsonObjLen);
293 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
294 strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
297 //Period -- Not Mandatory
298 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
299 if(jsonObj && cJSON_String == jsonObj->type)
301 jsonObjLen = strlen(jsonObj->valuestring) + 1;
302 cred->period = (char *)OICMalloc(jsonObjLen);
303 VERIFY_NON_NULL(TAG, cred->period, ERROR);
304 strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
307 //Owners -- Mandatory
308 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
309 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
310 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
311 cred->ownersLen = cJSON_GetArraySize(jsonObj);
312 VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
313 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
314 VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
315 for(size_t i = 0; i < cred->ownersLen; i++)
317 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
318 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
319 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
321 memset(base64Buff, 0, sizeof(base64Buff));
322 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
323 base64Buff, sizeof(base64Buff), &outLen);
324 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
325 outLen <= sizeof(cred->owners[i].id)), ERROR);
326 memcpy(cred->owners[i].id, base64Buff, outLen);
329 } while( ++idx < numCred);
335 cJSON_Delete(jsonRoot);
336 if (OC_STACK_OK != ret)
338 DeleteCredList(headCred);
345 * This function generates the bin credential data.
347 * @param subject pointer to subject of this credential.
348 * @param credType credential type.
349 * @param publicData public data such as public key.
350 * @param privateData private data such as private key.
351 * The privateData is expected in base64 encoded format.
352 * @param ownersLen length of owners array
353 * @param owners array of owners.
356 * pointer to instance of OicSecCred_t - success
359 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
360 const char * publicData, const char * privateData,
361 size_t ownersLen, const OicUuid_t * owners)
364 OCStackResult ret = OC_STACK_ERROR;
366 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
367 VERIFY_NON_NULL(TAG, cred, ERROR);
369 //CredId is assigned before appending new cred to the existing
370 //credential list and updating svr database in AddCredential().
373 VERIFY_NON_NULL(TAG, subject, ERROR);
374 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
376 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
377 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
378 cred->credType = credType;
383 cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
384 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
385 strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
391 cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
392 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
393 strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
396 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
397 cred->ownersLen = ownersLen;
399 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
400 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
401 for(size_t i = 0; i < cred->ownersLen; i++)
403 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
408 if (OC_STACK_OK != ret)
410 DeleteCredList(cred);
416 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
420 // Convert Cred data into JSON for update to persistent storage
421 char *jsonStr = BinToCredJSON(cred);
424 cJSON *jsonCred = cJSON_Parse(jsonStr);
428 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
432 cJSON_Delete(jsonCred );
434 else //Empty cred list
436 if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
445 * Compare function used LL_SORT for sorting credentials
447 * @param first pointer to OicSecCred_t struct
448 * @param second pointer to OicSecCred_t struct
451 * -1 if credId of first is less than credId of second
452 * 0 if credId of first is equal to credId of second
453 * 1 if credId of first is greater than credId of second
455 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
457 if(first->credId < second->credId)
461 else if(first->credId > second->credId)
470 * GetCredId goes through the cred list and returns the next
471 * available credId. The next credId could be the credId that is
472 * available due deletion of OicSecCred_t object or one more than
473 * credId of last credential in the list.
476 * next available credId - success
480 static uint16_t GetCredId()
482 //Sorts credential list in incremental order of credId
483 LL_SORT(gCred, CmpCredId);
486 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
487 uint16_t nextCredId = 1;
489 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
491 if(currentCred->credId == nextCredId)
501 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
510 * This function adds the new cred to the credential list.
512 * @param cred pointer to new credential.
515 * OC_STACK_OK - cred not NULL and persistent storage gets updated
516 * OC_STACK_ERROR - cred is NULL or fails to update persistent storage
518 OCStackResult AddCredential(OicSecCred_t * newCred)
520 OCStackResult ret = OC_STACK_ERROR;
522 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
524 //Assigning credId to the newCred
525 newCred->credId = GetCredId();
527 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
529 //Append the new Cred to existing list
530 LL_APPEND(gCred, newCred);
532 if(UpdatePersistentStorage(gCred))
541 OCStackResult RemoveCredential(const OicUuid_t *subject)
543 OCStackResult ret = OC_STACK_ERROR;
544 OicSecCred_t *cred = NULL;
545 OicSecCred_t *tempCred = NULL;
546 bool deleteFlag = false;
548 LL_FOREACH_SAFE(gCred, cred, tempCred)
550 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
552 LL_DELETE(gCred, cred);
560 if(UpdatePersistentStorage(gCred))
562 ret = OC_STACK_RESOURCE_DELETED;
569 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
571 OCEntityHandlerResult ret = OC_EH_ERROR;
573 //Get binary representation of json
574 OicSecCred_t * cred = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
578 //If the Post request credential has credId, it will be
579 //discarded and the next available credId will be assigned
580 //to it before getting appended to the existing credential
581 //list and updating svr database.
582 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
588 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
590 OC_LOG(INFO, TAG, "Processing CredDeleteRequest");
592 OCEntityHandlerResult ehRet = OC_EH_ERROR;
594 if(NULL == ehRequest->query)
599 OicParseQueryIter_t parseIter = {.attrPos=NULL};
600 OicUuid_t subject = {.id={0}};
602 //Parsing REST query to get the subject
603 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
604 while(GetNextQuery(&parseIter))
606 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
607 parseIter.attrLen) == 0)
609 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
611 B64Result b64Ret = B64_OK;
613 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
614 base64Buff, sizeof(base64Buff), &outLen);
616 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
617 memcpy(subject.id, base64Buff, outLen);
621 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
623 ehRet = OC_EH_RESOURCE_DELETED;
632 * This internal method is the entity handler for Cred resources
633 * to handle REST request (PUT/POST/DEL)
635 OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
636 OCEntityHandlerRequest * ehRequest,
637 void* callbackParameter)
639 (void)callbackParameter;
640 OCEntityHandlerResult ret = OC_EH_ERROR;
646 if (flag & OC_REQUEST_FLAG)
648 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
649 //TODO : Handle PUT/DEL methods
650 switch(ehRequest->method)
653 ret = OC_EH_FORBIDDEN;
656 ret = HandlePostRequest(ehRequest);
659 ret = HandleDeleteRequest(ehRequest);
667 //Send payload to request originator
668 ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
675 * This internal method is used to create '/oic/sec/Cred' resource.
677 OCStackResult CreateCredResource()
681 ret = OCCreateResource(&gCredHandle,
682 OIC_RSRC_TYPE_SEC_CRED,
689 if (OC_STACK_OK != ret)
691 OC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
692 DeInitCredResource();
698 * Get the default value
699 * @retval NULL for now. Update it when we finalize the default info.
701 static OicSecCred_t* GetCredDefault()
707 * Initialize Cred resource by loading data from persistent storage.
710 * OC_STACK_OK - no errors
711 * OC_STACK_ERROR - stack process error
713 OCStackResult InitCredResource()
715 OCStackResult ret = OC_STACK_ERROR;
717 //Read Cred resource from PS
718 char* jsonSVRDatabase = GetSVRDatabase();
722 //Convert JSON Cred into binary format
723 gCred = JSONToCredBin(jsonSVRDatabase);
726 * If SVR database in persistent storage got corrupted or
727 * is not available for some reason, a default Cred is created
728 * which allows user to initiate Cred provisioning again.
730 if (!jsonSVRDatabase || !gCred)
732 gCred = GetCredDefault();
734 //Instantiate 'oic.sec.cred'
735 ret = CreateCredResource();
736 OICFree(jsonSVRDatabase);
741 * Perform cleanup for Cred resources.
744 * OC_STACK_OK - no errors
745 * OC_STACK_ERROR - stack process error
746 * OC_STACK_NO_RESOURCE - resource not found
747 * OC_STACK_INVALID_PARAM - invalid param
749 OCStackResult DeInitCredResource()
751 OCStackResult result = OCDeleteResource(gCredHandle);
752 DeleteCredList(gCred);
758 * This method is used by tinydtls/SRM to retrieve credential for given Subject.
760 * @param subject - subject for which credential is required.
763 * reference to OicSecCred_t - if credential is found
764 * NULL - if credential not found
766 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
768 OicSecCred_t *cred = NULL;
770 if ( NULL == subject)
775 LL_FOREACH(gCred, cred)
777 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
786 #if defined(__WITH_DTLS__)
788 * This internal callback is used by lower stack (i.e. CA layer) to
789 * retrieve PSK credentials from RI security layer.
791 * Note: When finished, caller should initialize memory to zeros and
792 * invoke OICFree to delete @p credInfo.
795 * binary blob containing PSK credentials
799 void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
801 CADtlsPskCredsBlob_t * caBlob = NULL;
804 caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
807 OicUuid_t deviceID = {.id={}};
809 // Retrieve Device ID from doxm resource and copy in PSK creds blob
810 VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
811 memcpy(caBlob->identity, deviceID.id, sizeof(caBlob->identity));
813 OicSecCred_t *cred = NULL;
815 LL_FOREACH(gCred, cred)
817 // Currently, Iotivity supports only symmetric pair wise key credentials
818 if (cred->credType == SYMMETRIC_PAIR_WISE_KEY)
827 (OCDtlsPskCreds*) OICMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
828 VERIFY_NON_NULL(TAG, caBlob->creds, ERROR);
831 LL_FOREACH(gCred, cred)
833 if ((cred->credType == SYMMETRIC_PAIR_WISE_KEY) &&
838 memcpy(caBlob->creds[i].id, cred->subject.id,
839 sizeof(caBlob->creds[i].id));
841 // Convert PSK from JSON to binary before copying
843 B64Result b64Ret = b64Decode(cred->privateData.data,
844 strlen(cred->privateData.data), caBlob->creds[i].psk,
845 sizeof(caBlob->creds[i].psk), &outLen);
846 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
853 // Return from here after making the credential list
860 memset(caBlob->creds, 0, caBlob->num * sizeof(OCDtlsPskCreds));
861 OICFree(caBlob->creds);
867 * Add temporal PSK to PIN based OxM
869 * @param[in] tmpSubject UUID of target device
870 * @param[in] credType Type of credential to be added
871 * @param[in] pin numeric characters
872 * @param[in] pinSize length of 'pin'
873 * @param[in] ownersLen Number of owners
874 * @param[in] owners Array of owners
875 * @param[out] tmpCredSubject Generated credential's subject.
877 * @return OC_STACK_OK for success and errorcode otherwise.
879 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
880 const char * pin, size_t pinSize,
881 size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
883 OCStackResult ret = OC_STACK_ERROR;
885 if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
887 return OC_STACK_INVALID_PARAM;
890 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
891 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
892 UUID_LENGTH, PBKDF_ITERATIONS,
893 OWNER_PSK_LENGTH_128, privData);
894 VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
897 char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
898 B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
899 sizeof(base64Buff), &outLen);
900 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
902 OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
903 base64Buff, ownersLen, owners);
906 OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
907 return OC_STACK_ERROR;
910 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
912 ret = AddCredential(cred);
913 if( OC_STACK_OK != ret)
915 OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
922 #endif /* __WITH_DTLS__ */