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 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
74 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
75 return OC_STACK_INVALID_PARAM;
77 if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
79 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
80 return OC_STACK_INVALID_PARAM;
82 for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
84 pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
85 g_PinOxmData.pinData[i] = pinBuffer[i];
87 pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
88 g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
92 gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE);
96 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
97 OIC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
98 return OC_STACK_ERROR;
102 if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
104 //Set the device id to derive temporal PSK
105 SetUuidForPinBasedOxm(&deviceID);
108 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
109 * Credential should not be saved into SVR.
110 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
112 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
114 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
119 OIC_LOG(ERROR, TAG, "Failed to read device ID");
120 return OC_STACK_ERROR;
126 OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
130 OIC_LOG(ERROR, TAG, "PIN buffer is NULL");
131 return OC_STACK_INVALID_PARAM;
133 if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
135 OIC_LOG(ERROR, TAG, "PIN buffer size is too small");
136 return OC_STACK_INVALID_PARAM;
139 if(gInputPinCallback)
141 gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
142 memcpy(g_PinOxmData.pinData, pinBuffer, OXM_RANDOM_PIN_SIZE);
143 g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
147 OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
148 OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
149 return OC_STACK_ERROR;
155 #ifdef _ENABLE_MULTIPLE_OWNER_
156 OCStackResult SetPreconfigPin(const char* pinBuffer, size_t pinLength)
158 if(NULL == pinBuffer || OXM_PRECONFIG_PIN_SIZE < pinLength)
160 return OC_STACK_INVALID_PARAM;
163 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
164 g_PinOxmData.pinData[pinLength] = '\0';
168 #endif //_ENABLE_MULTIPLE_OWNER_
172 void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
176 memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
180 int DerivePSKUsingPIN(uint8_t* result)
182 int dtlsRes = DeriveCryptoKeyFromPassword(
183 (const unsigned char *)g_PinOxmData.pinData,
185 g_PinOxmData.newDevice.id,
186 UUID_LENGTH, PBKDF_ITERATIONS,
187 OWNER_PSK_LENGTH_128, result);
189 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
190 OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
191 OIC_LOG(DEBUG, TAG, "UUID : ");
192 OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
197 int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
198 const unsigned char *UNUSED1, size_t UNUSED2,
199 unsigned char *result, size_t result_length)
206 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
213 case CA_DTLS_PSK_HINT:
214 case CA_DTLS_PSK_IDENTITY:
217 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
219 * At this point, The server generate random hint and
220 * provide it to client through server key exchange message.
222 OCFillRandomMem(result, result_length);
225 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
226 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
230 case CA_DTLS_PSK_KEY:
232 if(0 == DerivePSKUsingPIN((uint8_t*)result))
234 ret = OWNER_PSK_LENGTH_128;
238 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
246 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
255 #ifdef _ENABLE_MULTIPLE_OWNER_
256 int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
257 const unsigned char *UNUSED1, size_t UNUSED2,
258 unsigned char *result, size_t result_length)
265 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
270 const OicSecDoxm_t* doxm = GetDoxmResourceData();
275 case CA_DTLS_PSK_HINT:
276 case CA_DTLS_PSK_IDENTITY:
278 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
279 return (sizeof(doxm->deviceID.id));
283 case CA_DTLS_PSK_KEY:
285 if(0 == DerivePSKUsingPIN((uint8_t*)result))
287 ret = OWNER_PSK_LENGTH_128;
291 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
299 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
310 int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
311 const unsigned char *UNUSED1, size_t UNUSED2,
312 unsigned char *result, size_t result_length)
319 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
324 const OicSecDoxm_t* doxm = GetDoxmResourceData();
329 case CA_DTLS_PSK_HINT:
330 case CA_DTLS_PSK_IDENTITY:
333 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
335 * At this point, The server generate random hint and
336 * provide it to client through server key exchange message.
338 OCFillRandomMem(result, result_length);
341 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
342 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
346 case CA_DTLS_PSK_KEY:
349 memset(&uuid, 0x00, sizeof(uuid));
350 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
352 //Load PreConfigured-PIN
353 const OicSecCred_t* cred = GetCredResourceData(&uuid);
356 char* pinBuffer = NULL;
357 uint32_t pinLength = 0;
358 if(OIC_ENCODING_RAW == cred->privateData.encoding)
360 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
361 if(NULL == pinBuffer)
363 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
366 pinLength = cred->privateData.len;
367 memcpy(pinBuffer, cred->privateData.data, pinLength);
369 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
371 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
372 pinBuffer = OICCalloc(1, pinBufSize);
373 if(NULL == pinBuffer)
375 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
379 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
381 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
387 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
391 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
395 if(0 == DerivePSKUsingPIN((uint8_t*)result))
397 ret = OWNER_PSK_LENGTH_128;
401 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
409 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
420 int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
421 const unsigned char *UNUSED1, size_t UNUSED2,
422 unsigned char *result, size_t result_length)
429 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
434 const OicSecDoxm_t* doxm = GetDoxmResourceData();
439 case CA_DTLS_PSK_HINT:
440 case CA_DTLS_PSK_IDENTITY:
442 memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
443 return (sizeof(doxm->deviceID.id));
446 case CA_DTLS_PSK_KEY:
449 memset(&uuid, 0x00, sizeof(uuid));
450 OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
452 //Load PreConfigured-PIN
453 const OicSecCred_t* cred = GetCredResourceData(&uuid);
456 char* pinBuffer = NULL;
457 uint32_t pinLength = 0;
458 if(OIC_ENCODING_RAW == cred->privateData.encoding)
460 pinBuffer = OICCalloc(1, cred->privateData.len + 1);
461 if(NULL == pinBuffer)
463 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
466 pinLength = cred->privateData.len;
467 memcpy(pinBuffer, cred->privateData.data, pinLength);
469 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
471 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
472 pinBuffer = OICCalloc(1, pinBufSize);
473 if(NULL == pinBuffer)
475 OIC_LOG (ERROR, TAG, "Failed to allocate memory");
479 if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
481 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
487 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
491 memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
495 if(0 == DerivePSKUsingPIN((uint8_t*)result))
497 ret = OWNER_PSK_LENGTH_128;
501 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
509 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
518 #endif //_ENABLE_MULTIPLE_OWNER_
520 #endif //__WITH_DTLS__