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