Merge branch 'master' into simulator
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / ownershiptransfermanager.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * *****************************************************************/
20
21 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1b, Real-time extensions
24 // (IEEE Std 1003.1b-1993) specification
25 //
26 // For this specific file, see use of clock_gettime,
27 // Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
28 // and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
29 #ifndef _POSIX_C_SOURCE
30 #define _POSIX_C_SOURCE 200809L
31 #endif
32
33 #include <time.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <stdbool.h>
37 #include <string.h>
38
39 #include "logger.h"
40 #include "oic_malloc.h"
41 #include "oic_string.h"
42 #include "cacommon.h"
43 #include "cainterface.h"
44 #include "base64.h"
45 #include "cJSON.h"
46
47 #include "srmresourcestrings.h"
48 #include "doxmresource.h"
49 #include "pstatresource.h"
50 #include "credresource.h"
51 #include "aclresource.h"
52 #include "ownershiptransfermanager.h"
53 #include "securevirtualresourcetypes.h"
54 #include "oxmjustworks.h"
55 #include "pmtypes.h"
56 #include "pmutility.h"
57 #include "srmutility.h"
58 #include "provisioningdatabasemanager.h"
59 #include "oxmrandompin.h"
60
61 #define TAG "OTM"
62
63 /**
64  * Array to store the callbacks for each owner transfer method.
65  */
66 static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
67
68 /**
69  * Variable for storing provisioning tool's provisioning capabilities
70  * Must be in decreasing order of preference. More prefered method should
71  * have lower array index.
72  */
73 static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
74
75 /**
76  * Number of supported provisioning methods
77  * current version supports only one.
78  */
79 static size_t gNumOfProvisioningMethodsPT = 1;
80
81 /**
82  * Function to getting string of ownership transfer method
83  */
84 static const char* GetOxmString(OicSecOxm_t oxmType)
85 {
86     switch(oxmType)
87     {
88         case OIC_JUST_WORKS:
89             return OXM_JUST_WORKS;
90         case OIC_MODE_SWITCH:
91             return OXM_MODE_SWITCH;
92         case OIC_RANDOM_DEVICE_PIN:
93             return OXM_RANDOM_DEVICE_PIN;
94         case OIC_PRE_PROVISIONED_DEVICE_PIN:
95             return OXM_PRE_PROVISIONED_DEVICE_PIN;
96         case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
97             return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
98         default:
99             return NULL;
100     }
101 }
102
103 /**
104  * Function to select appropriate  provisioning method.
105  *
106  * @param[in] supportedMethods   Array of supported methods
107  * @param[in] numberOfMethods   number of supported methods
108  * @param[out]  selectedMethod         Selected methods
109  * @return  OC_STACK_OK on success
110  */
111 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
112                                                             size_t numberOfMethods,
113                                                             OicSecOxm_t *selectedMethod)
114 {
115     OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
116
117     if(numberOfMethods == 0 || !supportedMethods)
118     {
119         OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
120         return OC_STACK_ERROR;
121     }
122
123     *selectedMethod  = supportedMethods[0];
124     for(size_t i = 0; i < numberOfMethods; i++)
125     {
126         if(*selectedMethod < supportedMethods[i])
127         {
128             *selectedMethod =  supportedMethods[i];
129         }
130     }
131
132     return OC_STACK_OK;
133 }
134
135 /**
136  * Function to select operation mode.This function will return most secure common operation mode.
137  *
138  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
139  * @param[out]   selectedMode   selected operation mode
140  * @return  OC_STACK_OK on success
141  */
142 static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
143                                 OicSecDpom_t *selectedMode)
144 {
145     OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
146
147     size_t i = 0;
148     size_t j = 0;
149
150     while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
151     {
152         if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
153         {
154             i++;
155         }
156         else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
157         {
158             j++;
159         }
160         else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
161         {
162             *selectedMode = gProvisioningToolCapability[j];
163             break;
164         }
165     }
166     OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
167 }
168
169 /**
170  * Function to update owner transfer mode
171  *
172  * @param[in]  otmCtx  Context value of ownership transfer.
173  * @return  OC_STACK_OK on success
174  */
175 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
176
177 /**
178  * Function to send request to resource to get its pstat resource information.
179  *
180  * @param[in]  otmCtx  Context value of ownership transfer.
181  * @return  OC_STACK_OK on success
182  */
183 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
184
185
186 /**
187  * Function to send ownerShip info. This function would update Owned as true and
188  * owner as UUID for provisioning tool
189  *
190  * @param[in]  otmCtx  Context value of ownership transfer.
191  * @return  OC_STACK_OK on success
192  */
193 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
194
195 /**
196  * Function to update the operation mode. As per the spec. Operation mode in client driven
197  * single service provisioning it will be updated to 0x3
198  *
199  * @param[in]  otmCtx  Context value of ownership transfer.
200  * @param[in] selectedOperationMode selected operation mode
201  * @return  OC_STACK_OK on success
202  */
203 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
204                                     OicSecDpom_t selectedOperationMode);
205
206 /**
207  * Function to start ownership transfer.
208  * This function will send the first request for provisioning,
209  * The next request message is sent from the response handler for this request.
210  *
211  * @param[in] ctx   context value passed to callback from calling function.
212  * @param[in] selectedDevice   selected device information to performing provisioning.
213  * @return  OC_STACK_OK on success
214  */
215 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
216
217 /*
218  * Function to finalize provisioning.
219  * This function will send default ACL and commit hash.
220  *
221  * @param[in] otmCtx   Context value of ownership transfer.
222  * @return  OC_STACK_OK on success
223  */
224 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
225
226
227 static bool IsComplete(OTMContext_t* otmCtx)
228 {
229     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
230     {
231         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
232         {
233             return false;
234         }
235     }
236
237     return true;
238 }
239
240 /**
241  * Function to save the result of provisioning.
242  *
243  * @param[in,out] otmCtx   Context value of ownership transfer.
244  * @param[in] res   result of provisioning
245  */
246 static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
247 {
248     OC_LOG(DEBUG, TAG, "IN SetResult");
249
250     if(!otmCtx)
251     {
252         OC_LOG(WARNING, TAG, "OTMContext is NULL");
253         return;
254     }
255
256     if(otmCtx->selectedDeviceInfo)
257     {
258         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
259         {
260             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
261                       otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
262             {
263                 otmCtx->ctxResultArray[i].res = res;
264                 if(OC_STACK_OK != res)
265                 {
266                     otmCtx->ctxHasError = true;
267                 }
268             }
269         }
270
271         //If all request is completed, invoke the user callback.
272         if(IsComplete(otmCtx))
273         {
274             otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
275                                        otmCtx->ctxResultArray, otmCtx->ctxHasError);
276             OICFree(otmCtx->ctxResultArray);
277             OICFree(otmCtx);
278         }
279         else
280         {
281             if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
282                                                      otmCtx->selectedDeviceInfo->next))
283             {
284                 OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
285             }
286         }
287     }
288
289     OC_LOG(DEBUG, TAG, "OUT SetResult");
290 }
291
292
293 /**
294  * Function to save ownerPSK at provisioning tool end.
295  *
296  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
297  * @return  OC_STACK_OK on success
298  */
299 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
300 {
301     OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
302
303     OCStackResult res = OC_STACK_ERROR;
304
305     CAEndpoint_t endpoint;
306     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
307     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
308     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
309     endpoint.port = selectedDeviceInfo->securePort;
310
311     OicUuid_t ptDeviceID = {.id={0}};
312     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
313     {
314         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
315         return res;
316     }
317
318     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
319
320     //Generating OwnerPSK
321     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
322             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
323             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
324             sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
325             sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
326             OWNER_PSK_LENGTH_128);
327
328     if (CA_STATUS_OK == pskRet)
329     {
330         OC_LOG(INFO, TAG,"ownerPSK dump:\n");
331         OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
332         //Generating new credential for provisioning tool
333         size_t ownLen = 1;
334         uint32_t outLen = 0;
335
336         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
337         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
338                 &outLen);
339         VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
340
341         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
342                 SYMMETRIC_PAIR_WISE_KEY, NULL,
343                 base64Buff, ownLen, &ptDeviceID);
344         VERIFY_NON_NULL(TAG, cred, ERROR);
345
346         res = AddCredential(cred);
347         if(res != OC_STACK_OK)
348         {
349             DeleteCredList(cred);
350             return res;
351         }
352     }
353     else
354     {
355         OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
356     }
357
358     OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
359 exit:
360     return res;
361 }
362
363 /**
364  * Callback handler for OwnerShipTransferModeHandler API.
365  *
366  * @param[in] ctx             ctx value passed to callback from calling function.
367  * @param[in] UNUSED          handle to an invocation
368  * @param[in] clientResponse  Response from queries to remote servers.
369  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
370  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
371  */
372 static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
373                                                          OCClientResponse *clientResponse)
374 {
375     OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
376
377     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
378     VERIFY_NON_NULL(TAG, ctx, WARNING);
379
380     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
381     (void)UNUSED;
382     if(clientResponse->result == OC_STACK_OK)
383     {
384         OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
385         //Send request : GET /oic/sec/pstat
386         OCStackResult res = GetProvisioningStatusResource(otmCtx);
387         if(OC_STACK_OK != res)
388         {
389             OC_LOG(WARNING, TAG, "Failed to get pstat information");
390             SetResult(otmCtx, res);
391         }
392     }
393     else
394     {
395         OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
396         clientResponse->result);
397         SetResult(otmCtx, clientResponse->result);
398     }
399
400     OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
401
402 exit:
403     return  OC_STACK_DELETE_TRANSACTION;
404 }
405
406 /**
407  * Callback handler for ProvisioningStatusResouceHandler API.
408  *
409  * @param[in] ctx             ctx value passed to callback from calling function.
410  * @param[in] UNUSED          handle to an invocation
411  * @param[in] clientResponse  Response from queries to remote servers.
412  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
413  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
414  */
415 static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
416                                                     OCClientResponse *clientResponse)
417 {
418     OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
419
420     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
421     VERIFY_NON_NULL(TAG, ctx, WARNING);
422
423     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
424     (void)UNUSED;
425     if  (OC_STACK_OK == clientResponse->result)
426     {
427         if  (NULL == clientResponse->payload)
428         {
429             OC_LOG(INFO, TAG, "Skiping Null payload");
430             SetResult(otmCtx, OC_STACK_ERROR);
431             return OC_STACK_DELETE_TRANSACTION;
432         }
433
434         if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
435         {
436             OC_LOG(INFO, TAG, "Unknown payload type");
437             SetResult(otmCtx, OC_STACK_ERROR);
438             return OC_STACK_DELETE_TRANSACTION;
439         }
440
441         OicSecPstat_t* pstat = JSONToPstatBin(
442                 ((OCSecurityPayload*)clientResponse->payload)->securityData);
443         if(NULL == pstat)
444         {
445             OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
446             SetResult(otmCtx, OC_STACK_ERROR);
447             return OC_STACK_DELETE_TRANSACTION;
448         }
449         otmCtx->selectedDeviceInfo->pstat = pstat;
450
451         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
452         OicSecDpom_t selectedOperationMode;
453         SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
454
455         //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
456         OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
457         if (OC_STACK_OK != res)
458         {
459             OC_LOG(ERROR, TAG, "Error while updating operation mode.");
460             SetResult(otmCtx, res);
461         }
462     }
463     else
464     {
465         OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
466             clientResponse->result);
467         SetResult(otmCtx, clientResponse->result);
468     }
469
470     OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
471 exit:
472     return  OC_STACK_DELETE_TRANSACTION;
473 }
474
475 /**
476  * Callback handler for OwnershipInformationHandler API.
477  *
478  * @param[in] ctx             ctx value passed to callback from calling function.
479  * @param[in] UNUSED          handle to an invocation
480  * @param[in] clientResponse  Response from queries to remote servers.
481  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
482  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
483  */
484 static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
485                                 OCClientResponse *clientResponse)
486 {
487     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
488     VERIFY_NON_NULL(TAG, ctx, WARNING);
489
490     OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
491     (void)UNUSED;
492     OCStackResult res = OC_STACK_OK;
493     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
494     if  (OC_STACK_OK == clientResponse->result)
495     {
496         if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
497         {
498             res = RemoveCredential(&otmCtx->subIdForPinOxm);
499             if(OC_STACK_RESOURCE_DELETED != res)
500             {
501                 OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
502                 return OC_STACK_DELETE_TRANSACTION;
503             }
504         }
505
506         res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
507         if(OC_STACK_OK != res)
508         {
509             OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
510             SetResult(otmCtx, res);
511             return OC_STACK_DELETE_TRANSACTION;
512         }
513
514         CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
515         endpoint->port = otmCtx->selectedDeviceInfo->securePort;
516         CAResult_t closeRes = CACloseDtlsSession(endpoint);
517         if(CA_STATUS_OK != closeRes)
518         {
519             OC_LOG(ERROR, TAG, "Failed to close DTLS session");
520             SetResult(otmCtx, closeRes);
521             return OC_STACK_DELETE_TRANSACTION;
522         }
523
524         OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
525         OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
526
527         res = FinalizeProvisioning(otmCtx);
528         if(OC_STACK_OK != res)
529         {
530             SetResult(otmCtx, res);
531         }
532     }
533     else
534     {
535         res = clientResponse->result;
536     }
537
538     OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
539
540 exit:
541     return  OC_STACK_DELETE_TRANSACTION;
542 }
543
544 /**
545  * Response handler for update operation mode.
546  *
547  * @param[in] ctx             ctx value passed to callback from calling function.
548  * @param[in] UNUSED          handle to an invocation
549  * @param[in] clientResponse  Response from queries to remote servers.
550  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
551  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
552  */
553 static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
554                                 OCClientResponse *clientResponse)
555 {
556     OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
557
558     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
559     VERIFY_NON_NULL(TAG, ctx, WARNING);
560
561     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
562     (void) UNUSED;
563     if  (OC_STACK_OK == clientResponse->result)
564     {
565         OCStackResult res = OC_STACK_ERROR;
566         OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
567         //DTLS Handshake
568         //Load secret for temporal secure session.
569         if(g_OTMDatas[selOxm].loadSecretCB)
570         {
571             res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
572             if(OC_STACK_OK != res)
573             {
574                 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
575                 SetResult(otmCtx, res);
576                 return  OC_STACK_DELETE_TRANSACTION;
577             }
578         }
579
580         //Try DTLS handshake to generate secure session
581         if(g_OTMDatas[selOxm].createSecureSessionCB)
582         {
583             res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
584             if(OC_STACK_OK != res)
585             {
586                 OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
587                 SetResult(otmCtx, res);
588                 return OC_STACK_DELETE_TRANSACTION;
589             }
590         }
591
592         //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
593         res = PutOwnershipInformation(otmCtx);
594         if(OC_STACK_OK != res)
595         {
596             OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
597             SetResult(otmCtx, res);
598         }
599     }
600     else
601     {
602         OC_LOG(ERROR, TAG, "Error while update operation mode");
603         SetResult(otmCtx, clientResponse->result);
604     }
605
606     OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
607
608 exit:
609     return  OC_STACK_DELETE_TRANSACTION;
610 }
611
612
613 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
614 {
615     OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
616
617     if(!otmCtx || !otmCtx->selectedDeviceInfo)
618     {
619         OC_LOG(ERROR, TAG, "Invalid parameters");
620         return OC_STACK_INVALID_PARAM;
621     }
622
623     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
624     OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
625     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
626
627     if(!PMGenerateQuery(false,
628                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
629                         deviceInfo->connType,
630                         query, sizeof(query), OIC_RSRC_DOXM_URI))
631     {
632         OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
633         return OC_STACK_ERROR;
634     }
635     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
636     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
637     if(!secPayload)
638     {
639         OC_LOG(ERROR, TAG, "Failed to memory allocation");
640         return OC_STACK_NO_MEMORY;
641     }
642     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
643     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
644     if (NULL == secPayload->securityData)
645     {
646         OICFree(secPayload);
647         OC_LOG(ERROR, TAG, "Error while converting bin to json");
648         return OC_STACK_ERROR;
649     }
650     OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
651
652     OCCallbackData cbData;
653     cbData.cb = &OwnerTransferModeHandler;
654     cbData.context = (void *)otmCtx;
655     cbData.cd = NULL;
656     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
657                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
658                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
659     if (res != OC_STACK_OK)
660     {
661         OC_LOG(ERROR, TAG, "OCStack resource error");
662     }
663
664     OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
665
666     return res;
667 }
668
669 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
670 {
671     OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
672
673     if(!otmCtx || !otmCtx->selectedDeviceInfo)
674     {
675         OC_LOG(ERROR, TAG, "Invailed parameters");
676         return OC_STACK_INVALID_PARAM;
677     }
678
679     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
680     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
681     if(!PMGenerateQuery(false,
682                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
683                         deviceInfo->connType,
684                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
685     {
686         OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
687         return OC_STACK_ERROR;
688     }
689     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
690
691     OCCallbackData cbData;
692     cbData.cb = &ListMethodsHandler;
693     cbData.context = (void *)otmCtx;
694     cbData.cd = NULL;
695     OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
696                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
697     if (res != OC_STACK_OK)
698     {
699         OC_LOG(ERROR, TAG, "OCStack resource error");
700     }
701
702     OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
703
704     return res;
705 }
706
707
708 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
709 {
710     OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
711
712     if(!otmCtx || !otmCtx->selectedDeviceInfo)
713     {
714         OC_LOG(ERROR, TAG, "Invailed parameters");
715         return OC_STACK_INVALID_PARAM;
716     }
717
718     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
719     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
720     if(!PMGenerateQuery(true,
721                         deviceInfo->endpoint.addr, deviceInfo->securePort,
722                         deviceInfo->connType,
723                         query, sizeof(query), OIC_RSRC_DOXM_URI))
724     {
725         OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
726         return OC_STACK_ERROR;
727     }
728     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
729
730     //OwnershipInformationHandler
731     OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
732     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
733     if(!secPayload)
734     {
735         OC_LOG(ERROR, TAG, "Failed to memory allocation");
736         return OC_STACK_NO_MEMORY;
737     }
738     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
739     secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
740     if (NULL == secPayload->securityData)
741     {
742         OICFree(secPayload);
743         OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
744         return OC_STACK_INVALID_PARAM;
745     }
746
747     OCCallbackData cbData;
748     cbData.cb = &OwnershipInformationHandler;
749     cbData.context = (void *)otmCtx;
750     cbData.cd = NULL;
751     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
752                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
753     if (res != OC_STACK_OK)
754     {
755         OC_LOG(ERROR, TAG, "OCStack resource error");
756     }
757
758     OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
759
760     return res;
761 }
762
763 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
764                                     OicSecDpom_t selectedOperationMode)
765 {
766     OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
767
768     if(!otmCtx || !otmCtx->selectedDeviceInfo)
769     {
770         return OC_STACK_INVALID_PARAM;
771     }
772
773     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
774     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
775     if(!PMGenerateQuery(false,
776                         deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
777                         deviceInfo->connType,
778                         query, sizeof(query), OIC_RSRC_PSTAT_URI))
779     {
780         OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
781         return OC_STACK_ERROR;
782     }
783     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
784
785     deviceInfo->pstat->om = selectedOperationMode;
786
787     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
788     if(!secPayload)
789     {
790         OC_LOG(ERROR, TAG, "Failed to memory allocation");
791         return OC_STACK_NO_MEMORY;
792     }
793     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
794     secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
795     if (NULL == secPayload->securityData)
796     {
797         OICFree(secPayload);
798         OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
799         return OC_STACK_INVALID_PARAM;
800     }
801
802     OCCallbackData cbData;
803     cbData.cb = &OperationModeUpdateHandler;
804     cbData.context = (void *)otmCtx;
805     cbData.cd = NULL;
806     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
807                                      deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
808     if (res != OC_STACK_OK)
809     {
810         OC_LOG(ERROR, TAG, "OCStack resource error");
811     }
812
813     OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
814
815     return res;
816 }
817
818 static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
819 {
820     OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
821     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
822     otmCtx->selectedDeviceInfo = selectedDevice;
823
824     //Set to the lowest level OxM, and then find more higher level OxM.
825     OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
826                                                  selectedDevice->doxm->oxmLen,
827                                                  &selectedDevice->doxm->oxmSel);
828     if(OC_STACK_OK != res)
829     {
830         OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
831         SetResult(otmCtx, res);
832         return res;
833     }
834     OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
835
836     //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
837     res = PutOwnerTransferModeToResource(otmCtx);
838     if(OC_STACK_OK != res)
839     {
840         OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
841         SetResult(otmCtx, res);
842         return res;
843     }
844
845     OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
846
847     return res;
848
849 }
850
851 OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
852 {
853     OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
854
855     if(!data)
856     {
857         OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
858         return OC_STACK_INVALID_PARAM;
859     }
860     if(oxmType >= OIC_OXM_COUNT)
861     {
862         OC_LOG(INFO, TAG, "Unknow ownership transfer method");
863         return OC_STACK_INVALID_PARAM;
864     }
865
866     g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
867     g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
868     g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
869     g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
870
871     OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
872
873     return OC_STACK_OK;
874 }
875
876 /**
877  * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
878  */
879 OCStackResult OTMDoOwnershipTransfer(void* ctx,
880                                      OCProvisionDev_t *selectedDevicelist,
881                                      OCProvisionResultCB resultCallback)
882 {
883     OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
884
885     if (NULL == selectedDevicelist || NULL == resultCallback )
886     {
887         return OC_STACK_INVALID_PARAM;
888     }
889
890     OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
891     if(!otmCtx)
892     {
893         OC_LOG(ERROR, TAG, "Failed to create OTM Context");
894         return OC_STACK_NO_MEMORY;
895     }
896     otmCtx->ctxResultCallback = resultCallback;
897     otmCtx->ctxHasError = false;
898     otmCtx->userCtx = ctx;
899     OCProvisionDev_t* pCurDev = selectedDevicelist;
900
901     //Counting number of selected devices.
902     otmCtx->ctxResultArraySize = 0;
903     while(NULL != pCurDev)
904     {
905         otmCtx->ctxResultArraySize++;
906         pCurDev = pCurDev->next;
907     }
908
909     otmCtx->ctxResultArray =
910         (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
911     if(NULL == otmCtx->ctxResultArray)
912     {
913         OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
914         OICFree(otmCtx);
915         return OC_STACK_NO_MEMORY;
916     }
917     pCurDev = selectedDevicelist;
918
919     //Fill the device UUID for result array.
920     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
921     {
922         //Checking duplication of Device ID.
923         if(true == PDMIsDuplicateDevice(&pCurDev->doxm->deviceID))
924         {
925             OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicate");
926             OICFree(otmCtx->ctxResultArray);
927             OICFree(otmCtx);
928             return OC_STACK_INVALID_PARAM;
929         }
930         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
931                pCurDev->doxm->deviceID.id,
932                UUID_LENGTH);
933         otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
934         pCurDev = pCurDev->next;
935     }
936     StartOwnershipTransfer(otmCtx, selectedDevicelist);
937
938     OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
939     return OC_STACK_OK;
940 }
941
942 /**
943  * Callback handler of SRPFinalizeProvisioning.
944  *
945  * @param[in] ctx             ctx value passed to callback from calling function.
946  * @param[in] UNUSED          handle to an invocation
947  * @param[in] clientResponse  Response from queries to remote servers.
948  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
949  *          and OC_STACK_KEEP_TRANSACTION to keep it.
950  */
951 static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
952                                                        OCClientResponse *clientResponse)
953 {
954     OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
955
956     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
957     VERIFY_NON_NULL(TAG, ctx, ERROR);
958
959     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
960     (void)UNUSED;
961     if(OC_STACK_OK == clientResponse->result)
962     {
963         OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
964
965          if (OC_STACK_OK == res)
966          {
967                 OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
968                 SetResult(otmCtx, OC_STACK_OK);
969                 return OC_STACK_DELETE_TRANSACTION;
970          }
971          else
972          {
973               OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
974          }
975     }
976 exit:
977     return OC_STACK_DELETE_TRANSACTION;
978 }
979
980 /**
981  * Callback handler of default ACL provisioning.
982  *
983  * @param[in] ctx             ctx value passed to callback from calling function.
984  * @param[in] UNUSED          handle to an invocation
985  * @param[in] clientResponse  Response from queries to remote servers.
986  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
987  *          and OC_STACK_KEEP_TRANSACTION to keep it.
988  */
989 static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
990                                                        OCClientResponse *clientResponse)
991 {
992     OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
993
994     VERIFY_NON_NULL(TAG, clientResponse, ERROR);
995     VERIFY_NON_NULL(TAG, ctx, ERROR);
996
997     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
998     (void)UNUSED;
999
1000     if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
1001     {
1002         OC_LOG_V(INFO, TAG, "Staring commit hash task.");
1003         // TODO hash currently have fixed value 0.
1004         uint16_t aclHash = 0;
1005         otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
1006         otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
1007         OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1008         if(!secPayload)
1009         {
1010             OC_LOG(ERROR, TAG, "Failed to memory allocation");
1011             return OC_STACK_NO_MEMORY;
1012         }
1013         secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1014         secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
1015         if (NULL == secPayload->securityData)
1016         {
1017             OICFree(secPayload);
1018             SetResult(otmCtx, OC_STACK_INVALID_JSON);
1019             return OC_STACK_DELETE_TRANSACTION;
1020         }
1021         OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
1022
1023         char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1024         if(!PMGenerateQuery(true,
1025                             otmCtx->selectedDeviceInfo->endpoint.addr,
1026                             otmCtx->selectedDeviceInfo->securePort,
1027                             otmCtx->selectedDeviceInfo->connType,
1028                             query, sizeof(query), OIC_RSRC_PSTAT_URI))
1029         {
1030             OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
1031             return OC_STACK_ERROR;
1032         }
1033         OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1034
1035         OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1036         cbData.cb = &FinalizeProvisioningCB;
1037         cbData.context = (void*)otmCtx;
1038         cbData.cd = NULL;
1039         OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
1040                 otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1041         OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
1042         if (ret != OC_STACK_OK)
1043         {
1044             OC_LOG(ERROR, TAG, "OCStack resource error");
1045             SetResult(otmCtx, ret);
1046         }
1047     }
1048     else
1049     {
1050         OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
1051                             clientResponse->result);
1052         SetResult(otmCtx, clientResponse->result);
1053     }
1054 exit:
1055     return OC_STACK_DELETE_TRANSACTION;
1056 }
1057
1058
1059 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
1060 {
1061     OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
1062
1063     if(!otmCtx)
1064     {
1065         OC_LOG(ERROR, TAG, "OTMContext is NULL");
1066         return OC_STACK_INVALID_PARAM;
1067     }
1068     if(!otmCtx->selectedDeviceInfo)
1069     {
1070         OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
1071         OICFree(otmCtx);
1072         return OC_STACK_INVALID_PARAM;
1073     }
1074     // Provision Default ACL to device
1075     OicSecAcl_t defaultAcl =
1076     { {.id={0}},
1077         1,
1078         NULL,
1079         0x001F,
1080         0,
1081         NULL,
1082         NULL,
1083         1,
1084         NULL,
1085         NULL,
1086     };
1087
1088     OicUuid_t provTooldeviceID = {.id={0}};
1089     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1090     {
1091         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1092         SetResult(otmCtx, OC_STACK_ERROR);
1093         return OC_STACK_ERROR;
1094     }
1095     OC_LOG(INFO, TAG, "Retieved deviceID");
1096     memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
1097     char *wildCardResource = "*";
1098     defaultAcl.resources = &wildCardResource;
1099
1100     defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
1101     if(!defaultAcl.owners)
1102     {
1103         OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
1104         SetResult(otmCtx, OC_STACK_NO_MEMORY);
1105         return OC_STACK_NO_MEMORY;
1106     }
1107     memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
1108     OC_LOG(INFO, TAG, "Provisioning default ACL");
1109
1110     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1111     if(!secPayload)
1112     {
1113         OC_LOG(ERROR, TAG, "Failed to memory allocation");
1114         return OC_STACK_NO_MEMORY;
1115     }
1116     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1117     secPayload->securityData = BinToAclJSON(&defaultAcl);
1118     OICFree(defaultAcl.owners);
1119     if(!secPayload->securityData)
1120     {
1121         OICFree(secPayload);
1122         OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
1123         SetResult(otmCtx, OC_STACK_ERROR);
1124         return OC_STACK_ERROR;
1125     }
1126     OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
1127
1128     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1129     if(!PMGenerateQuery(true,
1130                         otmCtx->selectedDeviceInfo->endpoint.addr,
1131                         otmCtx->selectedDeviceInfo->securePort,
1132                         otmCtx->selectedDeviceInfo->connType,
1133                         query, sizeof(query), OIC_RSRC_ACL_URI))
1134     {
1135         OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
1136         return OC_STACK_ERROR;
1137     }
1138     OC_LOG_V(DEBUG, TAG, "Query=%s", query);
1139
1140     OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
1141
1142     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
1143     cbData.cb = &ProvisionDefaultACLCB;
1144     cbData.context = (void *)otmCtx;
1145     cbData.cd = NULL;
1146     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
1147             &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1148             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1149     if (OC_STACK_OK != ret)
1150     {
1151         SetResult(otmCtx, ret);
1152         return ret;
1153     }
1154
1155     OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");
1156
1157     return ret;
1158
1159 }
1160