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