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