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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
26 #include "pinoxmcommon.h"
29 #include "securevirtualresourcetypes.h"
30 #include "srmresourcestrings.h"
31 #include "doxmresource.h"
32 #include "credresource.h"
33 #include "cainterface.h"
34 #include "oic_string.h"
36 #define TAG "OIC_PIN_OXM_COMMON"
38 #define NUMBER_OF_PINNUM (10)
39 #define NUMBER_OF_ALPHABET (26)
41 static GeneratePinCallback gGenPinCallback = NULL;
42 static InputPinCallback gInputPinCallback = NULL;
44 typedef struct PinOxmData {
45 uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
47 OicSecPinType_t pinType;
51 static PinOxmData_t g_PinOxmData = {
53 .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE,
54 .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE),
58 * Internal function to check pinType
60 static bool IsValidPinType(OicSecPinType_t pinType)
62 return ((NUM_PIN & pinType) ||
63 (LOWERCASE_CHAR_PIN & pinType) ||
64 (UPPERCASE_CHAR_PIN & pinType));
67 OCStackResult SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType)
69 if(OXM_RANDOM_PIN_MIN_SIZE > pinSize)
71 OIC_LOG(ERROR, TAG, "PIN size is too small");
72 return OC_STACK_INVALID_PARAM;
74 if(OXM_RANDOM_PIN_MAX_SIZE < pinSize)
76 OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE);
77 return OC_STACK_INVALID_PARAM;
79 if(false == IsValidPinType(pinType))
81 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
82 return OC_STACK_INVALID_PARAM;
85 g_PinOxmData.pinSize = pinSize;
86 g_PinOxmData.pinType = pinType;
91 void SetInputPinCB(InputPinCallback pinCB)
95 OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
99 gInputPinCallback = pinCB;
102 void SetGeneratePinCB(GeneratePinCallback pinCB)
106 OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
110 gGenPinCallback = pinCB;
113 void UnsetInputPinCB()
115 gInputPinCallback = NULL;
118 void UnsetGeneratePinCB()
120 gGenPinCallback = NULL;
124 * Internal function to generate PIN element according to pinType.
125 * This function assumes the pinType is valid.
126 * In case of invalid pinType, '0' will be returned as default vaule.
128 static char GenerateRandomPinElement(OicSecPinType_t pinType)
130 const char defaultRetValue = '0';
131 char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2];
134 if(NUM_PIN & pinType)
136 for(char pinEle = '0'; pinEle <= '9'; pinEle++)
138 allowedCharacters[curIndex++] = pinEle;
141 if(UPPERCASE_CHAR_PIN & pinType)
143 for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++)
145 allowedCharacters[curIndex++] = pinEle;
148 if(LOWERCASE_CHAR_PIN & pinType)
150 for(char pinEle = 'a'; pinEle <= 'z'; pinEle++)
152 allowedCharacters[curIndex++] = pinEle;
158 return defaultRetValue;
161 return allowedCharacters[OCGetRandomRange(0, curIndex)];
164 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
168 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
169 return OC_STACK_INVALID_PARAM;
171 if(g_PinOxmData.pinSize + 1 > bufferSize)
173 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
174 return OC_STACK_INVALID_PARAM;
176 if(false == IsValidPinType(g_PinOxmData.pinType))
178 OIC_LOG(ERROR, TAG, "Invalid PIN type.");
179 OIC_LOG(ERROR, TAG, "Please set the PIN type using SetRandomPinPolicy API.");
180 return OC_STACK_ERROR;
183 for(size_t i = 0; i < g_PinOxmData.pinSize; i++)
185 pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType);
186 g_PinOxmData.pinData[i] = pinBuffer[i];
189 pinBuffer[g_PinOxmData.pinSize] = '\0';
190 g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
194 gGenPinCallback(pinBuffer, g_PinOxmData.pinSize);
198 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
199 OIC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
200 return OC_STACK_ERROR;
204 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
206 //Set the device id to derive temporal PSK
207 SetUuidForPinBasedOxm(&deviceID);
210 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
211 * Credential should not be saved into SVR.
212 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
214 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
216 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
221 OIC_LOG(ERROR, TAG, "Failed to read device ID");
222 return OC_STACK_ERROR;
228 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
232 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
233 return OC_STACK_INVALID_PARAM;
235 if(g_PinOxmData.pinSize + 1 > bufferSize)
237 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
238 return OC_STACK_INVALID_PARAM;
241 if(gInputPinCallback)
243 gInputPinCallback(pinBuffer, bufferSize);
244 OICStrcpy(g_PinOxmData.pinData, OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
245 g_PinOxmData.pinSize = strlen(g_PinOxmData.pinData);
249 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
250 OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
251 return OC_STACK_ERROR;
257 #ifdef _ENABLE_MULTIPLE_OWNER_
258 OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength)
260 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength)
262 return OC_STACK_INVALID_PARAM;
265 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
266 g_PinOxmData.pinData[pinLength] = '\0';
270 #endif //_ENABLE_MULTIPLE_OWNER_
274 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
278 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
282 int DerivePSKUsingPIN(uint8_t* result)
284 int dtlsRes = DeriveCryptoKeyFromPassword(
285 (const unsigned char *)g_PinOxmData.pinData,
286 g_PinOxmData.pinSize,
287 g_PinOxmData.newDevice.id,
288 UUID_LENGTH, PBKDF_ITERATIONS,
289 OWNER_PSK_LENGTH_128, result);
291 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
292 OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
293 OIC_LOG(DEBUG, TAG, "UUID : ");
294 OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
299 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
300 const unsigned char *UNUSED1, size_t UNUSED2,
301 unsigned char *result, size_t result_length)
308 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
315 case CA_DTLS_PSK_HINT:
316 case CA_DTLS_PSK_IDENTITY:
319 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
321 * At this point, The server generate random hint and
322 * provide it to client through server key exchange message.
324 OCFillRandomMem(result, result_length);
327 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
328 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
332 case CA_DTLS_PSK_KEY:
334 if(0 == DerivePSKUsingPIN((uint8_t*)result))
336 ret = OWNER_PSK_LENGTH_128;
340 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
348 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
357 #ifdef _ENABLE_MULTIPLE_OWNER_
358 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
359 const unsigned char *UNUSED1, size_t UNUSED2,
360 unsigned char *result, size_t result_length)
367 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
372 const OicSecDoxm_t* doxm = GetDoxmResourceData();
377 case CA_DTLS_PSK_HINT:
378 case CA_DTLS_PSK_IDENTITY:
380 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
381 return (sizeof(doxm->deviceID.id));
385 case CA_DTLS_PSK_KEY:
387 if(0 == DerivePSKUsingPIN((uint8_t*)result))
389 ret = OWNER_PSK_LENGTH_128;
393 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
401 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
412 int32_t GetDtlsPskForPreconfPinOxm( 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:
435 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
437 * At this point, The server generate random hint and
438 * provide it to client through server key exchange message.
440 OCFillRandomMem(result, result_length);
443 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
444 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
448 case CA_DTLS_PSK_KEY:
451 memset(&uuid, 0x00, sizeof(uuid));
452 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
454 //Load PreConfigured-PIN
455 const OicSecCred_t* cred = GetCredResourceData(&uuid);
458 char* pinBuffer = NULL;
459 uint32_t pinLength = 0;
460 if(OIC_ENCODING_RAW == cred->privateData.encoding)
462 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
463 if(NULL == pinBuffer)
465 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
468 pinLength = cred->privateData.len;
469 memcpy(pinBuffer, cred->privateData.data, pinLength);
471 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
473 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
474 pinBuffer = OICCalloc(1, pinBufSize);
475 if(NULL == pinBuffer)
477 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
481 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
483 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
489 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
493 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
497 if(0 == DerivePSKUsingPIN((uint8_t*)result))
499 ret = OWNER_PSK_LENGTH_128;
503 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
511 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
522 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
523 const unsigned char *UNUSED1, size_t UNUSED2,
524 unsigned char *result, size_t result_length)
531 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
536 const OicSecDoxm_t* doxm = GetDoxmResourceData();
541 case CA_DTLS_PSK_HINT:
542 case CA_DTLS_PSK_IDENTITY:
544 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
545 return (sizeof(doxm->deviceID.id));
548 case CA_DTLS_PSK_KEY:
551 memset(&uuid, 0x00, sizeof(uuid));
552 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
554 //Load PreConfigured-PIN
555 const OicSecCred_t* cred = GetCredResourceData(&uuid);
558 char* pinBuffer = NULL;
559 uint32_t pinLength = 0;
560 if(OIC_ENCODING_RAW == cred->privateData.encoding)
562 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
563 if(NULL == pinBuffer)
565 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
568 pinLength = cred->privateData.len;
569 memcpy(pinBuffer, cred->privateData.data, pinLength);
571 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
573 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
574 pinBuffer = OICCalloc(1, pinBufSize);
575 if(NULL == pinBuffer)
577 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
581 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
583 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
589 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
593 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
597 if(0 == DerivePSKUsingPIN((uint8_t*)result))
599 ret = OWNER_PSK_LENGTH_128;
603 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
611 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
620 #endif //_ENABLE_MULTIPLE_OWNER_
622 #endif //__WITH_DTLS__