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
32 #include "cainterface.h"
33 #include "payload_logging.h"
37 #include "ocserverrequest.h"
38 #include "oic_malloc.h"
39 #include "ocpayload.h"
41 #include "credresource.h"
42 #include "doxmresource.h"
43 #include "pstatresource.h"
44 #include "iotvticalendar.h"
46 #include "resourcemanager.h"
47 #include "srmresourcestrings.h"
48 #include "srmutility.h"
49 #include "psinterface.h"
50 #include "pinoxmcommon.h"
56 #define TAG "SRM-CREDL"
58 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
59 * The value of payload size is increased until reaching belox max cbor size. */
60 static const uint16_t CBOR_SIZE = 2048;
62 /** Max cbor size payload. */
63 static const uint16_t CBOR_MAX_SIZE = 4400;
65 /** CRED size - Number of mandatory items. */
66 static const uint8_t CRED_ROOT_MAP_SIZE = 4;
67 static const uint8_t CRED_MAP_SIZE = 3;
70 static OicSecCred_t *gCred = NULL;
71 static OCResourceHandle gCredHandle = NULL;
74 * This function frees OicSecCred_t object's fields and object itself.
76 static void FreeCred(OicSecCred_t *cred)
80 OIC_LOG(ERROR, TAG, "Invalid Parameter");
83 //Note: Need further clarification on roleID data type
86 OICFree(cred->roleIds);
89 //Clean PublicData/OptionalData/Credusage
90 #if defined(__WITH_X509__) || defined(__WITH_TLS__)
91 // TODO: Need to check credUsage.
92 OICFree(cred->publicData.data);
93 OICFree(cred->optionalData.data);
94 OICFree(cred->credUsage);
96 #endif /* __WITH_X509__ || __WITH_TLS__*/
99 OICFree(cred->privateData.data);
102 OICFree(cred->period);
104 //Clean Cred node itself
108 void DeleteCredList(OicSecCred_t* cred)
112 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
113 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
115 LL_DELETE(cred, credTmp1);
121 static size_t OicSecCredCount(const OicSecCred_t *secCred)
124 for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
131 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
132 size_t *cborSize, int secureFlag)
134 if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
136 return OC_STACK_INVALID_PARAM;
139 OCStackResult ret = OC_STACK_ERROR;
141 CborError cborEncoderResult = CborNoError;
142 uint8_t *outPayload = NULL;
143 size_t cborLen = *cborSize;
146 const OicSecCred_t *cred = credS;
148 CborEncoder credArray;
149 CborEncoder credRootMap;
156 outPayload = (uint8_t *)OICCalloc(1, cborLen);
157 VERIFY_NON_NULL(TAG, outPayload, ERROR);
158 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
160 // Create CRED Root Map (creds, rownerid)
161 cborEncoderResult = cbor_encoder_create_map(&encoder, &credRootMap, CRED_ROOT_MAP_SIZE);
162 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Root Map");
165 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_CREDS_NAME,
166 strlen(OIC_JSON_CREDS_NAME));
167 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding creds Name Tag.");
170 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &credArray, OicSecCredCount(cred));
171 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Array.");
176 size_t mapSize = CRED_MAP_SIZE;
182 #if defined(__WITH_X509__) || defined(__WITH_TLS__)
183 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
187 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
195 #endif /* __WITH_X509__ || __WITH_TLS__*/
196 if (!secureFlag && cred->privateData.data)
200 cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
201 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");
203 //CredID -- Mandatory
204 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
205 strlen(OIC_JSON_CREDID_NAME));
206 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
207 cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
210 //Subject -- Mandatory
211 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECTID_NAME,
212 strlen(OIC_JSON_SUBJECTID_NAME));
213 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
214 inLen = (memcmp(&(cred->subject), &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN) == 0) ?
215 WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t);
216 if(inLen == WILDCARD_SUBJECT_ID_LEN)
218 cborEncoderResult = cbor_encode_text_string(&credMap, WILDCARD_RESOURCE_URI,
219 strlen(WILDCARD_RESOURCE_URI));
220 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value.");
224 char *subject = NULL;
225 ret = ConvertUuidToStr(&cred->subject, &subject);
226 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
227 cborEncoderResult = cbor_encode_text_string(&credMap, subject, strlen(subject));
228 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
232 //CredType -- Mandatory
233 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
234 strlen(OIC_JSON_CREDTYPE_NAME));
235 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
236 cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
237 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
239 #if defined(__WITH_X509__) || defined(__WITH_TLS__)
240 //PublicData -- Not Mandatory
241 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
243 CborEncoder publicMap;
244 const size_t publicMapSize = 2;
246 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PUBLICDATA_NAME,
247 strlen(OIC_JSON_PUBLICDATA_NAME));
248 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Tag.");
250 cborEncoderResult = cbor_encoder_create_map(&credMap, &publicMap, publicMapSize);
251 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Map");
253 cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_DATA_NAME,
254 strlen(OIC_JSON_DATA_NAME));
255 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Data Tag.");
256 cborEncoderResult = cbor_encode_byte_string(&publicMap, cred->publicData.data,
257 cred->publicData.len);
258 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Value.");
260 // TODO: Need to data strucure modification for OicSecCert_t.
261 cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_ENCODING_NAME,
262 strlen(OIC_JSON_ENCODING_NAME));
263 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Tag.");
264 cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_SEC_ENCODING_RAW,
265 strlen(OIC_SEC_ENCODING_RAW));
266 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Value.");
268 cborEncoderResult = cbor_encoder_close_container(&credMap, &publicMap);
269 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PublicData Map.");
271 //OptionalData -- Not Mandatory
272 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
274 CborEncoder optionalMap;
275 const size_t optionalMapSize = 2;
277 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_OPTDATA_NAME,
278 strlen(OIC_JSON_OPTDATA_NAME));
279 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OptionalData Tag.");
281 cborEncoderResult = cbor_encoder_create_map(&credMap, &optionalMap, optionalMapSize);
282 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OptionalData Map");
284 // TODO: Need to data strucure modification for OicSecCert_t.
285 if(OIC_ENCODING_RAW == cred->optionalData.encoding)
287 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_ENCODING_NAME,
288 strlen(OIC_JSON_ENCODING_NAME));
289 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Tag.");
290 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_SEC_ENCODING_RAW,
291 strlen(OIC_SEC_ENCODING_RAW));
292 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Value.");
294 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_DATA_NAME,
295 strlen(OIC_JSON_DATA_NAME));
296 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Tag.");
297 cborEncoderResult = cbor_encode_byte_string(&optionalMap, cred->optionalData.data,
298 cred->optionalData.len);
299 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Value.");
301 else if(OIC_ENCODING_BASE64 == cred->optionalData.encoding)
303 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_ENCODING_NAME,
304 strlen(OIC_JSON_ENCODING_NAME));
305 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Tag.");
306 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_SEC_ENCODING_BASE64,
307 strlen(OIC_SEC_ENCODING_BASE64));
308 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Value.");
310 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_DATA_NAME,
311 strlen(OIC_JSON_DATA_NAME));
312 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Tag.");
313 cborEncoderResult = cbor_encode_text_string(&optionalMap, (char*)(cred->optionalData.data),
314 cred->optionalData.len);
315 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Value.");
317 else if(OIC_ENCODING_PEM == cred->optionalData.encoding)
319 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_ENCODING_NAME,
320 strlen(OIC_JSON_ENCODING_NAME));
321 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Tag.");
322 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_SEC_ENCODING_PEM,
323 strlen(OIC_SEC_ENCODING_PEM));
324 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Value.");
326 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_DATA_NAME,
327 strlen(OIC_JSON_DATA_NAME));
328 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Tag.");
329 cborEncoderResult = cbor_encode_text_string(&optionalMap, (char*)(cred->optionalData.data),
330 cred->optionalData.len);
331 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Value.");
333 else if(OIC_ENCODING_DER == cred->optionalData.encoding)
335 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_ENCODING_NAME,
336 strlen(OIC_JSON_ENCODING_NAME));
337 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Tag.");
338 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_SEC_ENCODING_DER,
339 strlen(OIC_SEC_ENCODING_DER));
340 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Encoding Value.");
342 cborEncoderResult = cbor_encode_text_string(&optionalMap, OIC_JSON_DATA_NAME,
343 strlen(OIC_JSON_DATA_NAME));
344 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Tag.");
345 cborEncoderResult = cbor_encode_byte_string(&optionalMap, cred->optionalData.data,
346 cred->optionalData.len);
347 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding optional Value.");
351 OIC_LOG(ERROR, TAG, "Unknow encoding type for optional data.");
352 VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding optional Encoding Value.");
355 cborEncoderResult = cbor_encoder_close_container(&credMap, &optionalMap);
356 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing OptionalData Map.");
358 //CredUsage -- Not Mandatory
361 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDUSAGE_NAME,
362 strlen(OIC_JSON_CREDUSAGE_NAME));
363 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Credusage Name Tag.");
364 cborEncoderResult = cbor_encode_text_string(&credMap, cred->credUsage,
365 strlen(cred->credUsage));
366 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Credusage Name Value.");
368 #endif /* __WITH_X509__ || __WITH_TLS__*/
369 //PrivateData -- Not Mandatory
370 if(!secureFlag && cred->privateData.data)
372 CborEncoder privateMap;
373 const size_t privateMapSize = 2;
375 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PRIVATEDATA_NAME,
376 strlen(OIC_JSON_PRIVATEDATA_NAME));
377 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
379 cborEncoderResult = cbor_encoder_create_map(&credMap, &privateMap, privateMapSize);
380 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Map");
382 // TODO: Need to data strucure modification for OicSecKey_t.
383 // TODO: Added as workaround, will be replaced soon.
384 if(OIC_ENCODING_RAW == cred->privateData.encoding)
386 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
387 strlen(OIC_JSON_ENCODING_NAME));
388 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
389 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_RAW,
390 strlen(OIC_SEC_ENCODING_RAW));
391 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
393 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
394 strlen(OIC_JSON_DATA_NAME));
395 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
396 cborEncoderResult = cbor_encode_byte_string(&privateMap, cred->privateData.data,
397 cred->privateData.len);
398 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
400 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
402 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
403 strlen(OIC_JSON_ENCODING_NAME));
404 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
405 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_BASE64,
406 strlen(OIC_SEC_ENCODING_BASE64));
407 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
409 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
410 strlen(OIC_JSON_DATA_NAME));
411 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
412 cborEncoderResult = cbor_encode_text_string(&privateMap, (char*)(cred->privateData.data),
413 cred->privateData.len);
414 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
418 OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
419 VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding Private Encoding Value.");
422 cborEncoderResult = cbor_encoder_close_container(&credMap, &privateMap);
423 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PrivateData Map.");
426 //Period -- Not Mandatory
429 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
430 strlen(OIC_JSON_PERIOD_NAME));
431 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
432 cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
433 strlen(cred->period));
434 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
438 cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
439 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
443 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
444 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
451 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
452 strlen(OIC_JSON_ROWNERID_NAME));
453 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
454 ret = ConvertUuidToStr(&cred->rownerID, &rowner);
455 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
456 cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
457 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
463 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_RT_NAME,
464 strlen(OIC_JSON_RT_NAME));
465 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
466 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &rtArray, 1);
467 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
468 for (size_t i = 0; i < 1; i++)
470 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_CRED,
471 strlen(OIC_RSRC_TYPE_SEC_CRED));
472 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
474 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &rtArray);
475 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
479 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_IF_NAME,
480 strlen(OIC_JSON_IF_NAME));
481 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
482 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &ifArray, 1);
483 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
484 for (size_t i = 0; i < 1; i++)
486 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
487 strlen(OC_RSRVD_INTERFACE_DEFAULT));
488 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
490 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &ifArray);
491 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
494 // Close CRED Root Map
495 cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
496 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");
498 if (CborNoError == cborEncoderResult)
500 OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
501 *cborPayload = outPayload;
502 *cborSize = encoder.ptr - outPayload;
505 OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
507 if (CborErrorOutOfMemory == cborEncoderResult)
509 OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
510 // reallocate and try again!
512 // Since the allocated initial memory failed, double the memory.
513 cborLen += encoder.ptr - encoder.end;
514 cborEncoderResult = CborNoError;
515 ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
519 if (CborNoError != cborEncoderResult)
521 OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
526 ret = OC_STACK_ERROR;
532 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
533 OicSecCred_t **secCred)
535 if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
537 return OC_STACK_INVALID_PARAM;
540 OCStackResult ret = OC_STACK_ERROR;
541 CborValue credCbor = { .parser = NULL };
542 CborParser parser = { .end = NULL };
543 CborError cborFindResult = CborNoError;
544 cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
546 OicSecCred_t *headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
548 // Enter CRED Root Map
549 CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
550 cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
551 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering CRED Root Map.");
553 while (cbor_value_is_valid(&CredRootMap))
555 char* tagName = NULL;
557 CborType type = cbor_value_get_type(&CredRootMap);
558 if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
560 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
561 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
562 cborFindResult = cbor_value_advance(&CredRootMap);
563 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
567 if (strcmp(tagName, OIC_JSON_CREDS_NAME) == 0)
572 CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
573 cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
574 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
576 while (cbor_value_is_valid(&credArray))
579 //CredId -- Mandatory
580 CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
581 cborFindResult = cbor_value_enter_container(&credArray, &credMap);
582 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
583 OicSecCred_t *cred = NULL;
591 cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
592 OicSecCred_t *temp = headCred;
600 VERIFY_NON_NULL(TAG, cred, ERROR);
602 while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
605 CborType type = cbor_value_get_type(&credMap);
606 if (type == CborTextStringType)
608 cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
609 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
610 cborFindResult = cbor_value_advance(&credMap);
611 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
616 if (strcmp(name, OIC_JSON_CREDID_NAME) == 0)
619 cborFindResult = cbor_value_get_uint64(&credMap, &credId);
620 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredId.");
621 cred->credId = (uint16_t)credId;
624 if (strcmp(name, OIC_JSON_SUBJECTID_NAME) == 0)
626 char *subjectid = NULL;
627 cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &len, NULL);
628 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subjectid Value.");
629 if(strcmp(subjectid, WILDCARD_RESOURCE_URI) == 0)
631 cred->subject.id[0] = '*';
635 ret = ConvertStrToUuid(subjectid, &cred->subject);
636 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
641 if (strcmp(name, OIC_JSON_CREDTYPE_NAME) == 0)
643 uint64_t credType = 0;
644 cborFindResult = cbor_value_get_uint64(&credMap, &credType);
645 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredType.");
646 cred->credType = (OicSecCredType_t)credType;
649 if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME) == 0)
651 CborValue privateMap = { .parser = NULL };
652 cborFindResult = cbor_value_enter_container(&credMap, &privateMap);
654 while (cbor_value_is_valid(&privateMap))
656 char* privname = NULL;
657 CborType type = cbor_value_get_type(&privateMap);
658 if (type == CborTextStringType && cbor_value_is_text_string(&privateMap))
660 cborFindResult = cbor_value_dup_text_string(&privateMap, &privname,
662 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
663 cborFindResult = cbor_value_advance(&privateMap);
664 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
668 // PrivateData::privdata -- Mandatory
669 if (strcmp(privname, OIC_JSON_DATA_NAME) == 0)
671 if(cbor_value_is_byte_string(&privateMap))
673 cborFindResult = cbor_value_dup_byte_string(&privateMap, &cred->privateData.data,
674 &cred->privateData.len, NULL);
676 else if(cbor_value_is_text_string(&privateMap))
678 cborFindResult = cbor_value_dup_text_string(&privateMap, (char**)(&cred->privateData.data),
679 &cred->privateData.len, NULL);
683 cborFindResult = CborErrorUnknownType;
684 OIC_LOG(ERROR, TAG, "Unknow type for private data.");
686 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PrivateData.");
689 // PrivateData::encoding -- Mandatory
690 if (strcmp(privname, OIC_JSON_ENCODING_NAME) == 0)
692 // TODO: Added as workaround. Will be replaced soon.
693 char* strEncoding = NULL;
694 cborFindResult = cbor_value_dup_text_string(&privateMap, &strEncoding, &len, NULL);
695 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding EncodingType");
697 if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
699 cred->privateData.encoding = OIC_ENCODING_RAW;
701 else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
703 cred->privateData.encoding = OIC_ENCODING_BASE64;
708 cred->privateData.encoding = OIC_ENCODING_RAW;
709 OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for private data.");
712 OICFree(strEncoding);
715 if (cbor_value_is_valid(&privateMap))
717 cborFindResult = cbor_value_advance(&privateMap);
718 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing privatedata Map.");
724 #if defined(__WITH_X509__) || defined(__WITH_TLS__)
725 //PublicData -- Not Mandatory
726 if (strcmp(name, OIC_JSON_PUBLICDATA_NAME) == 0)
728 CborValue pubMap = { .parser = NULL };
729 cborFindResult = cbor_value_enter_container(&credMap, &pubMap);
731 while (cbor_value_is_valid(&pubMap))
733 char* pubname = NULL;
734 CborType type = cbor_value_get_type(&pubMap);
735 if (type == CborTextStringType && cbor_value_is_text_string(&pubMap))
737 cborFindResult = cbor_value_dup_text_string(&pubMap, &pubname,
739 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
740 cborFindResult = cbor_value_advance(&pubMap);
741 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
745 // PrivateData::privdata -- Mandatory
746 if (strcmp(pubname, OIC_JSON_DATA_NAME) == 0 && cbor_value_is_byte_string(&pubMap))
748 cborFindResult = cbor_value_dup_byte_string(&pubMap, &cred->publicData.data,
749 &cred->publicData.len, NULL);
750 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PubData.");
752 // PublicData::encoding -- Mandatory
753 if (strcmp(pubname, OIC_JSON_ENCODING_NAME) == 0)
755 // TODO: Need to update data structure, just ignore encoding value now.
758 if (cbor_value_is_valid(&pubMap))
760 cborFindResult = cbor_value_advance(&pubMap);
761 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing publicdata Map.");
766 //OptionalData -- Not Mandatory
767 if (strcmp(name, OIC_JSON_OPTDATA_NAME) == 0)
769 CborValue optMap = { .parser = NULL };
770 cborFindResult = cbor_value_enter_container(&credMap, &optMap);
772 while (cbor_value_is_valid(&optMap))
774 char* optname = NULL;
775 CborType type = cbor_value_get_type(&optMap);
776 if (type == CborTextStringType && cbor_value_is_text_string(&optMap))
778 cborFindResult = cbor_value_dup_text_string(&optMap, &optname,
780 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
781 cborFindResult = cbor_value_advance(&optMap);
782 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
786 // OptionalData::optdata -- Mandatory
787 if (strcmp(optname, OIC_JSON_DATA_NAME) == 0)
789 if(cbor_value_is_byte_string(&optMap))
791 cborFindResult = cbor_value_dup_byte_string(&optMap, &cred->optionalData.data,
792 &cred->optionalData.len, NULL);
794 else if(cbor_value_is_text_string(&optMap))
796 cborFindResult = cbor_value_dup_text_string(&optMap, (char**)(&cred->optionalData.data),
797 &cred->optionalData.len, NULL);
801 cborFindResult = CborErrorUnknownType;
802 OIC_LOG(ERROR, TAG, "Unknow type for optional data.");
804 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OptionalData.");
806 // OptionalData::encoding -- Mandatory
807 if (strcmp(optname, OIC_JSON_ENCODING_NAME) == 0)
809 // TODO: Added as workaround. Will be replaced soon.
810 char* strEncoding = NULL;
811 cborFindResult = cbor_value_dup_text_string(&optMap, &strEncoding, &len, NULL);
812 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding EncodingType");
814 if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
816 OIC_LOG(INFO,TAG,"cbor_value_is_byte_string");
817 cred->optionalData.encoding = OIC_ENCODING_RAW;
819 else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
821 cred->optionalData.encoding = OIC_ENCODING_BASE64;
823 else if(strcmp(strEncoding, OIC_SEC_ENCODING_PEM) == 0)
825 cred->optionalData.encoding = OIC_ENCODING_PEM;
827 else if(strcmp(strEncoding, OIC_SEC_ENCODING_DER) == 0)
829 cred->optionalData.encoding = OIC_ENCODING_DER;
834 cred->optionalData.encoding = OIC_ENCODING_RAW;
835 OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for optional data.");
837 OICFree(strEncoding);
840 if (cbor_value_is_valid(&optMap))
842 cborFindResult = cbor_value_advance(&optMap);
843 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing optdata Map.");
848 //Credusage -- Not Mandatory
849 if (0 == strcmp(OIC_JSON_CREDUSAGE_NAME, name))
851 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->credUsage, &len, NULL);
852 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
854 #endif //__WITH_X509__ || __WITH_TLS__
856 if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
858 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &len, NULL);
859 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
862 if (cbor_value_is_valid(&credMap))
864 cborFindResult = cbor_value_advance(&credMap);
865 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Map.");
871 if (cbor_value_is_valid(&credArray))
873 cborFindResult = cbor_value_advance(&credArray);
874 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Array.");
879 //ROwner -- Mandatory
880 if (strcmp(tagName, OIC_JSON_ROWNERID_NAME) == 0 && cbor_value_is_text_string(&CredRootMap))
882 char *stRowner = NULL;
883 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
884 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
886 ret = ConvertStrToUuid(stRowner, &headCred->rownerID);
887 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
892 if (cbor_value_is_valid(&CredRootMap))
894 cborFindResult = cbor_value_advance(&CredRootMap);
895 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
903 if (CborNoError != cborFindResult)
905 DeleteCredList(headCred);
908 ret = OC_STACK_ERROR;
914 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
915 const OicSecCert_t * publicData, const OicSecKey_t* privateData,
916 const OicUuid_t * rownerID)
919 OCStackResult ret = OC_STACK_ERROR;
921 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
922 VERIFY_NON_NULL(TAG, cred, ERROR);
924 //CredId is assigned before appending new cred to the existing
925 //credential list and updating svr database in AddCredential().
928 VERIFY_NON_NULL(TAG, subject, ERROR);
929 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
931 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
932 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
933 cred->credType = credType;
936 if (publicData && publicData->data)
938 cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
939 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
940 memcpy(cred->publicData.data, publicData->data, publicData->len);
941 cred->publicData.len = publicData->len;
943 #endif // __WITH_X509__
945 if (privateData && privateData->data)
947 cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
948 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
949 memcpy(cred->privateData.data, privateData->data, privateData->len);
950 cred->privateData.len = privateData->len;
952 // TODO: Added as workaround. Will be replaced soon.
953 cred->privateData.encoding = OIC_ENCODING_RAW;
956 // NOTE: Test codes to use base64 for credential.
957 uint32_t outSize = 0;
958 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((privateData->len + 1));
959 char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
960 VERIFY_NON_NULL(TAG, b64Buf, ERROR);
961 b64Encode(privateData->data, privateData->len, b64Buf, b64BufSize, &outSize);
963 OICFree( cred->privateData.data );
964 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
965 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
967 strcpy(cred->privateData.data, b64Buf);
968 cred->privateData.encoding = OIC_ENCODING_BASE64;
969 cred->privateData.len = outSize;
971 #endif //End of Test codes
975 VERIFY_NON_NULL(TAG, rownerID, ERROR);
976 memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
980 if (OC_STACK_OK != ret)
982 DeleteCredList(cred);
988 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
992 // Convert Cred data into JSON for update to persistent storage
995 uint8_t *payload = NULL;
998 OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
999 if ((OC_STACK_OK == res) && payload)
1001 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
1008 else //Empty cred list
1010 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
1019 * Compare function used LL_SORT for sorting credentials.
1021 * @param first pointer to OicSecCred_t struct.
1022 * @param second pointer to OicSecCred_t struct.
1024 *@return -1, if credId of first is less than credId of second.
1025 * 0, if credId of first is equal to credId of second.
1026 * 1, if credId of first is greater than credId of second.
1028 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
1030 if (first->credId < second->credId)
1034 else if (first->credId > second->credId)
1043 * GetCredId goes through the cred list and returns the next
1044 * available credId. The next credId could be the credId that is
1045 * available due deletion of OicSecCred_t object or one more than
1046 * credId of last credential in the list.
1048 * @return next available credId if successful, else 0 for error.
1050 static uint16_t GetCredId()
1052 //Sorts credential list in incremental order of credId
1053 LL_SORT(gCred, CmpCredId);
1055 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
1056 uint16_t nextCredId = 1;
1058 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
1060 if (currentCred->credId == nextCredId)
1070 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
1078 * Get the default value.
1080 * @return NULL for now.
1082 static OicSecCred_t* GetCredDefault()
1084 // TODO:Update it when we finalize the default info.
1088 OCStackResult AddCredential(OicSecCred_t * newCred)
1090 OCStackResult ret = OC_STACK_ERROR;
1091 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
1093 //Assigning credId to the newCred
1094 newCred->credId = GetCredId();
1095 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
1097 //Append the new Cred to existing list
1098 LL_APPEND(gCred, newCred);
1100 if (UpdatePersistentStorage(gCred))
1109 OCStackResult RemoveCredential(const OicUuid_t *subject)
1111 OCStackResult ret = OC_STACK_ERROR;
1112 OicSecCred_t *cred = NULL;
1113 OicSecCred_t *tempCred = NULL;
1114 bool deleteFlag = false;
1116 LL_FOREACH_SAFE(gCred, cred, tempCred)
1118 if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1120 LL_DELETE(gCred, cred);
1128 if (UpdatePersistentStorage(gCred))
1130 ret = OC_STACK_RESOURCE_DELETED;
1138 * Remove all credential data on credential resource and persistent storage
1141 * OC_STACK_OK - no errors
1142 * OC_STACK_ERROR - stack process error
1144 OCStackResult RemoveAllCredentials(void)
1146 DeleteCredList(gCred);
1147 gCred = GetCredDefault();
1149 if (!UpdatePersistentStorage(gCred))
1151 return OC_STACK_ERROR;
1156 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1158 * Internal function to fill private data of owner PSK.
1160 * @param receviedCred recevied owner credential from OBT(PT)
1161 * @param ownerAdd address of OBT(PT)
1162 * @param doxm current device's doxm resource
1165 * true successfully done and valid ower psk information
1166 * false Invalid owner psk information or failed to owner psk generation
1168 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
1169 const OicSecDoxm_t* doxm)
1171 //Derive OwnerPSK locally
1172 const char* oxmLabel = GetOxmString(doxm->oxmSel);
1173 VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
1175 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
1176 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
1177 (uint8_t*)oxmLabel, strlen(oxmLabel),
1178 doxm->owner.id, sizeof(doxm->owner.id),
1179 doxm->deviceID.id, sizeof(doxm->deviceID.id),
1180 ownerPSK, OWNER_PSK_LENGTH_128);
1181 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
1183 OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
1184 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
1186 //Generate owner credential based on recevied credential information
1188 // TODO: Added as workaround, will be replaced soon.
1189 if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
1191 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
1192 VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
1193 receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
1194 memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
1196 else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
1198 uint32_t b64OutSize = 0;
1199 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
1200 char* b64Buf = OICCalloc(1, b64BufSize);
1201 VERIFY_NON_NULL(TAG, b64Buf, ERROR);
1203 b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);
1205 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
1206 VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
1207 receviedCred->privateData.len = b64OutSize;
1208 strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
1209 receviedCred->privateData.data[b64OutSize] = '\0';
1214 VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
1217 OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
1219 //Verify OwnerPSK information
1220 return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
1221 receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
1223 //receviedCred->privateData.data will be deallocated when deleting credential.
1227 #endif //__WITH_DTLS__
1229 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
1231 OCEntityHandlerResult ret = OC_EH_ERROR;
1232 OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest IN");
1234 static uint16_t previousMsgId = 0;
1235 //Get binary representation of cbor
1236 OicSecCred_t *cred = NULL;
1237 uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
1238 size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
1240 OCStackResult res = CBORPayloadToCred(payload, size, &cred);
1241 if (res == OC_STACK_OK)
1243 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1244 OicUuid_t emptyUuid = {.id={0}};
1245 const OicSecDoxm_t* doxm = GetDoxmResourceData();
1246 if(doxm && false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
1248 //in case of owner PSK
1249 switch(cred->credType)
1251 case SYMMETRIC_PAIR_WISE_KEY:
1253 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
1254 if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
1256 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
1258 OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
1261 OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
1262 if(OC_STACK_OK == AddCredential(cred))
1264 ret = OC_EH_CHANGED;
1268 OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
1274 OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
1278 if(OC_EH_CHANGED == ret)
1281 * in case of random PIN based OxM,
1282 * revert get_psk_info callback of tinyDTLS to use owner credential.
1284 if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
1286 OicUuid_t emptyUuid = { .id={0}};
1287 SetUuidForRandomPinOxm(&emptyUuid);
1290 if(CA_STATUS_OK != CAregisterTlsCredentialsHandler(GetDtlsPskCredentials))
1292 OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
1297 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
1299 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
1305 //Select cipher suite to use owner PSK
1306 if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
1308 OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
1313 OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
1317 CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter))
1319 OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
1326 case SYMMETRIC_GROUP_KEY:
1327 case ASYMMETRIC_KEY:
1328 case SIGNED_ASYMMETRIC_KEY:
1330 case ASYMMETRIC_ENCRYPTION_KEY:
1332 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
1338 OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
1344 if(OC_EH_CHANGED != ret)
1347 * If some error is occured while ownership transfer,
1348 * ownership transfer related resource should be revert back to initial status.
1350 const OicSecDoxm_t* doxm = GetDoxmResourceData();
1353 if(!doxm->owned && previousMsgId != ehRequest->messageID)
1355 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
1356 "DOXM will be reverted.");
1357 RestoreDoxmToInitState();
1358 RestorePstatToInitState();
1363 OIC_LOG(ERROR, TAG, "Invalid DOXM resource");
1370 * If the post request credential has credId, it will be
1371 * discarded and the next available credId will be assigned
1372 * to it before getting appended to the existing credential
1373 * list and updating svr database.
1375 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
1377 #else //not __WITH_DTLS__
1379 * If the post request credential has credId, it will be
1380 * discarded and the next available credId will be assigned
1381 * to it before getting appended to the existing credential
1382 * list and updating svr database.
1384 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
1385 OC_UNUSED(previousMsgId);
1386 #endif//__WITH_DTLS__
1389 if (OC_EH_CHANGED != ret)
1391 if(OC_STACK_OK != RemoveCredential(&cred->subject))
1393 OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
1399 previousMsgId = ehRequest->messageID;
1401 //Send response to request originator
1402 ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
1403 OC_EH_OK : OC_EH_ERROR;
1405 OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest OUT");
1410 * The entity handler determines how to process a GET request.
1412 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
1414 OIC_LOG(INFO, TAG, "HandleGetRequest processing GET request");
1416 // Convert Cred data into CBOR for transmission
1418 uint8_t *payload = NULL;
1421 const OicSecCred_t *cred = gCred;
1422 OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1424 // A device should always have a default cred. Therefore, payload should never be NULL.
1425 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
1428 //Send payload to request originator
1429 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
1430 OC_EH_OK : OC_EH_ERROR;
1435 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1437 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
1439 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1441 if (NULL == ehRequest->query)
1446 OicParseQueryIter_t parseIter = { .attrPos=NULL };
1447 OicUuid_t subject = {.id={0}};
1449 //Parsing REST query to get the subject
1450 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1451 while (GetNextQuery(&parseIter))
1453 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
1454 parseIter.attrLen) == 0)
1456 OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1457 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1461 if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
1463 ehRet = OC_EH_RESOURCE_DELETED;
1465 //Send response to request originator
1466 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1467 OC_EH_OK : OC_EH_ERROR;
1472 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
1473 OCEntityHandlerRequest * ehRequest,
1474 void* callbackParameter)
1476 (void)callbackParameter;
1477 OCEntityHandlerResult ret = OC_EH_ERROR;
1483 if (flag & OC_REQUEST_FLAG)
1485 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1486 //TODO : Remove Handle PUT methods once CTT have changed to POST on OTM
1487 switch (ehRequest->method)
1490 ret = HandleGetRequest(ehRequest);;
1494 ret = HandlePostRequest(ehRequest);
1496 case OC_REST_DELETE:
1497 ret = HandleDeleteRequest(ehRequest);
1500 ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
1501 OC_EH_OK : OC_EH_ERROR;
1508 OCStackResult CreateCredResource()
1510 OCStackResult ret = OCCreateResource(&gCredHandle,
1511 OIC_RSRC_TYPE_SEC_CRED,
1512 OC_RSRVD_INTERFACE_DEFAULT,
1518 if (OC_STACK_OK != ret)
1520 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
1521 DeInitCredResource();
1526 OCStackResult InitCredResource()
1528 OCStackResult ret = OC_STACK_ERROR;
1530 //Read Cred resource from PS
1531 uint8_t *data = NULL;
1533 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1534 // If database read failed
1535 if (ret != OC_STACK_OK)
1537 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1541 // Read ACL resource from PS
1542 ret = CBORPayloadToCred(data, size, &gCred);
1546 * If SVR database in persistent storage got corrupted or
1547 * is not available for some reason, a default Cred is created
1548 * which allows user to initiate Cred provisioning again.
1550 if (ret != OC_STACK_OK || !data || !gCred)
1552 gCred = GetCredDefault();
1554 //Instantiate 'oic.sec.cred'
1555 ret = CreateCredResource();
1560 OCStackResult DeInitCredResource()
1562 OCStackResult result = OCDeleteResource(gCredHandle);
1563 DeleteCredList(gCred);
1568 OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1570 OicSecCred_t *cred = NULL;
1572 if ( NULL == subject)
1577 LL_FOREACH(gCred, cred)
1579 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1587 OicSecCred_t* GetCredResourceDataByCredId(const uint16_t credId)
1589 OicSecCred_t *cred = NULL;
1596 LL_FOREACH(gCred, cred)
1598 if(cred->credId == credId)
1606 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1607 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1608 const uint8_t *desc, size_t desc_len,
1609 uint8_t *result, size_t result_length)
1620 case CA_DTLS_PSK_HINT:
1621 case CA_DTLS_PSK_IDENTITY:
1623 OicUuid_t deviceID = {.id={0}};
1624 // Retrieve Device ID from doxm resource
1625 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1627 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1631 if (result_length < sizeof(deviceID.id))
1633 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1636 memcpy(result, deviceID.id, sizeof(deviceID.id));
1637 return (sizeof(deviceID.id));
1641 case CA_DTLS_PSK_KEY:
1643 OicSecCred_t *cred = NULL;
1644 LL_FOREACH(gCred, cred)
1646 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1651 if ((desc_len == sizeof(cred->subject.id)) &&
1652 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1655 * If the credentials are valid for limited time,
1656 * check their expiry.
1660 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1662 OIC_LOG (INFO, TAG, "Credentials are expired.");
1668 // TODO: Added as workaround. Will be replaced soon.
1669 if(OIC_ENCODING_RAW == cred->privateData.encoding)
1671 ret = cred->privateData.len;
1672 memcpy(result, cred->privateData.data, ret);
1674 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
1676 size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
1677 uint8_t* outKey = OICCalloc(1, outBufSize);
1678 uint32_t outKeySize;
1681 OIC_LOG (ERROR, TAG, "Failed to memoray allocation.");
1685 if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
1687 memcpy(result, outKey, outKeySize);
1692 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
1706 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1715 * Add temporal PSK to PIN based OxM
1717 * @param[in] tmpSubject UUID of target device
1718 * @param[in] credType Type of credential to be added
1719 * @param[in] pin numeric characters
1720 * @param[in] pinSize length of 'pin'
1721 * @param[in] rownerID Resource owner's UUID
1722 * @param[out] tmpCredSubject Generated credential's subject.
1724 * @return OC_STACK_OK for success and errorcode otherwise.
1726 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1727 const char * pin, size_t pinSize,
1728 const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
1730 OCStackResult ret = OC_STACK_ERROR;
1731 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1733 if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1735 return OC_STACK_INVALID_PARAM;
1738 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1739 OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128, OIC_ENCODING_RAW};
1740 OicSecCred_t* cred = NULL;
1741 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
1742 UUID_LENGTH, PBKDF_ITERATIONS,
1743 OWNER_PSK_LENGTH_128, privData);
1744 VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1746 cred = GenerateCredential(tmpSubject, credType, NULL,
1747 &privKey, rownerID);
1750 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1751 return OC_STACK_ERROR;
1754 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1756 ret = AddCredential(cred);
1757 if( OC_STACK_OK != ret)
1759 RemoveCredential(tmpSubject);
1760 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1762 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1768 #endif /* __WITH_DTLS__ */
1769 #ifdef __WITH_X509__
1770 #define CERT_LEN_PREFIX (3)
1771 #define BYTE_SIZE (8) //bits
1772 #define PUB_KEY_X_COORD ("x")
1773 #define PUB_KEY_Y_COORD ("y")
1774 #define CERTIFICATE ("x5c")
1775 #define PRIVATE_KEY ("d")
1777 static uint32_t parseCertPrefix(uint8_t *prefix)
1782 for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1784 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1790 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1792 OCStackResult ret = OC_STACK_ERROR;
1793 uint8_t *ccPtr = credInfo->certificateChain;
1794 for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1796 ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1799 ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1800 CertificateX509 certStruct;
1802 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1804 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1806 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1807 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1814 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1817 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1820 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1823 OicSecCred_t *cred = NULL;
1824 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1825 VERIFY_NON_NULL(TAG, cred, ERROR);
1827 if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1831 credInfo->chainLen = 2;
1832 memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1833 memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1834 credInfo->certificateChainLen = cred->publicData.len;
1835 GetCAPublicKeyData(credInfo);
1842 #undef CERT_LEN_PREFIX
1843 #endif /* __WITH_X509__ */
1845 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
1847 OCStackResult ret = OC_STACK_ERROR;
1848 uint8_t *cborPayload = NULL;
1851 OicUuid_t prevId = {.id={0}};
1853 if(NULL == newROwner)
1855 ret = OC_STACK_INVALID_PARAM;
1859 ret = OC_STACK_NO_RESOURCE;
1862 if(newROwner && gCred)
1864 memcpy(prevId.id, gCred->rownerID.id, sizeof(prevId.id));
1865 memcpy(gCred->rownerID.id, newROwner->id, sizeof(newROwner->id));
1867 ret = CredToCBORPayload(gCred, &cborPayload, &size, secureFlag);
1868 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1870 ret = UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, cborPayload, size);
1871 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1873 OICFree(cborPayload);
1879 OICFree(cborPayload);
1880 memcpy(gCred->rownerID.id, prevId.id, sizeof(prevId.id));
1884 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
1886 OCStackResult retVal = OC_STACK_ERROR;
1889 *rowneruuid = gCred->rownerID;
1890 retVal = OC_STACK_OK;
1896 void GetDerCaCert(ByteArray * crt)
1898 uint8_t *data = NULL;
1899 OCStackResult ret = OC_STACK_ERROR;
1900 OicSecCred_t * cred;
1901 OicSecCred_t * temp = NULL;
1902 OIC_LOG(DEBUG, TAG, "IN GetDerCaCert");
1903 LL_FOREACH(gCred, temp)
1905 if (0==memcmp((temp->credUsage), TRUST_CA, sizeof(TRUST_CA)))
1907 OIC_LOG_V(DEBUG, TAG, "len: %d, crt len: %d", temp->optionalData.len, crt->len);
1908 if(OIC_ENCODING_BASE64 == temp->optionalData.encoding)
1910 size_t bufSize = B64DECODE_OUT_SAFESIZE((temp->optionalData.len + 1));
1911 uint8 * buf = OICCalloc(1, bufSize);
1914 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1918 b64Decode(temp->optionalData.data, temp->optionalData.len, buf, bufSize, &outSize);
1919 crt->data = OICRealloc(crt->data, crt->len + outSize);
1920 memcpy(crt->data + crt->len, buf, outSize);
1921 crt->len += outSize;
1926 crt->data = OICRealloc(crt->data, crt->len + temp->optionalData.len);
1927 memcpy(crt->data + crt->len, temp->optionalData.data, temp->optionalData.len);
1928 crt->len += temp->optionalData.len;
1930 OIC_LOG_V(DEBUG, TAG, "Trust CA Found!! %d", crt->len);
1933 if(!crt->len) OIC_LOG(DEBUG, TAG, "Trust CA Not Found!!");
1938 void GetDerKey(ByteArray * key)
1940 // TODO Add implementation
1946 void GetDerOwnCert(ByteArray * cert)
1948 // TODO Add implementation
1953 void GetPkixInfo(PkiInfo_t * inf)
1955 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1956 GetDerOwnCert(&inf->crt);
1957 GetDerKey(&inf->key);
1958 GetDerCaCert(&inf->ca);
1959 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);