replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / oxmrandompin.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 #include <memory.h>
22
23 #include "ocstack.h"
24 #include "securevirtualresourcetypes.h"
25 #include "doxmresource.h"
26 #include "credresource.h"
27 #include "cacommon.h"
28 #include "cainterface.h"
29 #include "ocrandom.h"
30 #include "oic_malloc.h"
31 #include "logger.h"
32 #include "pbkdf2.h"
33 #include "base64.h"
34 #include "oxmrandompin.h"
35 #include "ownershiptransfermanager.h"
36 #include "pinoxmcommon.h"
37 #include "oxmverifycommon.h"
38
39 #define TAG "OIC_OXM_RandomPIN"
40
41 typedef enum PinState{
42     PIN_INPUT_READY = 0,
43     PIN_INPUT_WAIT = 1,
44     PIN_INPUT_SUCCESS = 2,
45     PIN_INPUT_FAIL = 3
46 } PinState_t;
47
48 static PinState_t gPinState = PIN_INPUT_READY;
49
50 OCStackResult CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
51 {
52     if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
53     {
54         return OC_STACK_INVALID_PARAM;
55     }
56
57     otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RANDOM_DEVICE_PIN;
58
59     return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
60 }
61
62 OCStackResult CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
63 {
64     if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
65     {
66         return OC_STACK_INVALID_PARAM;
67     }
68
69     OicUuid_t uuidPT = {.id={0}};
70     *payload = NULL;
71     *size = 0;
72
73     if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
74     {
75         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
76         return OC_STACK_ERROR;
77     }
78     memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
79
80     return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
81 }
82
83 OCStackResult InputPinCodeCallback(OTMContext_t *otmCtx)
84 {
85     if (!otmCtx || !otmCtx->selectedDeviceInfo)
86     {
87         return OC_STACK_INVALID_PARAM;
88     }
89
90     uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
91     OCStackResult res = OC_STACK_ERROR;
92
93     if (PIN_INPUT_WAIT == gPinState)
94     {
95         OIC_LOG(ERROR, TAG, "Pin input callback invoked already");
96         NotifyInputState();
97         SetResult(otmCtx, res);
98         return OC_STACK_NOT_ACCEPTABLE;
99     }
100
101     gPinState = PIN_INPUT_WAIT;
102
103     res = InputPin((char*)pinData, sizeof(pinData));
104     if (OC_STACK_OK != res)
105     {
106         OIC_LOG(ERROR, TAG, "Failed to input PIN");
107         gPinState = PIN_INPUT_FAIL;
108         SetResult(otmCtx, res);
109         return res;
110     }
111     gPinState = PIN_INPUT_SUCCESS;
112
113     /**
114      * Since PSK will be used directly while PIN based ownership transfer,
115      * Credential should not be saved into SVR.
116      * For this reason, We will use a temporary get_psk_info callback to random PIN OxM.
117      */
118     //in case of OTM
119     if(!(otmCtx->selectedDeviceInfo->doxm->owned))
120     {
121         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
122         {
123             OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
124             res = OC_STACK_ERROR;
125         }
126     }
127 #ifdef MULTIPLE_OWNER
128     //in case of MOT
129     else if(otmCtx->selectedDeviceInfo->doxm->owned &&
130             otmCtx->selectedDeviceInfo->doxm->mom &&
131             OIC_MULTIPLE_OWNER_DISABLE != otmCtx->selectedDeviceInfo->doxm->mom->mode)
132     {
133         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForMotRandomPinOxm))
134         {
135             OIC_LOG(ERROR, TAG, "Failed to register TLS credentials handler for random PIN OxM.");
136             res = OC_STACK_ERROR;
137         }
138     }
139 #endif //MULTIPLE_OWNER
140
141     //Set the device id to derive temporal PSK
142     SetUuidForPinBasedOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
143
144     return res;
145 }
146
147 OCStackResult CreateSecureSessionRandomPinCallback(OTMContext_t* otmCtx)
148 {
149     OIC_LOG(INFO, TAG, "IN CreateSecureSessionRandomPinCallbak");
150
151     if (!otmCtx || !otmCtx->selectedDeviceInfo)
152     {
153         return OC_STACK_INVALID_PARAM;
154     }
155
156     CAResult_t caresult = CAEnableAnonECDHCipherSuite(false);
157     if (CA_STATUS_OK != caresult)
158     {
159         OIC_LOG_V(ERROR, TAG, "Unable to disable anon cipher suite");
160         return OC_STACK_ERROR;
161     }
162     OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
163
164     caresult  = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, otmCtx->selectedDeviceInfo->endpoint.adapter);
165     if (CA_STATUS_OK != caresult)
166     {
167         OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
168         return OC_STACK_ERROR;
169     }
170     OIC_LOG(INFO, TAG, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 cipher suite selected.");
171
172     OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
173     CAEndpoint_t endpoint;
174     memcpy(&endpoint, &selDevInfo->endpoint, sizeof(CAEndpoint_t));
175
176     if(CA_ADAPTER_IP == endpoint.adapter)
177     {
178         endpoint.port = selDevInfo->securePort;
179         caresult = CAInitiateHandshake(&endpoint);
180     }
181     else if (CA_ADAPTER_GATT_BTLE == endpoint.adapter)
182     {
183         caresult = CAInitiateHandshake(&endpoint);
184     }
185 #ifdef __WITH_TLS__
186     else
187     {
188         endpoint.port = selDevInfo->tcpPort;
189         caresult = CAinitiateSslHandshake(&endpoint);
190     }
191 #endif
192     if (CA_STATUS_OK != caresult)
193     {
194         OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
195         return OC_STACK_ERROR;
196     }
197
198     OIC_LOG(INFO, TAG, "OUT CreateSecureSessionRandomPinCallbak");
199
200     return OC_STACK_OK;
201 }