security: publish securevirtualresourcetypes.h
[iotivity.git] / resource / csdk / security / src / oxmpincommon.c
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <memory.h>
22 #include <limits.h>
23
24 #include "ocstack.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "ocrandom.h"
28 #include "logger.h"
29 #include "pinoxmcommon.h"
30 #include "pbkdf2.h"
31 #include "base64.h"
32 #include "srmresourcestrings.h"
33 #include "doxmresource.h"
34 #include "credresource.h"
35 #include "cainterface.h"
36 #include "oic_string.h"
37
38 #define TAG "OIC_PIN_OXM_COMMON"
39
40 #define NUMBER_OF_PINNUM (10)
41 #define NUMBER_OF_ALPHABET (26)
42
43 /**
44  * Callbacks for displaying a pin.
45  */
46 typedef struct DisplayPinCallbacks
47 {
48     GeneratePinCallback callback;
49     DisplayPinCallbackWithContext contextCallback;
50     ClosePinDisplayCallback closePinDisplayCallback;
51     void* context;
52 } DisplayPinCallbacks_t;
53
54 /**
55  * Callbacks for pin input.
56  */
57 typedef struct InputPinCallbacks
58 {
59     InputPinCallback callback;
60     InputPinCallbackWithContext contextCallback;
61     void* context;
62 } InputPinCallbacks_t;
63
64 static DisplayPinCallbacks_t g_displayPinCallbacks = { .callback = NULL, .contextCallback = NULL, .closePinDisplayCallback = NULL, .context = NULL };
65 static InputPinCallbacks_t g_inputPinCallbacks = { .callback = NULL, .contextCallback = NULL, .context = NULL };
66
67 typedef struct PinOxmData {
68     uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
69     size_t pinSize;
70     OicSecPinType_t pinType;
71     OicUuid_t newDevice;
72 }PinOxmData_t;
73
74 static PinOxmData_t g_PinOxmData = {
75         .pinData={0},
76         .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE,
77         .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE),
78     };
79
80 /**
81  * Internal function to check pinType
82  */
83 static bool IsValidPinType(OicSecPinType_t pinType)
84 {
85     return ((NUM_PIN & pinType) ||
86             (LOWERCASE_CHAR_PIN & pinType) ||
87             (UPPERCASE_CHAR_PIN & pinType));
88 }
89
90 OCStackResult OC_CALL SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType)
91 {
92     if(OXM_RANDOM_PIN_MIN_SIZE > pinSize)
93     {
94         OIC_LOG(ERROR, TAG, "PIN size is too small");
95         return OC_STACK_INVALID_PARAM;
96     }
97     if(OXM_RANDOM_PIN_MAX_SIZE < pinSize)
98     {
99         OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE);
100         return OC_STACK_INVALID_PARAM;
101     }
102     if(false == IsValidPinType(pinType))
103     {
104         OIC_LOG(ERROR, TAG, "Invalid PIN type.");
105         return OC_STACK_INVALID_PARAM;
106     }
107
108     g_PinOxmData.pinSize = pinSize;
109     g_PinOxmData.pinType = pinType;
110
111     return OC_STACK_OK;
112 }
113
114 void OC_CALL SetInputPinCB(InputPinCallback pinCB)
115 {
116     if(NULL == pinCB)
117     {
118         OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
119         return;
120     }
121
122     if ((NULL != g_inputPinCallbacks.callback) || (NULL != g_inputPinCallbacks.contextCallback))
123     {
124         OIC_LOG(ERROR, TAG, "Callback for input pin is already set.");
125         return;
126     }
127
128     g_inputPinCallbacks.callback = pinCB;
129 }
130
131 OCStackResult OC_CALL SetInputPinWithContextCB(InputPinCallbackWithContext inputPinCB, void* context)
132 {
133     if (NULL == inputPinCB)
134     {
135         OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
136         return OC_STACK_INVALID_PARAM;
137     }
138
139     if ((NULL != g_inputPinCallbacks.callback) || (NULL != g_inputPinCallbacks.contextCallback))
140     {
141         OIC_LOG(ERROR, TAG, "Callback for input pin is already set.");
142         return OC_STACK_DUPLICATE_REQUEST;
143     }
144
145     g_inputPinCallbacks.contextCallback = inputPinCB;
146     g_inputPinCallbacks.context = context;
147
148     return OC_STACK_OK;
149 }
150
151 void OC_CALL SetGeneratePinCB(GeneratePinCallback pinCB)
152 {
153     if(NULL == pinCB)
154     {
155         OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
156         return;
157     }
158
159     if ((NULL != g_displayPinCallbacks.callback) || (NULL != g_displayPinCallbacks.contextCallback))
160     {
161         OIC_LOG(ERROR, TAG, "Callback for generate pin is already set.");
162         return;
163     }
164
165     g_displayPinCallbacks.callback = pinCB;
166 }
167
168 OCStackResult OC_CALL SetDisplayPinWithContextCB(DisplayPinCallbackWithContext displayPinCB, void* context)
169 {
170     if (NULL == displayPinCB)
171     {
172         OIC_LOG(ERROR, TAG, "Failed to set a callback for displaying a pin.");
173         return OC_STACK_INVALID_PARAM;
174     }
175
176     if ((NULL != g_displayPinCallbacks.callback) || (NULL != g_displayPinCallbacks.contextCallback))
177     {
178         OIC_LOG(ERROR, TAG, "Callback for displaying a pin is already set.");
179         return OC_STACK_DUPLICATE_REQUEST;
180     }
181
182     g_displayPinCallbacks.contextCallback = displayPinCB;
183     g_displayPinCallbacks.context = context;
184
185     return OC_STACK_OK;
186 }
187
188 void OC_CALL SetClosePinDisplayCB(ClosePinDisplayCallback closeCB)
189 {
190     if (NULL == closeCB)
191     {
192         OIC_LOG(ERROR, TAG, "Failed to set a callback for closing a pin.");
193         return;
194     }
195
196     if (NULL != g_displayPinCallbacks.closePinDisplayCallback)
197     {
198         OIC_LOG(ERROR, TAG, "Callback for closing a pin is already set.");
199         return;
200     }
201
202     g_displayPinCallbacks.closePinDisplayCallback = closeCB;
203 }
204
205 void OC_CALL UnsetInputPinCB()
206 {
207     UnsetInputPinWithContextCB();
208 }
209
210 void OC_CALL UnsetInputPinWithContextCB()
211 {
212     g_inputPinCallbacks.callback = NULL;
213     g_inputPinCallbacks.contextCallback = NULL;
214     g_inputPinCallbacks.context = NULL;
215 }
216
217 void OC_CALL UnsetGeneratePinCB()
218 {
219     UnsetDisplayPinWithContextCB();
220 }
221
222 void OC_CALL UnsetDisplayPinWithContextCB()
223 {
224     g_displayPinCallbacks.callback = NULL;
225     g_displayPinCallbacks.contextCallback = NULL;
226     g_displayPinCallbacks.context = NULL;
227 }
228
229 void OC_CALL UnsetClosePinDisplayCB()
230 {
231     g_displayPinCallbacks.closePinDisplayCallback = NULL;
232 }
233
234 void ClosePinDisplay()
235 {
236     if (g_displayPinCallbacks.closePinDisplayCallback)
237     {
238         g_displayPinCallbacks.closePinDisplayCallback();
239     }
240 }
241
242 /**
243  * Internal function to generate PIN element according to pinType.
244  * This function assumes the pinType is valid.
245  * In case of invalid pinType, '0' will be returned as default vaule.
246  */
247 static char GenerateRandomPinElement(OicSecPinType_t pinType)
248 {
249     const char defaultRetValue = '0';
250     char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
251     uint32_t curIndex = 0;
252
253     if(NUM_PIN & pinType)
254     {
255         for(char pinEle = '0'; pinEle <= '9'; pinEle++)
256         {
257             allowedCharacters[curIndex++] = pinEle;
258         }
259     }
260     if(UPPERCASE_CHAR_PIN & pinType)
261     {
262         for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
263         {
264             allowedCharacters[curIndex++] = pinEle;
265         }
266     }
267     if(LOWERCASE_CHAR_PIN & pinType)
268     {
269         for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
270         {
271             allowedCharacters[curIndex++] = pinEle;
272         }
273     }
274
275     if(0 == curIndex)
276     {
277         return defaultRetValue;
278     }
279     else
280     {
281         curIndex -= 1;
282     }
283
284     return allowedCharacters[OCGetRandomRange(0, curIndex)];
285 }
286
287 OCStackResult OC_CALL GeneratePin(char* pinBuffer, size_t bufferSize)
288 {
289     if(!pinBuffer)
290     {
291         OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
292         return OC_STACK_INVALID_PARAM;
293     }
294     if(g_PinOxmData.pinSize + 1 > bufferSize)
295     {
296         OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
297         return OC_STACK_INVALID_PARAM;
298     }
299     if(false == IsValidPinType(g_PinOxmData.pinType))
300     {
301         OIC_LOG(ERROR, TAG, "Invalid PIN type.");
302         OIC_LOG(ERROR, TAG, "Please set the PIN type using SetRandomPinPolicy API.");
303         return OC_STACK_ERROR;
304     }
305
306     for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
307     {
308         pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
309         g_PinOxmData.pinData[i] = pinBuffer[i];
310     }
311
312     pinBuffer[g_PinOxmData.pinSize] = '\0';
313     g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
314
315     if(g_displayPinCallbacks.callback)
316     {
317         g_displayPinCallbacks.callback(pinBuffer, g_PinOxmData.pinSize);
318     }
319     else if (g_displayPinCallbacks.contextCallback)
320     {
321         g_displayPinCallbacks.contextCallback(pinBuffer, g_PinOxmData.pinSize, g_displayPinCallbacks.context);
322     }
323     else
324     {
325         OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
326         OIC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
327         return OC_STACK_ERROR;
328     }
329
330     OicUuid_t deviceID;
331     if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
332     {
333         //Set the device id to derive temporal PSK
334         SetUuidForPinBasedOxm(&deviceID);
335
336         /**
337          * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
338          * Credential should not be saved into SVR.
339          * For this reason, use a temporary get_psk_info callback to random PIN OxM.
340          */
341         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
342         {
343             OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
344         }
345     }
346     else
347     {
348         OIC_LOG(ERROR, TAG, "Failed to read device ID");
349         return OC_STACK_ERROR;
350     }
351
352     return OC_STACK_OK;
353 }
354
355 OCStackResult InputPin(OicUuid_t deviceId, char* pinBuffer, size_t bufferSize)
356 {
357     if(!pinBuffer)
358     {
359         OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
360         return OC_STACK_INVALID_PARAM;
361     }
362     if(g_PinOxmData.pinSize + 1 > bufferSize)
363     {
364         OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
365         return OC_STACK_INVALID_PARAM;
366     }
367
368     if(g_inputPinCallbacks.callback)
369     {
370         g_inputPinCallbacks.callback(pinBuffer, bufferSize);
371         OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
372         g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
373     }
374     else if (g_inputPinCallbacks.contextCallback)
375     {
376         g_inputPinCallbacks.contextCallback(deviceId, pinBuffer, bufferSize, g_inputPinCallbacks.context);
377         OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
378         g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
379     }
380     else
381     {
382         OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
383         OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
384         return OC_STACK_ERROR;
385     }
386
387     return OC_STACK_OK;
388 }
389
390 #ifdef MULTIPLE_OWNER
391 OCStackResult OC_CALL SetPreconfigPin(const char *pinBuffer, size_t pinLength)
392 {
393     if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
394     {
395         return OC_STACK_INVALID_PARAM;
396     }
397
398     memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
399     g_PinOxmData.pinData[pinLength] = '\0';
400
401     return OC_STACK_OK;
402 }
403 #endif //MULTIPLE_OWNER
404
405 #ifdef __WITH_DTLS__
406
407 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
408 {
409     if(NULL != uuid)
410     {
411         memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
412     }
413 }
414
415 int DerivePSKUsingPIN(uint8_t* result)
416 {
417     int dtlsRes = DeriveCryptoKeyFromPassword(
418                                               (const unsigned char *)g_PinOxmData.pinData,
419                                               g_PinOxmData.pinSize,
420                                               g_PinOxmData.newDevice.id,
421                                               UUID_LENGTH, PBKDF_ITERATIONS,
422                                               OWNER_PSK_LENGTH_128, result);
423
424     OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
425     OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
426     OIC_LOG(DEBUG, TAG, "UUID : ");
427     OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
428
429     return dtlsRes;
430 }
431
432 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
433               const unsigned char *UNUSED1, size_t UNUSED2,
434               unsigned char *result, size_t result_length)
435 {
436     int32_t ret = -1;
437
438     (void)UNUSED1;
439     (void)UNUSED2;
440
441     if ((NULL == result)
442         || (result_length < OWNER_PSK_LENGTH_128)
443         || (result_length > INT32_MAX))
444     {
445         return ret;
446     }
447
448     switch (type)
449     {
450         case CA_DTLS_PSK_HINT:
451         case CA_DTLS_PSK_IDENTITY:
452             {
453                 /**
454                  * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
455                  *
456                  * At this point, The server generate random hint and
457                  * provide it to client through server key exchange message.
458                  */
459                 if (!OCGetRandomBytes(result, result_length))
460                 {
461                     OIC_LOG(ERROR, TAG, "Failed to generate random PSK hint");
462                     break;
463                 }
464                 ret = (int32_t)result_length;
465
466                 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
467                 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
468             }
469             break;
470
471         case CA_DTLS_PSK_KEY:
472             {
473                 if(0 == DerivePSKUsingPIN((uint8_t*)result))
474                 {
475                     ret = OWNER_PSK_LENGTH_128;
476                 }
477                 else
478                 {
479                     OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
480                 }
481             }
482             break;
483
484         default:
485             {
486                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
487             }
488             break;
489     }
490
491     return ret;
492 }
493
494 #ifdef MULTIPLE_OWNER
495 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
496               const unsigned char *UNUSED1, size_t UNUSED2,
497               unsigned char *result, size_t result_length)
498 {
499     int32_t ret = -1;
500
501     (void)UNUSED1;
502     (void)UNUSED2;
503
504     if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
505     {
506         return ret;
507     }
508
509     const OicSecDoxm_t* doxm = GetDoxmResourceData();
510     if(doxm)
511     {
512         switch (type)
513         {
514             case CA_DTLS_PSK_HINT:
515             case CA_DTLS_PSK_IDENTITY:
516                 {
517                     memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
518                     return (sizeof(doxm->deviceID.id));
519                 }
520                 break;
521
522             case CA_DTLS_PSK_KEY:
523                 {
524                     if(0 == DerivePSKUsingPIN((uint8_t*)result))
525                     {
526                         ret = OWNER_PSK_LENGTH_128;
527                     }
528                     else
529                     {
530                         OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
531                         ret = -1;
532                     }
533                 }
534                 break;
535
536             default:
537                 {
538                     OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
539                     ret = -1;
540                 }
541                 break;
542         }
543     }
544
545     return ret;
546 }
547
548
549 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
550               const unsigned char *UNUSED1, size_t UNUSED2,
551               unsigned char *result, size_t result_length)
552 {
553     int32_t ret = -1;
554
555     (void)UNUSED1;
556     (void)UNUSED2;
557
558     if ((NULL == result)
559         || (result_length < OWNER_PSK_LENGTH_128)
560         || (result_length > INT_MAX))
561     {
562         return ret;
563     }
564
565     const OicSecDoxm_t* doxm = GetDoxmResourceData();
566     if(doxm)
567     {
568         switch (type)
569         {
570             case CA_DTLS_PSK_HINT:
571             case CA_DTLS_PSK_IDENTITY:
572                 {
573                     /**
574                      * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
575                      *
576                      * At this point, The server generate random hint and
577                      * provide it to client through server key exchange message.
578                      */
579                     if (!OCGetRandomBytes(result, result_length))
580                     {
581                         OIC_LOG(ERROR, TAG, "Failed to generate random PSK hint");
582                         ret = -1;
583                         break;
584                     }
585                     ret = (int32_t)result_length;
586
587                     OIC_LOG(DEBUG, TAG, "PSK HINT : ");
588                     OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
589                 }
590                 break;
591
592             case CA_DTLS_PSK_KEY:
593                 {
594                     OicUuid_t uuid;
595                     memcpy(&uuid, &WILDCARD_SUBJECT_ID, sizeof(uuid));
596
597                     //Load PreConfigured-PIN
598                     const OicSecCred_t* cred = GetCredResourceData(&uuid);
599                     if(cred)
600                     {
601                         char* pinBuffer = NULL;
602                         size_t pinLength = 0;
603                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
604                         {
605                             pinBuffer = (char*)OICCalloc(1, cred->privateData.len + 1);
606                             if(NULL == pinBuffer)
607                             {
608                                 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
609                                 return ret;
610                             }
611                             pinLength = cred->privateData.len;
612                             memcpy(pinBuffer, cred->privateData.data, pinLength);
613                         }
614                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
615                         {
616                             size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
617                             pinBuffer = (char*)OICCalloc(1, pinBufSize);
618                             if(NULL == pinBuffer)
619                             {
620                                 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
621                                 return ret;
622                             }
623
624                             if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, (uint8_t*)pinBuffer, pinBufSize, &pinLength))
625                             {
626                                 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
627                                 OICFree(pinBuffer);
628                                 return ret;
629                             }
630                         }
631                         else
632                         {
633                             OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
634                             return ret;
635                         }
636
637                         if (g_PinOxmData.pinSize < pinLength)
638                         {
639                             OIC_LOG (ERROR, TAG, "PIN length too long");
640                             OICFree(pinBuffer);
641                             return ret;
642                         }
643                         memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
644                         OICFree(pinBuffer);
645                     }
646
647                     if(0 == DerivePSKUsingPIN((uint8_t*)result))
648                     {
649                         ret = OWNER_PSK_LENGTH_128;
650                     }
651                     else
652                     {
653                         OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
654                         ret = -1;
655                     }
656                 }
657                 break;
658
659             default:
660                 {
661                     OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
662                     ret = -1;
663                 }
664                 break;
665         }
666     }
667
668     return ret;
669 }
670
671
672 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
673               const unsigned char *UNUSED1, size_t UNUSED2,
674               unsigned char *result, size_t result_length)
675 {
676     int32_t ret = -1;
677
678     (void)UNUSED1;
679     (void)UNUSED2;
680
681     if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
682     {
683         return ret;
684     }
685
686     const OicSecDoxm_t* doxm = GetDoxmResourceData();
687     if(doxm)
688     {
689         switch (type)
690         {
691             case CA_DTLS_PSK_HINT:
692             case CA_DTLS_PSK_IDENTITY:
693                 {
694                     memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
695                     return (sizeof(doxm->deviceID.id));
696                 }
697                 break;
698             case CA_DTLS_PSK_KEY:
699                 {
700                     OicUuid_t uuid;
701                     memcpy(&uuid, &WILDCARD_SUBJECT_ID, sizeof(uuid));
702
703                     //Load PreConfigured-PIN
704                     const OicSecCred_t* cred = GetCredResourceData(&uuid);
705                     if(cred)
706                     {
707                         char* pinBuffer = NULL;
708                         size_t pinLength = 0;
709                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
710                         {
711                             pinBuffer = (char*)OICCalloc(1, cred->privateData.len + 1);
712                             if(NULL == pinBuffer)
713                             {
714                                 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
715                                 return ret;
716                             }
717                             pinLength = cred->privateData.len;
718                             memcpy(pinBuffer, cred->privateData.data, pinLength);
719                         }
720                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
721                         {
722                             size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
723                             pinBuffer = (char*)OICCalloc(1, pinBufSize);
724                             if(NULL == pinBuffer)
725                             {
726                                 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
727                                 return ret;
728                             }
729
730                             if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, (uint8_t*)pinBuffer, pinBufSize, &pinLength))
731                             {
732                                 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
733                                 OICFree(pinBuffer);
734                                 return ret;
735                             }
736                         }
737                         else
738                         {
739                             OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
740                             return ret;
741                         }
742
743                         if (g_PinOxmData.pinSize < pinLength)
744                         {
745                             OIC_LOG (ERROR, TAG, "PIN length is too long");
746                             OICFree(pinBuffer);
747                             return ret;
748                         }
749                         memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
750                         OICFree(pinBuffer);
751                     }
752
753                     if(0 == DerivePSKUsingPIN((uint8_t*)result))
754                     {
755                         ret = OWNER_PSK_LENGTH_128;
756                     }
757                     else
758                     {
759                         OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
760                         ret = -1;
761                     }
762                 }
763                 break;
764
765             default:
766                 {
767                     OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
768                     ret = -1;
769                 }
770                 break;
771         }
772     }
773
774     return ret;
775 }
776 #endif //MULTIPLE_OWNER
777
778 #endif //__WITH_DTLS__