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"
37 #include "oic_malloc.h"
39 #define TAG "OIC_PIN_OXM_COMMON"
41 #define NUMBER_OF_PINNUM (10)
42 #define NUMBER_OF_ALPHABET (26)
44 static GeneratePinCallback gGenPinCallback = NULL;
45 static GeneratePinCallback gSetPinCallback = NULL;
46 static InputPinCallback gInputPinCallback = NULL;
47 static ClosePinDisplayCallback gClosePinDispalyCallback = NULL;
49 typedef struct PinOxmData {
50 uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
52 OicSecPinType_t pinType;
57 static PinOxmData_t g_PinOxmData = {
59 .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE,
60 .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE),
65 * Internal function to check pinType
67 static bool IsValidPinType(OicSecPinType_t pinType)
69 return ((NUM_PIN & pinType) ||
70 (LOWERCASE_CHAR_PIN & pinType) ||
71 (UPPERCASE_CHAR_PIN & pinType));
74 OCStackResult SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType)
76 if(OXM_RANDOM_PIN_MIN_SIZE > pinSize)
78 OIC_LOG(ERROR, TAG, "PIN size is too small");
79 return OC_STACK_INVALID_PARAM;
81 if(OXM_RANDOM_PIN_MAX_SIZE < pinSize)
83 OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE);
84 return OC_STACK_INVALID_PARAM;
86 if(false == IsValidPinType(pinType))
88 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
89 return OC_STACK_INVALID_PARAM;
92 g_PinOxmData.pinSize = pinSize;
93 g_PinOxmData.pinType = pinType;
98 void SetInputPinCB(InputPinCallback pinCB)
102 OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
106 gInputPinCallback = pinCB;
109 void SetGeneratePinCB(GeneratePinCallback pinCB)
113 OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
117 gGenPinCallback = pinCB;
120 void SetClosePinDisplayCB(ClosePinDisplayCallback closeCB)
124 OIC_LOG(ERROR, TAG, "Failed to set a callback for closing a pin.");
128 gClosePinDispalyCallback = closeCB;
131 void UnsetInputPinCB()
133 gInputPinCallback = NULL;
136 void UnsetGeneratePinCB()
138 gGenPinCallback = NULL;
141 void UnsetClosePinDisplayCB()
143 gClosePinDispalyCallback = NULL;
146 void ClosePinDisplay()
148 if (gClosePinDispalyCallback)
150 gClosePinDispalyCallback();
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.
159 static char GenerateRandomPinElement(OicSecPinType_t pinType)
161 const char defaultRetValue = '0';
162 char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
165 if(NUM_PIN & pinType)
167 for(char pinEle = '0'; pinEle <= '9'; pinEle++)
169 allowedCharacters[curIndex++] = pinEle;
172 if(UPPERCASE_CHAR_PIN & pinType)
174 for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
176 allowedCharacters[curIndex++] = pinEle;
179 if(LOWERCASE_CHAR_PIN & pinType)
181 for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
183 allowedCharacters[curIndex++] = pinEle;
189 return defaultRetValue;
196 return allowedCharacters[OCGetRandomRange(0, curIndex)];
199 OCStackResult SetPin(const char * pin, size_t pinLen)
201 if(NULL == pin || OXM_PRECONFIG_PIN_MAX_SIZE < pinLen)
203 return OC_STACK_INVALID_PARAM;
206 memcpy(g_PinOxmData.pinData, pin, pinLen);
207 g_PinOxmData.pinSize = pinLen;
208 g_PinOxmData.pinData[pinLen] = '\0';
209 g_PinOxmData.pinPreset = 1;
214 OCStackResult UnSetPin()
216 g_PinOxmData.pinPreset = 0;
220 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
224 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
225 return OC_STACK_INVALID_PARAM;
227 if(g_PinOxmData.pinSize + 1 > bufferSize)
229 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
230 return OC_STACK_INVALID_PARAM;
232 if(false == IsValidPinType(g_PinOxmData.pinType))
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;
239 if (!g_PinOxmData.pinPreset)
241 for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
243 pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
244 g_PinOxmData.pinData[i] = pinBuffer[i];
247 pinBuffer[g_PinOxmData.pinSize] = '\0';
248 g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
253 gGenPinCallback(g_PinOxmData.pinData, g_PinOxmData.pinSize);
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;
263 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
265 //Set the device id to derive temporal PSK
266 SetUuidForPinBasedOxm(&deviceID);
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.
273 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
275 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
280 OIC_LOG(ERROR, TAG, "Failed to read device ID");
281 return OC_STACK_ERROR;
287 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
291 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
292 return OC_STACK_INVALID_PARAM;
294 if(g_PinOxmData.pinSize + 1 > bufferSize)
296 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
297 return OC_STACK_INVALID_PARAM;
300 if(gInputPinCallback)
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));
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;
316 #ifdef MULTIPLE_OWNER
317 OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength)
319 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
321 return OC_STACK_INVALID_PARAM;
324 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
325 g_PinOxmData.pinData[pinLength] = '\0';
329 #endif //MULTIPLE_OWNER
333 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
337 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
341 int DerivePSKUsingPIN(uint8_t* result)
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);
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);
356 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
357 const unsigned char *UNUSED1, size_t UNUSED2,
358 unsigned char *result, size_t result_length)
365 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
372 case CA_DTLS_PSK_HINT:
373 case CA_DTLS_PSK_IDENTITY:
376 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
378 * At this point, The server generate random hint and
379 * provide it to client through server key exchange message.
381 OCFillRandomMem(result, result_length);
383 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
384 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
388 case CA_DTLS_PSK_KEY:
390 if(0 == DerivePSKUsingPIN((uint8_t*)result))
392 ret = OWNER_PSK_LENGTH_128;
396 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
404 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
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)
422 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
427 const OicSecDoxm_t* doxm = GetDoxmResourceData();
432 case CA_DTLS_PSK_HINT:
433 case CA_DTLS_PSK_IDENTITY:
435 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
436 return (sizeof(doxm->deviceID.id));
440 case CA_DTLS_PSK_KEY:
442 if(0 == DerivePSKUsingPIN((uint8_t*)result))
444 ret = OWNER_PSK_LENGTH_128;
448 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
456 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
467 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
468 const unsigned char *UNUSED1, size_t UNUSED2,
469 unsigned char *result, size_t result_length)
476 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
481 const OicSecDoxm_t* doxm = GetDoxmResourceData();
486 case CA_DTLS_PSK_HINT:
487 case CA_DTLS_PSK_IDENTITY:
490 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
492 * At this point, The server generate random hint and
493 * provide it to client through server key exchange message.
495 OCFillRandomMem(result, result_length);
498 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
499 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
503 case CA_DTLS_PSK_KEY:
506 memset(&uuid, 0x00, sizeof(uuid));
507 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
509 //Load PreConfigured-PIN
510 const OicSecCred_t* cred = GetCredResourceData(&uuid);
513 char* pinBuffer = NULL;
514 uint32_t pinLength = 0;
515 if(OIC_ENCODING_RAW == cred->privateData.encoding)
517 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
518 if(NULL == pinBuffer)
520 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
523 pinLength = cred->privateData.len;
524 memcpy(pinBuffer, cred->privateData.data, pinLength);
526 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
528 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
529 pinBuffer = OICCalloc(1, pinBufSize);
530 if(NULL == pinBuffer)
532 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
536 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
538 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
544 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
548 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
552 if(0 == DerivePSKUsingPIN((uint8_t*)result))
554 ret = OWNER_PSK_LENGTH_128;
558 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
566 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
577 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
578 const unsigned char *UNUSED1, size_t UNUSED2,
579 unsigned char *result, size_t result_length)
586 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
591 const OicSecDoxm_t* doxm = GetDoxmResourceData();
596 case CA_DTLS_PSK_HINT:
597 case CA_DTLS_PSK_IDENTITY:
599 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
600 return (sizeof(doxm->deviceID.id));
603 case CA_DTLS_PSK_KEY:
606 memset(&uuid, 0x00, sizeof(uuid));
607 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
609 //Load PreConfigured-PIN
610 const OicSecCred_t* cred = GetCredResourceData(&uuid);
613 char* pinBuffer = NULL;
614 uint32_t pinLength = 0;
615 if(OIC_ENCODING_RAW == cred->privateData.encoding)
617 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
618 if(NULL == pinBuffer)
620 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
623 pinLength = cred->privateData.len;
624 memcpy(pinBuffer, cred->privateData.data, pinLength);
626 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
628 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
629 pinBuffer = OICCalloc(1, pinBufSize);
630 if(NULL == pinBuffer)
632 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
636 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
638 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
644 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
648 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
652 if(0 == DerivePSKUsingPIN((uint8_t*)result))
654 ret = OWNER_PSK_LENGTH_128;
658 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
666 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
675 #endif //MULTIPLE_OWNER
677 #endif //__WITH_DTLS__