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 InputPinCallback gInputPinCallback = NULL;
45 static ClosePinDisplayCallback gClosePinDispalyCallback = NULL;
47 typedef struct PinOxmData {
48 uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
50 OicSecPinType_t pinType;
54 static PinOxmData_t g_PinOxmData = {
56 .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE,
57 .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE),
61 * Internal function to check pinType
63 static bool IsValidPinType(OicSecPinType_t pinType)
65 return ((NUM_PIN & pinType) ||
66 (LOWERCASE_CHAR_PIN & pinType) ||
67 (UPPERCASE_CHAR_PIN & pinType));
70 OCStackResult SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType)
72 if(OXM_RANDOM_PIN_MIN_SIZE > pinSize)
74 OIC_LOG(ERROR, TAG, "PIN size is too small");
75 return OC_STACK_INVALID_PARAM;
77 if(OXM_RANDOM_PIN_MAX_SIZE < pinSize)
79 OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE);
80 return OC_STACK_INVALID_PARAM;
82 if(false == IsValidPinType(pinType))
84 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
85 return OC_STACK_INVALID_PARAM;
88 g_PinOxmData.pinSize = pinSize;
89 g_PinOxmData.pinType = pinType;
94 void SetInputPinCB(InputPinCallback pinCB)
98 OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
102 gInputPinCallback = pinCB;
105 void SetGeneratePinCB(GeneratePinCallback pinCB)
109 OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
113 gGenPinCallback = pinCB;
116 void SetClosePinDisplayCB(ClosePinDisplayCallback closeCB)
120 OIC_LOG(ERROR, TAG, "Failed to set a callback for closing a pin.");
124 gClosePinDispalyCallback = closeCB;
127 void UnsetInputPinCB()
129 gInputPinCallback = NULL;
132 void UnsetGeneratePinCB()
134 gGenPinCallback = NULL;
137 void UnsetClosePinDisplayCB()
139 gClosePinDispalyCallback = NULL;
142 void ClosePinDisplay()
144 if (gClosePinDispalyCallback)
146 gClosePinDispalyCallback();
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.
155 static char GenerateRandomPinElement(OicSecPinType_t pinType)
157 const char defaultRetValue = '0';
158 char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
161 if(NUM_PIN & pinType)
163 for(char pinEle = '0'; pinEle <= '9'; pinEle++)
165 allowedCharacters[curIndex++] = pinEle;
168 if(UPPERCASE_CHAR_PIN & pinType)
170 for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
172 allowedCharacters[curIndex++] = pinEle;
175 if(LOWERCASE_CHAR_PIN & pinType)
177 for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
179 allowedCharacters[curIndex++] = pinEle;
185 return defaultRetValue;
192 return allowedCharacters[OCGetRandomRange(0, curIndex)];
195 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
199 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
200 return OC_STACK_INVALID_PARAM;
202 if(g_PinOxmData.pinSize + 1 > bufferSize)
204 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
205 return OC_STACK_INVALID_PARAM;
207 if(false == IsValidPinType(g_PinOxmData.pinType))
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;
214 for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
216 pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
217 g_PinOxmData.pinData[i] = pinBuffer[i];
220 pinBuffer[g_PinOxmData.pinSize] = '\0';
221 g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
225 gGenPinCallback(pinBuffer, g_PinOxmData.pinSize);
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;
235 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
237 //Set the device id to derive temporal PSK
238 SetUuidForPinBasedOxm(&deviceID);
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.
245 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
247 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
252 OIC_LOG(ERROR, TAG, "Failed to read device ID");
253 return OC_STACK_ERROR;
259 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
263 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
264 return OC_STACK_INVALID_PARAM;
266 if(g_PinOxmData.pinSize + 1 > bufferSize)
268 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
269 return OC_STACK_INVALID_PARAM;
272 if(gInputPinCallback)
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));
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;
288 #ifdef MULTIPLE_OWNER
289 OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength)
291 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
293 return OC_STACK_INVALID_PARAM;
296 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
297 g_PinOxmData.pinData[pinLength] = '\0';
301 #endif //MULTIPLE_OWNER
305 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
309 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
313 int DerivePSKUsingPIN(uint8_t* result)
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);
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);
328 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
329 const unsigned char *UNUSED1, size_t UNUSED2,
330 unsigned char *result, size_t result_length)
337 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
344 case CA_DTLS_PSK_HINT:
345 case CA_DTLS_PSK_IDENTITY:
348 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
350 * At this point, The server generate random hint and
351 * provide it to client through server key exchange message.
353 OCFillRandomMem(result, result_length);
355 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
356 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
360 case CA_DTLS_PSK_KEY:
362 if(0 == DerivePSKUsingPIN((uint8_t*)result))
364 ret = OWNER_PSK_LENGTH_128;
368 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
376 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
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)
394 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
399 const OicSecDoxm_t* doxm = GetDoxmResourceData();
404 case CA_DTLS_PSK_HINT:
405 case CA_DTLS_PSK_IDENTITY:
407 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
408 return (sizeof(doxm->deviceID.id));
412 case CA_DTLS_PSK_KEY:
414 if(0 == DerivePSKUsingPIN((uint8_t*)result))
416 ret = OWNER_PSK_LENGTH_128;
420 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
428 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
439 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
440 const unsigned char *UNUSED1, size_t UNUSED2,
441 unsigned char *result, size_t result_length)
448 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
453 const OicSecDoxm_t* doxm = GetDoxmResourceData();
458 case CA_DTLS_PSK_HINT:
459 case CA_DTLS_PSK_IDENTITY:
462 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
464 * At this point, The server generate random hint and
465 * provide it to client through server key exchange message.
467 OCFillRandomMem(result, result_length);
470 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
471 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
475 case CA_DTLS_PSK_KEY:
478 memset(&uuid, 0x00, sizeof(uuid));
479 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
481 //Load PreConfigured-PIN
482 const OicSecCred_t* cred = GetCredResourceData(&uuid);
485 char* pinBuffer = NULL;
486 uint32_t pinLength = 0;
487 if(OIC_ENCODING_RAW == cred->privateData.encoding)
489 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
490 if(NULL == pinBuffer)
492 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
495 pinLength = cred->privateData.len;
496 memcpy(pinBuffer, cred->privateData.data, pinLength);
498 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
500 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
501 pinBuffer = OICCalloc(1, pinBufSize);
502 if(NULL == pinBuffer)
504 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
508 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
510 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
516 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
520 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
524 if(0 == DerivePSKUsingPIN((uint8_t*)result))
526 ret = OWNER_PSK_LENGTH_128;
530 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
538 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
549 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
550 const unsigned char *UNUSED1, size_t UNUSED2,
551 unsigned char *result, size_t result_length)
558 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
563 const OicSecDoxm_t* doxm = GetDoxmResourceData();
568 case CA_DTLS_PSK_HINT:
569 case CA_DTLS_PSK_IDENTITY:
571 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
572 return (sizeof(doxm->deviceID.id));
575 case CA_DTLS_PSK_KEY:
578 memset(&uuid, 0x00, sizeof(uuid));
579 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
581 //Load PreConfigured-PIN
582 const OicSecCred_t* cred = GetCredResourceData(&uuid);
585 char* pinBuffer = NULL;
586 uint32_t pinLength = 0;
587 if(OIC_ENCODING_RAW == cred->privateData.encoding)
589 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
590 if(NULL == pinBuffer)
592 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
595 pinLength = cred->privateData.len;
596 memcpy(pinBuffer, cred->privateData.data, pinLength);
598 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
600 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
601 pinBuffer = OICCalloc(1, pinBufSize);
602 if(NULL == pinBuffer)
604 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
608 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
610 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
616 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
620 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
624 if(0 == DerivePSKUsingPIN((uint8_t*)result))
626 ret = OWNER_PSK_LENGTH_128;
630 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
638 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
647 #endif //MULTIPLE_OWNER
649 #endif //__WITH_DTLS__