1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
28 #include "pinoxmcommon.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"
38 #define TAG "OIC_PIN_OXM_COMMON"
40 #define NUMBER_OF_PINNUM (10)
41 #define NUMBER_OF_ALPHABET (26)
43 static GeneratePinCallback gGenPinCallback = NULL;
44 static GeneratePinCallback gSetPinCallback = NULL;
45 static InputPinCallback gInputPinCallback = NULL;
46 static ClosePinDisplayCallback gClosePinDispalyCallback = NULL;
48 typedef struct PinOxmData {
49 uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
51 OicSecPinType_t pinType;
56 static PinOxmData_t g_PinOxmData = {
58 .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE,
59 .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE),
64 * Internal function to check pinType
66 static bool IsValidPinType(OicSecPinType_t pinType)
68 return ((NUM_PIN & pinType) ||
69 (LOWERCASE_CHAR_PIN & pinType) ||
70 (UPPERCASE_CHAR_PIN & pinType));
73 OCStackResult SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType)
75 if(OXM_RANDOM_PIN_MIN_SIZE > pinSize)
77 OIC_LOG(ERROR, TAG, "PIN size is too small");
78 return OC_STACK_INVALID_PARAM;
80 if(OXM_RANDOM_PIN_MAX_SIZE < pinSize)
82 OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE);
83 return OC_STACK_INVALID_PARAM;
85 if(false == IsValidPinType(pinType))
87 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
88 return OC_STACK_INVALID_PARAM;
91 g_PinOxmData.pinSize = pinSize;
92 g_PinOxmData.pinType = pinType;
97 void SetInputPinCB(InputPinCallback pinCB)
101 OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
105 gInputPinCallback = pinCB;
108 void SetGeneratePinCB(GeneratePinCallback pinCB)
112 OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
116 gGenPinCallback = pinCB;
119 void SetClosePinDisplayCB(ClosePinDisplayCallback closeCB)
123 OIC_LOG(ERROR, TAG, "Failed to set a callback for closing a pin.");
127 gClosePinDispalyCallback = closeCB;
130 void UnsetInputPinCB()
132 gInputPinCallback = NULL;
135 void UnsetGeneratePinCB()
137 gGenPinCallback = NULL;
140 void UnsetClosePinDisplayCB()
142 gClosePinDispalyCallback = NULL;
145 void ClosePinDisplay()
147 if (gClosePinDispalyCallback)
149 gClosePinDispalyCallback();
154 * Internal function to generate PIN element according to pinType.
155 * This function assumes the pinType is valid.
156 * In case of invalid pinType, '0' will be returned as default vaule.
158 static char GenerateRandomPinElement(OicSecPinType_t pinType)
160 const char defaultRetValue = '0';
161 char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
164 if(NUM_PIN & pinType)
166 for(char pinEle = '0'; pinEle <= '9'; pinEle++)
168 allowedCharacters[curIndex++] = pinEle;
171 if(UPPERCASE_CHAR_PIN & pinType)
173 for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
175 allowedCharacters[curIndex++] = pinEle;
178 if(LOWERCASE_CHAR_PIN & pinType)
180 for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
182 allowedCharacters[curIndex++] = pinEle;
188 return defaultRetValue;
195 return allowedCharacters[OCGetRandomRange(0, curIndex)];
198 OCStackResult SetPin(const char * pin, size_t pinLen)
200 if(NULL == pin || OXM_PRECONFIG_PIN_MAX_SIZE < pinLen)
202 return OC_STACK_INVALID_PARAM;
205 memcpy(g_PinOxmData.pinData, pin, pinLen);
206 g_PinOxmData.pinSize = pinLen;
207 g_PinOxmData.pinData[pinLen] = '\0';
208 g_PinOxmData.pinPreset = 1;
213 OCStackResult UnSetPin()
215 g_PinOxmData.pinPreset = 0;
219 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
223 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
224 return OC_STACK_INVALID_PARAM;
226 if(g_PinOxmData.pinSize + 1 > bufferSize)
228 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
229 return OC_STACK_INVALID_PARAM;
231 if(false == IsValidPinType(g_PinOxmData.pinType))
233 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
234 OIC_LOG(ERROR, TAG, "Please set the PIN type using SetRandomPinPolicy API.");
235 return OC_STACK_ERROR;
238 if (!g_PinOxmData.pinPreset)
240 for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
242 pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
243 g_PinOxmData.pinData[i] = pinBuffer[i];
246 pinBuffer[g_PinOxmData.pinSize] = '\0';
247 g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
252 gGenPinCallback(g_PinOxmData.pinData, g_PinOxmData.pinSize);
256 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
257 OIC_LOG(ERROR, TAG, "Callback for generate PIN should be registered to use PIN based OxM.");
258 return OC_STACK_ERROR;
262 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
264 //Set the device id to derive temporal PSK
265 SetUuidForPinBasedOxm(&deviceID);
268 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
269 * Credential should not be saved into SVR.
270 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
272 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
274 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
279 OIC_LOG(ERROR, TAG, "Failed to read device ID");
280 return OC_STACK_ERROR;
286 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
290 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
291 return OC_STACK_INVALID_PARAM;
293 if(g_PinOxmData.pinSize + 1 > bufferSize)
295 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
296 return OC_STACK_INVALID_PARAM;
299 if(gInputPinCallback)
301 gInputPinCallback(pinBuffer, bufferSize);
302 OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
303 g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
307 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
308 OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
309 return OC_STACK_ERROR;
315 #ifdef MULTIPLE_OWNER
316 OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength)
318 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
320 return OC_STACK_INVALID_PARAM;
323 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
324 g_PinOxmData.pinData[pinLength] = '\0';
328 #endif //MULTIPLE_OWNER
332 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
336 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
340 int DerivePSKUsingPIN(uint8_t* result)
342 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)g_PinOxmData.pinData,
343 g_PinOxmData.pinSize,
344 g_PinOxmData.newDevice.id,
345 UUID_LENGTH, PBKDF_ITERATIONS,
346 OWNER_PSK_LENGTH_128, result);
348 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
349 OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
350 OIC_LOG(DEBUG, TAG, "UUID : ");
351 OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
355 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
356 const unsigned char *UNUSED1, size_t UNUSED2,
357 unsigned char *result, size_t result_length)
364 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
371 case CA_DTLS_PSK_HINT:
372 case CA_DTLS_PSK_IDENTITY:
375 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
377 * At this point, The server generate random hint and
378 * provide it to client through server key exchange message.
380 OCFillRandomMem(result, result_length);
382 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
383 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
387 case CA_DTLS_PSK_KEY:
389 if(0 == DerivePSKUsingPIN((uint8_t*)result))
391 ret = OWNER_PSK_LENGTH_128;
395 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
403 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
411 #ifdef MULTIPLE_OWNER
412 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
413 const unsigned char *UNUSED1, size_t UNUSED2,
414 unsigned char *result, size_t result_length)
421 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
426 const OicSecDoxm_t* doxm = GetDoxmResourceData();
431 case CA_DTLS_PSK_HINT:
432 case CA_DTLS_PSK_IDENTITY:
434 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
435 return (sizeof(doxm->deviceID.id));
439 case CA_DTLS_PSK_KEY:
441 if(0 == DerivePSKUsingPIN((uint8_t*)result))
443 ret = OWNER_PSK_LENGTH_128;
447 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
455 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
466 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
467 const unsigned char *UNUSED1, size_t UNUSED2,
468 unsigned char *result, size_t result_length)
475 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
480 const OicSecDoxm_t* doxm = GetDoxmResourceData();
485 case CA_DTLS_PSK_HINT:
486 case CA_DTLS_PSK_IDENTITY:
489 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
491 * At this point, The server generate random hint and
492 * provide it to client through server key exchange message.
494 OCFillRandomMem(result, result_length);
497 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
498 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
502 case CA_DTLS_PSK_KEY:
505 memset(&uuid, 0x00, sizeof(uuid));
506 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
508 //Load PreConfigured-PIN
509 const OicSecCred_t* cred = GetCredResourceData(&uuid);
512 char* pinBuffer = NULL;
513 uint32_t pinLength = 0;
514 if(OIC_ENCODING_RAW == cred->privateData.encoding)
516 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
517 if(NULL == pinBuffer)
519 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
522 pinLength = cred->privateData.len;
523 memcpy(pinBuffer, cred->privateData.data, pinLength);
525 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
527 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
528 pinBuffer = OICCalloc(1, pinBufSize);
529 if(NULL == pinBuffer)
531 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
535 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
537 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
543 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
547 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
551 if(0 == DerivePSKUsingPIN((uint8_t*)result))
553 ret = OWNER_PSK_LENGTH_128;
557 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
565 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
576 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
577 const unsigned char *UNUSED1, size_t UNUSED2,
578 unsigned char *result, size_t result_length)
585 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
590 const OicSecDoxm_t* doxm = GetDoxmResourceData();
595 case CA_DTLS_PSK_HINT:
596 case CA_DTLS_PSK_IDENTITY:
598 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
599 return (sizeof(doxm->deviceID.id));
602 case CA_DTLS_PSK_KEY:
605 memset(&uuid, 0x00, sizeof(uuid));
606 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
608 //Load PreConfigured-PIN
609 const OicSecCred_t* cred = GetCredResourceData(&uuid);
612 char* pinBuffer = NULL;
613 uint32_t pinLength = 0;
614 if(OIC_ENCODING_RAW == cred->privateData.encoding)
616 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
617 if(NULL == pinBuffer)
619 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
622 pinLength = cred->privateData.len;
623 memcpy(pinBuffer, cred->privateData.data, pinLength);
625 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
627 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
628 pinBuffer = OICCalloc(1, pinBufSize);
629 if(NULL == pinBuffer)
631 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
635 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
637 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
643 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
647 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
651 if(0 == DerivePSKUsingPIN((uint8_t*)result))
653 ret = OWNER_PSK_LENGTH_128;
657 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
665 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
674 #endif //MULTIPLE_OWNER
676 #endif //__WITH_DTLS__