1 /* *****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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 * *****************************************************************/
24 #include "securevirtualresourcetypes.h"
25 #include "doxmresource.h"
26 #include "credresource.h"
28 #include "cainterface.h"
30 #include "oic_malloc.h"
34 #include "oxmrawpublickey.h"
35 #include "ownershiptransfermanager.h"
36 #include "oxmverifycommon.h"
37 #include "mbedtls/ctr_drbg.h"
38 #include "mbedtls/entropy.h"
39 #include "mbedtls/ssl_internal.h"
41 #define TAG "OIC_OXM_RawPubKey"
43 typedef struct RPKOxmData {
44 char rpkData[OXM_RPK_MASTER_KEY_MAX_SIZE + 1];
49 static RPKOxmData_t g_RPKOxmData = {
54 static GetRPKMasterKeyCallback gGetRPKMasterKeyCallback = NULL;
56 void SetInputRPKMasterKeyCB(GetRPKMasterKeyCallback rpkCB)
60 OIC_LOG(ERROR, TAG, "Failed to set callback for rpk.");
64 gGetRPKMasterKeyCallback = rpkCB;
67 void UnsetRPKMasterKeyCB()
69 gGetRPKMasterKeyCallback = NULL;
72 OCStackResult CreateRPKBasedSelectOxmPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
74 if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
76 return OC_STACK_INVALID_PARAM;
79 otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RAW_PUB_KEY;
81 return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
84 OCStackResult CreateRPKBasedOwnerTransferPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
86 if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
88 return OC_STACK_INVALID_PARAM;
91 OicUuid_t uuidPT = {.id={0}};
95 if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
97 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
98 return OC_STACK_ERROR;
100 memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
102 return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
105 OCStackResult GetMasterRPK(char* master, size_t* master_len)
107 if(!master || !master_len)
109 OIC_LOG(ERROR, TAG, "RPK buffer is NULL");
110 return OC_STACK_INVALID_PARAM;
113 if(gGetRPKMasterKeyCallback)
115 gGetRPKMasterKeyCallback(g_RPKOxmData.rpkData, &g_RPKOxmData.rpkSize);
119 OIC_LOG(ERROR, TAG, "Invoke RPK callback failed!");
120 OIC_LOG(ERROR, TAG, "Callback for input RPK should be registered to use Random RPK based OxM.");
121 return OC_STACK_ERROR;
127 void SetUuidForRPKBasedOxm(const OicUuid_t* uuid)
131 memcpy(g_RPKOxmData.newDevice.id, uuid->id, UUID_LENGTH);
135 int DerivePSKUsingRPK(uint8_t* result)
137 int dtlsRes = DeriveCryptoKeyFromPassword(
138 (const unsigned char *)g_RPKOxmData.rpkData,
139 g_RPKOxmData.rpkSize,
140 g_RPKOxmData.newDevice.id,
141 UUID_LENGTH, PBKDF_ITERATIONS,
142 OWNER_PSK_LENGTH_128, result);
144 OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
145 OIC_LOG_V(DEBUG, TAG, "RPK : %s", g_RPKOxmData.rpkData);
146 OIC_LOG(DEBUG, TAG, "UUID : ");
147 OIC_LOG_BUFFER(DEBUG, TAG, g_RPKOxmData.newDevice.id, UUID_LENGTH);
151 int32_t GetDtlsPskForRPKOxm( CADtlsPskCredType_t type,
152 const unsigned char *UNUSED1, size_t UNUSED2,
153 unsigned char *result, size_t result_length)
160 if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
167 case CA_DTLS_PSK_HINT:
168 case CA_DTLS_PSK_IDENTITY:
171 * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
173 * At this point, The server generate random hint and
174 * provide it to client through server key exchange message.
176 OCFillRandomMem(result, result_length);
178 OIC_LOG(DEBUG, TAG, "PSK HINT : ");
179 OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
183 case CA_DTLS_PSK_KEY:
185 if(0 == DerivePSKUsingRPK((uint8_t*)result))
187 ret = OWNER_PSK_LENGTH_128;
191 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from RPK");
199 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
207 OCStackResult GetMasterRPKCallback(OTMContext_t *otmCtx)
209 if (!otmCtx || !otmCtx->selectedDeviceInfo)
211 return OC_STACK_INVALID_PARAM;
214 uint8_t rpkData[OXM_RPK_MASTER_KEY_MAX_SIZE + 1] = {0};
216 OCStackResult res = OC_STACK_ERROR;
218 res = GetMasterRPK((char*)rpkData, &rpkLen);
220 if (OC_STACK_OK != res)
222 OIC_LOG(ERROR, TAG, "Failed to generate RPK master key");
223 SetResult(otmCtx, res);
228 * Since PSK will be used directly while RPK based ownership transfer,
229 * Credential should not be saved into SVR.
230 * For this reason, We will use a temporary get_psk_info callback to random RPK OxM.
233 if(!(otmCtx->selectedDeviceInfo->doxm->owned))
235 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRPKOxm))
237 OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random raw public key OxM.");
238 res = OC_STACK_ERROR;
242 //Set the device id to derive temporal PSK
243 SetUuidForRPKBasedOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
248 OCStackResult CreateSecureSessionRPKCallback(OTMContext_t* otmCtx)
250 OIC_LOG(INFO, TAG, "IN CreateSecureSessionRPKCallback");
252 if (!otmCtx || !otmCtx->selectedDeviceInfo)
254 return OC_STACK_INVALID_PARAM;
257 CAResult_t caresult = CAEnableAnonECDHCipherSuite(false);
258 if (CA_STATUS_OK != caresult)
260 OIC_LOG_V(ERROR, TAG, "Unable to disable anon cipher suite");
261 return OC_STACK_ERROR;
263 OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
265 caresult = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, otmCtx->selectedDeviceInfo->endpoint.adapter);
266 if (CA_STATUS_OK != caresult)
268 OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
269 return OC_STACK_ERROR;
271 OIC_LOG(INFO, TAG, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 cipher suite selected.");
273 OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
274 CAEndpoint_t endpoint;
275 memcpy(&endpoint, &selDevInfo->endpoint, sizeof(CAEndpoint_t));
277 if(CA_ADAPTER_IP == endpoint.adapter)
279 endpoint.port = selDevInfo->securePort;
280 caresult = CAInitiateHandshake(&endpoint);
282 else if (CA_ADAPTER_GATT_BTLE == endpoint.adapter)
284 caresult = CAInitiateHandshake(&endpoint);
289 endpoint.port = selDevInfo->tcpPort;
290 caresult = CAinitiateSslHandshake(&endpoint);
293 if (CA_STATUS_OK != caresult)
295 OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
296 return OC_STACK_ERROR;
299 OIC_LOG(INFO, TAG, "OUT CreateSecureSessionRPKCallback");