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"
35 #define TAG "PIN_OXM_COMMON"
37 static GeneratePinCallback gGenPinCallback = NULL;
38 static InputPinCallback gInputPinCallback = NULL;
40 typedef struct PinOxmData {
41 uint8_t pinData[OXM_RANDOM_PIN_SIZE + 1];
45 static PinOxmData_t g_PinOxmData;
48 void SetInputPinCB(InputPinCallback pinCB)
52 OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
56 gInputPinCallback = pinCB;
59 void SetGeneratePinCB(GeneratePinCallback pinCB)
63 OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
67 gGenPinCallback = pinCB;
70 void UnsetInputPinCB()
72 gInputPinCallback = NULL;
75 void UnsetGeneratePinCB()
77 gGenPinCallback = NULL;
80 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
84 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
85 return OC_STACK_INVALID_PARAM;
87 if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
89 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
90 return OC_STACK_INVALID_PARAM;
92 for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
94 pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
95 g_PinOxmData.pinData[i] = pinBuffer[i];
97 pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
98 g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
102 gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE);
106 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
107 OIC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
108 return OC_STACK_ERROR;
112 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
114 //Set the device id to derive temporal PSK
115 SetUuidForPinBasedOxm(&deviceID);
118 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
119 * Credential should not be saved into SVR.
120 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
122 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
124 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
129 OIC_LOG(ERROR, TAG, "Failed to read device ID");
130 return OC_STACK_ERROR;
136 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
140 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
141 return OC_STACK_INVALID_PARAM;
143 if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
145 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
146 return OC_STACK_INVALID_PARAM;
149 if(gInputPinCallback)
151 gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
152 memcpy(g_PinOxmData.pinData, pinBuffer, OXM_RANDOM_PIN_SIZE);
153 g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
157 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
158 OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
159 return OC_STACK_ERROR;
165 #ifdef _ENABLE_MULTIPLE_OWNER_
166 OCStackResult SetPreconfigPin(const char* pinBuffer, size_t pinLength)
168 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_SIZE < pinLength)
170 return OC_STACK_INVALID_PARAM;
173 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
174 g_PinOxmData.pinData[pinLength] = '\0';
178 #endif //_ENABLE_MULTIPLE_OWNER_
182 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
186 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
190 int DerivePSKUsingPIN(uint8_t* result)
192 int dtlsRes = DeriveCryptoKeyFromPassword(
193 (const unsigned char *)g_PinOxmData.pinData,
195 g_PinOxmData.newDevice.id,
196 UUID_LENGTH, PBKDF_ITERATIONS,
197 OWNER_PSK_LENGTH_128, result);
199 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
200 OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
201 OIC_LOG(DEBUG, TAG, "UUID : ");
202 OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
207 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
208 const unsigned char *UNUSED1, size_t UNUSED2,
209 unsigned char *result, size_t result_length)
216 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
223 case CA_DTLS_PSK_HINT:
224 case CA_DTLS_PSK_IDENTITY:
227 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
229 * At this point, The server generate random hint and
230 * provide it to client through server key exchange message.
232 OCFillRandomMem(result, result_length);
235 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
236 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
240 case CA_DTLS_PSK_KEY:
242 if(0 == DerivePSKUsingPIN((uint8_t*)result))
244 ret = OWNER_PSK_LENGTH_128;
248 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
256 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
265 #ifdef _ENABLE_MULTIPLE_OWNER_
266 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
267 const unsigned char *UNUSED1, size_t UNUSED2,
268 unsigned char *result, size_t result_length)
275 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
280 const OicSecDoxm_t* doxm = GetDoxmResourceData();
285 case CA_DTLS_PSK_HINT:
286 case CA_DTLS_PSK_IDENTITY:
288 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
289 return (sizeof(doxm->deviceID.id));
293 case CA_DTLS_PSK_KEY:
295 if(0 == DerivePSKUsingPIN((uint8_t*)result))
297 ret = OWNER_PSK_LENGTH_128;
301 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
309 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
320 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
321 const unsigned char *UNUSED1, size_t UNUSED2,
322 unsigned char *result, size_t result_length)
329 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
334 const OicSecDoxm_t* doxm = GetDoxmResourceData();
339 case CA_DTLS_PSK_HINT:
340 case CA_DTLS_PSK_IDENTITY:
343 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
345 * At this point, The server generate random hint and
346 * provide it to client through server key exchange message.
348 OCFillRandomMem(result, result_length);
351 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
352 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
356 case CA_DTLS_PSK_KEY:
359 memset(&uuid, 0x00, sizeof(uuid));
360 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
362 //Load PreConfigured-PIN
363 const OicSecCred_t* cred = GetCredResourceData(&uuid);
366 char* pinBuffer = NULL;
367 uint32_t pinLength = 0;
368 if(OIC_ENCODING_RAW == cred->privateData.encoding)
370 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
371 if(NULL == pinBuffer)
373 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
376 pinLength = cred->privateData.len;
377 memcpy(pinBuffer, cred->privateData.data, pinLength);
379 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
381 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
382 pinBuffer = OICCalloc(1, pinBufSize);
383 if(NULL == pinBuffer)
385 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
389 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
391 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
397 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
401 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
405 if(0 == DerivePSKUsingPIN((uint8_t*)result))
407 ret = OWNER_PSK_LENGTH_128;
411 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
419 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
430 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
431 const unsigned char *UNUSED1, size_t UNUSED2,
432 unsigned char *result, size_t result_length)
439 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
444 const OicSecDoxm_t* doxm = GetDoxmResourceData();
449 case CA_DTLS_PSK_HINT:
450 case CA_DTLS_PSK_IDENTITY:
452 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
453 return (sizeof(doxm->deviceID.id));
456 case CA_DTLS_PSK_KEY:
459 memset(&uuid, 0x00, sizeof(uuid));
460 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
462 //Load PreConfigured-PIN
463 const OicSecCred_t* cred = GetCredResourceData(&uuid);
466 char* pinBuffer = NULL;
467 uint32_t pinLength = 0;
468 if(OIC_ENCODING_RAW == cred->privateData.encoding)
470 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
471 if(NULL == pinBuffer)
473 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
476 pinLength = cred->privateData.len;
477 memcpy(pinBuffer, cred->privateData.data, pinLength);
479 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
481 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
482 pinBuffer = OICCalloc(1, pinBufSize);
483 if(NULL == pinBuffer)
485 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
489 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
491 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
497 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
501 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
505 if(0 == DerivePSKUsingPIN((uint8_t*)result))
507 ret = OWNER_PSK_LENGTH_128;
511 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
519 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
528 #endif //_ENABLE_MULTIPLE_OWNER_
530 #endif //__WITH_DTLS__