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;
128 void UnsetInputPinCB()
130 gInputPinCallback = NULL;
133 void UnsetGeneratePinCB()
135 gGenPinCallback = NULL;
138 void UnsetClosePinDisplayCB()
140 gClosePinDispalyCallback = NULL;
143 void ClosePinDisplay()
145 if (gClosePinDispalyCallback)
147 gClosePinDispalyCallback();
152 * Internal function to generate PIN element according to pinType.
153 * This function assumes the pinType is valid.
154 * In case of invalid pinType, '0' will be returned as default vaule.
156 static char GenerateRandomPinElement(OicSecPinType_t pinType)
158 const char defaultRetValue = '0';
159 char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
162 if(NUM_PIN & pinType)
164 for(char pinEle = '0'; pinEle <= '9'; pinEle++)
166 allowedCharacters[curIndex++] = pinEle;
169 if(UPPERCASE_CHAR_PIN & pinType)
171 for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
173 allowedCharacters[curIndex++] = pinEle;
176 if(LOWERCASE_CHAR_PIN & pinType)
178 for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
180 allowedCharacters[curIndex++] = pinEle;
186 return defaultRetValue;
193 return allowedCharacters[OCGetRandomRange(0, curIndex)];
196 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
200 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
201 return OC_STACK_INVALID_PARAM;
203 if(g_PinOxmData.pinSize + 1 > bufferSize)
205 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
206 return OC_STACK_INVALID_PARAM;
208 if(false == IsValidPinType(g_PinOxmData.pinType))
210 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
211 OIC_LOG(ERROR, TAG, "Please set the PIN type using SetRandomPinPolicy API.");
212 return OC_STACK_ERROR;
215 for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
217 pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
218 g_PinOxmData.pinData[i] = pinBuffer[i];
221 pinBuffer[g_PinOxmData.pinSize] = '\0';
222 g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
226 gGenPinCallback(pinBuffer, g_PinOxmData.pinSize);
230 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
231 OIC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
232 return OC_STACK_ERROR;
236 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
238 //Set the device id to derive temporal PSK
239 SetUuidForPinBasedOxm(&deviceID);
242 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
243 * Credential should not be saved into SVR.
244 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
246 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
248 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
253 OIC_LOG(ERROR, TAG, "Failed to read device ID");
254 return OC_STACK_ERROR;
260 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
264 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
265 return OC_STACK_INVALID_PARAM;
267 if(g_PinOxmData.pinSize + 1 > bufferSize)
269 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
270 return OC_STACK_INVALID_PARAM;
273 if(gInputPinCallback)
275 gInputPinCallback(pinBuffer, bufferSize);
276 OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
277 g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
281 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
282 OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
283 return OC_STACK_ERROR;
289 #ifdef MULTIPLE_OWNER
290 OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength)
292 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
294 return OC_STACK_INVALID_PARAM;
297 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
298 g_PinOxmData.pinData[pinLength] = '\0';
302 #endif //MULTIPLE_OWNER
306 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
310 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
314 int DerivePSKUsingPIN(uint8_t* result)
316 int dtlsRes = DeriveCryptoKeyFromPassword(
317 (const unsigned char *)g_PinOxmData.pinData,
318 g_PinOxmData.pinSize,
319 g_PinOxmData.newDevice.id,
320 UUID_LENGTH, PBKDF_ITERATIONS,
321 OWNER_PSK_LENGTH_128, result);
323 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
324 OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
325 OIC_LOG(DEBUG, TAG, "UUID : ");
326 OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
330 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
331 const unsigned char *UNUSED1, size_t UNUSED2,
332 unsigned char *result, size_t result_length)
339 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
346 case CA_DTLS_PSK_HINT:
347 case CA_DTLS_PSK_IDENTITY:
350 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
352 * At this point, The server generate random hint and
353 * provide it to client through server key exchange message.
355 OCFillRandomMem(result, result_length);
357 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
358 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
362 case CA_DTLS_PSK_KEY:
364 if(0 == DerivePSKUsingPIN((uint8_t*)result))
366 ret = OWNER_PSK_LENGTH_128;
370 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
378 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
386 #ifdef MULTIPLE_OWNER
387 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
388 const unsigned char *UNUSED1, size_t UNUSED2,
389 unsigned char *result, size_t result_length)
396 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
401 const OicSecDoxm_t* doxm = GetDoxmResourceData();
406 case CA_DTLS_PSK_HINT:
407 case CA_DTLS_PSK_IDENTITY:
409 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
410 return (sizeof(doxm->deviceID.id));
414 case CA_DTLS_PSK_KEY:
416 if(0 == DerivePSKUsingPIN((uint8_t*)result))
418 ret = OWNER_PSK_LENGTH_128;
422 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
430 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
441 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
442 const unsigned char *UNUSED1, size_t UNUSED2,
443 unsigned char *result, size_t result_length)
450 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
455 const OicSecDoxm_t* doxm = GetDoxmResourceData();
460 case CA_DTLS_PSK_HINT:
461 case CA_DTLS_PSK_IDENTITY:
464 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
466 * At this point, The server generate random hint and
467 * provide it to client through server key exchange message.
469 OCFillRandomMem(result, result_length);
472 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
473 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
477 case CA_DTLS_PSK_KEY:
480 memset(&uuid, 0x00, sizeof(uuid));
481 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
483 //Load PreConfigured-PIN
484 const OicSecCred_t* cred = GetCredResourceData(&uuid);
487 char* pinBuffer = NULL;
488 uint32_t pinLength = 0;
489 if(OIC_ENCODING_RAW == cred->privateData.encoding)
491 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
492 if(NULL == pinBuffer)
494 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
497 pinLength = cred->privateData.len;
498 memcpy(pinBuffer, cred->privateData.data, pinLength);
500 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
502 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
503 pinBuffer = OICCalloc(1, pinBufSize);
504 if(NULL == pinBuffer)
506 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
510 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
512 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
518 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
522 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
526 if(0 == DerivePSKUsingPIN((uint8_t*)result))
528 ret = OWNER_PSK_LENGTH_128;
532 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
540 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
551 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
552 const unsigned char *UNUSED1, size_t UNUSED2,
553 unsigned char *result, size_t result_length)
560 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
565 const OicSecDoxm_t* doxm = GetDoxmResourceData();
570 case CA_DTLS_PSK_HINT:
571 case CA_DTLS_PSK_IDENTITY:
573 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
574 return (sizeof(doxm->deviceID.id));
577 case CA_DTLS_PSK_KEY:
580 memset(&uuid, 0x00, sizeof(uuid));
581 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
583 //Load PreConfigured-PIN
584 const OicSecCred_t* cred = GetCredResourceData(&uuid);
587 char* pinBuffer = NULL;
588 uint32_t pinLength = 0;
589 if(OIC_ENCODING_RAW == cred->privateData.encoding)
591 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
592 if(NULL == pinBuffer)
594 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
597 pinLength = cred->privateData.len;
598 memcpy(pinBuffer, cred->privateData.data, pinLength);
600 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
602 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
603 pinBuffer = OICCalloc(1, pinBufSize);
604 if(NULL == pinBuffer)
606 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
610 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
612 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
618 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
622 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
626 if(0 == DerivePSKUsingPIN((uint8_t*)result))
628 ret = OWNER_PSK_LENGTH_128;
632 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
640 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
649 #endif //MULTIPLE_OWNER
651 #endif //__WITH_DTLS__