X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Foxmpincommon.c;h=189f07c39aa99b9951403d721e315cff10c5bd50;hb=refs%2Fchanges%2F14%2F212714%2F1;hp=85612e936a9f0ff2a221c4fe185c1e9fbb4ce1e7;hpb=78d5cb6296c178dea7e6e9c10abf3ccd72002c1d;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/oxmpincommon.c b/resource/csdk/security/src/oxmpincommon.c index 85612e9..189f07c 100644 --- a/resource/csdk/security/src/oxmpincommon.c +++ b/resource/csdk/security/src/oxmpincommon.c @@ -1,37 +1,104 @@ -/* ***************************************************************** - * - * Copyright 2015 Samsung Electronics All Rights Reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * *****************************************************************/ +//****************************************************************** +// +// Copyright 2015 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef __TIZENRT__ +#include +#endif + #include "ocstack.h" #include "ocrandom.h" #include "logger.h" #include "pinoxmcommon.h" +#include "pbkdf2.h" +#include "base64.h" +#include "securevirtualresourcetypes.h" +#include "srmresourcestrings.h" +#include "doxmresource.h" +#include "credresource.h" +#include "cainterface.h" +#include "oic_string.h" + +#define TAG "OIC_PIN_OXM_COMMON" -#define TAG "PIN_OXM_COMMON" +#define NUMBER_OF_PINNUM (10) +#define NUMBER_OF_ALPHABET (26) static GeneratePinCallback gGenPinCallback = NULL; +static GeneratePinCallback gSetPinCallback = NULL; static InputPinCallback gInputPinCallback = NULL; +static ClosePinDisplayCallback gClosePinDispalyCallback = NULL; + +typedef struct PinOxmData { + uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1]; + size_t pinSize; + OicSecPinType_t pinType; + OicUuid_t newDevice; + int pinPreset; +}PinOxmData_t; + +static PinOxmData_t g_PinOxmData = { + .pinData = {0}, + .pinSize = OXM_RANDOM_PIN_DEFAULT_SIZE, + .pinType = (OicSecPinType_t)(OXM_RANDOM_PIN_DEFAULT_PIN_TYPE), + .pinPreset = 0 + }; + +/** + * Internal function to check pinType + */ +static bool IsValidPinType(OicSecPinType_t pinType) +{ + return ((NUM_PIN & pinType) || + (LOWERCASE_CHAR_PIN & pinType) || + (UPPERCASE_CHAR_PIN & pinType)); +} + +OCStackResult SetRandomPinPolicy(size_t pinSize, OicSecPinType_t pinType) +{ + if(OXM_RANDOM_PIN_MIN_SIZE > pinSize) + { + OIC_LOG(ERROR, TAG, "PIN size is too small"); + return OC_STACK_INVALID_PARAM; + } + if(OXM_RANDOM_PIN_MAX_SIZE < pinSize) + { + OIC_LOG_V(ERROR, TAG, "PIN size can not exceed %d bytes", OXM_RANDOM_PIN_MAX_SIZE); + return OC_STACK_INVALID_PARAM; + } + if(false == IsValidPinType(pinType)) + { + OIC_LOG(ERROR, TAG, "Invalid PIN type."); + return OC_STACK_INVALID_PARAM; + } + + g_PinOxmData.pinSize = pinSize; + g_PinOxmData.pinType = pinType; + + return OC_STACK_OK; +} void SetInputPinCB(InputPinCallback pinCB) { if(NULL == pinCB) { - OC_LOG(ERROR, TAG, "Failed to set callback for input pin."); + OIC_LOG(ERROR, TAG, "Failed to set callback for input pin."); return; } @@ -42,69 +109,568 @@ void SetGeneratePinCB(GeneratePinCallback pinCB) { if(NULL == pinCB) { - OC_LOG(ERROR, TAG, "Failed to set callback for generate pin."); + OIC_LOG(ERROR, TAG, "Failed to set callback for generate pin."); return; } gGenPinCallback = pinCB; } +void SetClosePinDisplayCB(ClosePinDisplayCallback closeCB) +{ + if (NULL == closeCB) + { + OIC_LOG(ERROR, TAG, "Failed to set a callback for closing a pin."); + return; + } + + gClosePinDispalyCallback = closeCB; +} + +void UnsetInputPinCB() +{ + gInputPinCallback = NULL; +} + +void UnsetGeneratePinCB() +{ + gGenPinCallback = NULL; +} + +void UnsetClosePinDisplayCB() +{ + gClosePinDispalyCallback = NULL; +} + +void ClosePinDisplay() +{ + if (gClosePinDispalyCallback) + { + gClosePinDispalyCallback(); + } +} + +/** + * Internal function to generate PIN element according to pinType. + * This function assumes the pinType is valid. + * In case of invalid pinType, '0' will be returned as default vaule. + */ +static char GenerateRandomPinElement(OicSecPinType_t pinType) +{ + const char defaultRetValue = '0'; + char allowedCharacters[NUMBER_OF_PINNUM + NUMBER_OF_ALPHABET * 2]; + size_t curIndex = 0; + + if(NUM_PIN & pinType) + { + for(char pinEle = '0'; pinEle <= '9'; pinEle++) + { + allowedCharacters[curIndex++] = pinEle; + } + } + if(UPPERCASE_CHAR_PIN & pinType) + { + for(char pinEle = 'A'; pinEle <= 'Z'; pinEle++) + { + allowedCharacters[curIndex++] = pinEle; + } + } + if(LOWERCASE_CHAR_PIN & pinType) + { + for(char pinEle = 'a'; pinEle <= 'z'; pinEle++) + { + allowedCharacters[curIndex++] = pinEle; + } + } + + if(0 == curIndex) + { + return defaultRetValue; + } + else + { + curIndex -= 1; + } + + return allowedCharacters[OCGetRandomRange(0, curIndex)]; +} + +OCStackResult SetPin(const char * pin, size_t pinLen) +{ + if(NULL == pin || OXM_PRECONFIG_PIN_MAX_SIZE < pinLen) + { + return OC_STACK_INVALID_PARAM; + } + + memcpy(g_PinOxmData.pinData, pin, pinLen); + g_PinOxmData.pinSize = pinLen; + g_PinOxmData.pinData[pinLen] = '\0'; + g_PinOxmData.pinPreset = 1; + + return OC_STACK_OK; +} + +OCStackResult UnSetPin() +{ + g_PinOxmData.pinPreset = 0; + return OC_STACK_OK; +} + OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize) { if(!pinBuffer) { - OC_LOG(ERROR, TAG, "PIN buffer is NULL"); + OIC_LOG(ERROR, TAG, "PIN buffer is NULL"); return OC_STACK_INVALID_PARAM; } - if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize) + if(g_PinOxmData.pinSize + 1 > bufferSize) { - OC_LOG(ERROR, TAG, "PIN buffer size is too small"); + OIC_LOG(ERROR, TAG, "PIN buffer size is too small"); return OC_STACK_INVALID_PARAM; } - for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++) + if(false == IsValidPinType(g_PinOxmData.pinType)) { - pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9'); + OIC_LOG(ERROR, TAG, "Invalid PIN type."); + OIC_LOG(ERROR, TAG, "Please set the PIN type using SetRandomPinPolicy API."); + return OC_STACK_ERROR; + } + + if (!g_PinOxmData.pinPreset) + { + for(size_t i = 0; i < g_PinOxmData.pinSize; i++) + { + pinBuffer[i] = GenerateRandomPinElement(g_PinOxmData.pinType); + g_PinOxmData.pinData[i] = pinBuffer[i]; + } + + pinBuffer[g_PinOxmData.pinSize] = '\0'; + g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0'; } - pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0'; if(gGenPinCallback) { - gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE); + gGenPinCallback(g_PinOxmData.pinData, g_PinOxmData.pinSize); } else { - OC_LOG(ERROR, TAG, "Invoke PIN callback failed!"); - OC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM."); + OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!"); + OIC_LOG(ERROR, TAG, "Callback for generate PIN should be registered to use PIN based OxM."); + return OC_STACK_ERROR; + } + + OicUuid_t deviceID; + if(OC_STACK_OK == GetDoxmDeviceID(&deviceID)) + { + //Set the device id to derive temporal PSK + SetUuidForPinBasedOxm(&deviceID); + + /** + * Since PSK will be used directly by DTLS layer while PIN based ownership transfer, + * Credential should not be saved into SVR. + * For this reason, use a temporary get_psk_info callback to random PIN OxM. + */ + if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm)) + { + OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM."); + } + } + else + { + OIC_LOG(ERROR, TAG, "Failed to read device ID"); return OC_STACK_ERROR; } return OC_STACK_OK; } - OCStackResult InputPin(char* pinBuffer, size_t bufferSize) { if(!pinBuffer) { - OC_LOG(ERROR, TAG, "PIN buffer is NULL"); + OIC_LOG(ERROR, TAG, "PIN buffer is NULL"); return OC_STACK_INVALID_PARAM; } - if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize) + if(g_PinOxmData.pinSize + 1 > bufferSize) { - OC_LOG(ERROR, TAG, "PIN buffer size is too small"); + OIC_LOG(ERROR, TAG, "PIN buffer size is too small"); return OC_STACK_INVALID_PARAM; } if(gInputPinCallback) { - gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1); + gInputPinCallback(pinBuffer, bufferSize); + OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer); + g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData)); } else { - OC_LOG(ERROR, TAG, "Invoke PIN callback failed!"); - OC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use PIN based OxM."); + OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!"); + OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM."); return OC_STACK_ERROR; } return OC_STACK_OK; } + +#ifdef MULTIPLE_OWNER +OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength) +{ + if(NULL == pinBuffer || OXM_PRECONFIG_PIN_MAX_SIZE < pinLength) + { + return OC_STACK_INVALID_PARAM; + } + + memcpy(g_PinOxmData.pinData, pinBuffer, pinLength); + g_PinOxmData.pinData[pinLength] = '\0'; + + return OC_STACK_OK; +} +#endif //MULTIPLE_OWNER + +#ifdef __WITH_DTLS__ + +void SetUuidForPinBasedOxm(const OicUuid_t* uuid) +{ + if(NULL != uuid) + { + memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH); + } +} + +int DerivePSKUsingPIN(uint8_t* result) +{ + int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)g_PinOxmData.pinData, + g_PinOxmData.pinSize, + g_PinOxmData.newDevice.id, + UUID_LENGTH, PBKDF_ITERATIONS, + OWNER_PSK_LENGTH_128, result); + + OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes); + OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData); + OIC_LOG(DEBUG, TAG, "UUID : "); + OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH); + return dtlsRes; +} + +int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type, + const unsigned char *UNUSED1, size_t UNUSED2, + unsigned char *result, size_t result_length) +{ + int32_t ret = -1; + + (void)UNUSED1; + (void)UNUSED2; + + if (NULL == result || result_length < OWNER_PSK_LENGTH_128) + { + return ret; + } + + switch (type) + { + case CA_DTLS_PSK_HINT: + case CA_DTLS_PSK_IDENTITY: + { + /** + * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279. + * + * At this point, The server generate random hint and + * provide it to client through server key exchange message. + */ + OCFillRandomMem(result, result_length); + ret = result_length; + OIC_LOG(DEBUG, TAG, "PSK HINT : "); + OIC_LOG_BUFFER(DEBUG, TAG, result, result_length); + } + break; + + case CA_DTLS_PSK_KEY: + { + if(0 == DerivePSKUsingPIN((uint8_t*)result)) + { + ret = OWNER_PSK_LENGTH_128; + } + else + { + OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN"); + ret = -1; + } + } + break; + + default: + { + OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t."); + ret = -1; + } + break; + } + return ret; +} + +#ifdef MULTIPLE_OWNER +int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type, + const unsigned char *UNUSED1, size_t UNUSED2, + unsigned char *result, size_t result_length) +{ + int32_t ret = -1; + + (void)UNUSED1; + (void)UNUSED2; + + if (NULL == result || result_length < OWNER_PSK_LENGTH_128) + { + return ret; + } + + const OicSecDoxm_t* doxm = GetDoxmResourceData(); + if(doxm) + { + switch (type) + { + case CA_DTLS_PSK_HINT: + case CA_DTLS_PSK_IDENTITY: + { + memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id)); + return (sizeof(doxm->deviceID.id)); + } + break; + + case CA_DTLS_PSK_KEY: + { + if(0 == DerivePSKUsingPIN((uint8_t*)result)) + { + ret = OWNER_PSK_LENGTH_128; + } + else + { + OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result"); + ret = -1; + } + } + break; + + default: + { + OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t."); + ret = -1; + } + break; + } + } + + return ret; +} + + +int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type, + const unsigned char *UNUSED1, size_t UNUSED2, + unsigned char *result, size_t result_length) +{ + int32_t ret = -1; + + (void)UNUSED1; + (void)UNUSED2; + + if (NULL == result || result_length < OWNER_PSK_LENGTH_128) + { + return ret; + } + + const OicSecDoxm_t* doxm = GetDoxmResourceData(); + if(doxm) + { + switch (type) + { + case CA_DTLS_PSK_HINT: + case CA_DTLS_PSK_IDENTITY: + { + /** + * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279. + * + * At this point, The server generate random hint and + * provide it to client through server key exchange message. + */ + OCFillRandomMem(result, result_length); + ret = result_length; + + OIC_LOG(DEBUG, TAG, "PSK HINT : "); + OIC_LOG_BUFFER(DEBUG, TAG, result, result_length); + } + break; + + case CA_DTLS_PSK_KEY: + { + OicUuid_t uuid; + memset(&uuid, 0x00, sizeof(uuid)); + OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id); + + //Load PreConfigured-PIN + const OicSecCred_t* cred = GetCredResourceData(&uuid); + if(cred) + { + char* pinBuffer = NULL; + uint32_t pinLength = 0; + if(OIC_ENCODING_RAW == cred->privateData.encoding) + { + pinBuffer = OICCalloc(1, cred->privateData.len + 1); + if(NULL == pinBuffer) + { + OIC_LOG (ERROR, TAG, "Failed to allocate memory"); + return ret; + } + pinLength = cred->privateData.len; + memcpy(pinBuffer, cred->privateData.data, pinLength); + } + else if(OIC_ENCODING_BASE64 == cred->privateData.encoding) + { + size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1)); + pinBuffer = OICCalloc(1, pinBufSize); + if(NULL == pinBuffer) + { + OIC_LOG (ERROR, TAG, "Failed to allocate memory"); + return ret; + } + + if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength)) + { + OIC_LOG (ERROR, TAG, "Failed to base64 decoding."); + return ret; + } + } + else + { + OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential."); + return ret; + } + + memcpy(g_PinOxmData.pinData, pinBuffer, pinLength); + OICFree(pinBuffer); + } + + if(0 == DerivePSKUsingPIN((uint8_t*)result)) + { + ret = OWNER_PSK_LENGTH_128; + } + else + { + OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result"); + ret = -1; + } + } + break; + + default: + { + OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t."); + ret = -1; + } + break; + } + } + + return ret; +} + + +int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type, + const unsigned char *UNUSED1, size_t UNUSED2, + unsigned char *result, size_t result_length) +{ + int32_t ret = -1; + + (void)UNUSED1; + (void)UNUSED2; + + if (NULL == result || result_length < OWNER_PSK_LENGTH_128) + { + return ret; + } + + const OicSecDoxm_t* doxm = GetDoxmResourceData(); + if(doxm) + { + switch (type) + { + case CA_DTLS_PSK_HINT: + case CA_DTLS_PSK_IDENTITY: + { + memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id)); + return (sizeof(doxm->deviceID.id)); + } + break; + case CA_DTLS_PSK_KEY: + { + OicUuid_t uuid; + memset(&uuid, 0x00, sizeof(uuid)); + OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id); + + //Load PreConfigured-PIN + const OicSecCred_t* cred = GetCredResourceData(&uuid); + if(cred) + { + char* pinBuffer = NULL; + uint32_t pinLength = 0; + if(OIC_ENCODING_RAW == cred->privateData.encoding) + { + pinBuffer = OICCalloc(1, cred->privateData.len + 1); + if(NULL == pinBuffer) + { + OIC_LOG (ERROR, TAG, "Failed to allocate memory"); + return ret; + } + pinLength = cred->privateData.len; + memcpy(pinBuffer, cred->privateData.data, pinLength); + } + else if(OIC_ENCODING_BASE64 == cred->privateData.encoding) + { + size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1)); + pinBuffer = OICCalloc(1, pinBufSize); + if(NULL == pinBuffer) + { + OIC_LOG (ERROR, TAG, "Failed to allocate memory"); + return ret; + } + + if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength)) + { + OIC_LOG (ERROR, TAG, "Failed to base64 decoding."); + return ret; + } + } + else + { + OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential."); + return ret; + } + + memcpy(g_PinOxmData.pinData, pinBuffer, pinLength); + OICFree(pinBuffer); + } + + if(0 == DerivePSKUsingPIN((uint8_t*)result)) + { + ret = OWNER_PSK_LENGTH_128; + } + else + { + OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result"); + ret = -1; + } + } + break; + + default: + { + OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t."); + ret = -1; + } + break; + } + } + + return ret; +} +#endif //MULTIPLE_OWNER + +#endif //__WITH_DTLS__