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