c2c7228688a441fd29bb9e06d45e759a2b20141d
[iotivity.git] / resource / csdk / security / provisioning / src / oxmpreconfpin.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 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 "oic_string.h"
32 #include "logger.h"
33 #include "pbkdf2.h"
34 #include "base64.h"
35 #include "oxmpreconfpin.h"
36 #include "ownershiptransfermanager.h"
37 #include "pinoxmcommon.h"
38 #include "srmresourcestrings.h"
39 #include "ocstackinternal.h"
40 #include "mbedtls/ssl_ciphersuites.h"
41
42 #define TAG "OIC_OXM_PreconfigPIN"
43
44 OCStackResult CreatePreconfigPinBasedSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **payload, size_t *size)
45 {
46     if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
47     {
48         return OC_STACK_INVALID_PARAM;
49     }
50
51     otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_PRECONFIG_PIN;
52
53     bool propertiesToInclude[DOXM_PROPERTY_COUNT];
54     memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
55     propertiesToInclude[DOXM_OXMSEL] = true;
56
57     return DoxmToCBORPayloadPartial(otmCtx->selectedDeviceInfo->doxm, payload, size, propertiesToInclude);
58 }
59
60 OCStackResult CreatePreconfigPinBasedOwnerTransferPayload(OTMContext_t *otmCtx, uint8_t **payload, size_t *size)
61 {
62     if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
63     {
64         return OC_STACK_INVALID_PARAM;
65     }
66
67     OicUuid_t uuidPT = {.id={0}};
68     *payload = NULL;
69     *size = 0;
70
71     if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
72     {
73         OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
74         return OC_STACK_ERROR;
75     }
76     memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
77
78     bool propertiesToInclude[DOXM_PROPERTY_COUNT];
79     memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
80     propertiesToInclude[DOXM_DEVOWNERUUID] = true;
81
82     return DoxmToCBORPayloadPartial(otmCtx->selectedDeviceInfo->doxm, payload, size, propertiesToInclude);
83 }
84
85 OCStackResult LoadPreconfigPinCodeCallback(OTMContext_t *otmCtx)
86 {
87     OIC_LOG(INFO, TAG, "IN LoadPreconfigPinCodeCallback");
88     OCStackResult res = OC_STACK_ERROR;
89     OicSecCred_t* cred = GetCredResourceData(&otmCtx->selectedDeviceInfo->doxm->deviceID);
90     if(NULL == cred)
91     {
92         OicUuid_t uuid = {.id={0}};
93         memcpy(&uuid, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t));
94         cred = GetCredResourceData(&uuid);
95         if(NULL == cred)
96         {
97             OIC_LOG(ERROR, TAG, "Can not find the Credential for MOT");
98             OIC_LOG(ERROR, TAG, "Please make sure the preconfigured PIN");
99             return OC_STACK_ERROR;
100         }
101     }
102
103     uint8_t* pinBuffer = NULL;
104     size_t pinBufLen = 0;
105     if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
106     {
107         //In case of 'preconfig PIN', secret data(PIN) already exist.
108         pinBufLen = B64DECODE_OUT_SAFESIZE(cred->privateData.len + 1);
109         pinBuffer = (uint8_t*)OICCalloc(1, pinBufLen);
110         if(NULL == pinBuffer)
111         {
112             OIC_LOG(ERROR, TAG, "Failed to memory allocation.");
113             return OC_STACK_NO_MEMORY;
114         }
115         size_t pinLen = 0;
116         if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufLen, &pinLen))
117         {
118             OIC_LOG(ERROR, TAG, "Failed to base64 deconding for preconfig PIN");
119             OICFree(pinBuffer);
120             return OC_STACK_ERROR;
121         }
122         pinBufLen = pinLen;
123     }
124     else if(OIC_ENCODING_RAW == cred->privateData.encoding)
125     {
126         pinBuffer = (uint8_t*)OICMalloc(cred->privateData.len + 1);
127         if(NULL == pinBuffer)
128         {
129             OIC_LOG(ERROR, TAG, "Failed to memory allocation.");
130             return OC_STACK_NO_MEMORY;
131         }
132         memcpy(pinBuffer, cred->privateData.data, cred->privateData.len);
133         pinBuffer[cred->privateData.len] = '\0';
134         pinBufLen = cred->privateData.len;
135     }
136     else
137     {
138         OIC_LOG(ERROR, TAG, "Unknown encoding type for PreConfigured PIN credential");
139         return OC_STACK_ERROR;
140     }
141
142     res = SetPreconfigPin((char*)pinBuffer, pinBufLen);
143     OICFree(pinBuffer);
144     if(OC_STACK_OK != res)
145     {
146         OIC_LOG_V(ERROR, TAG, "Failed to save the preconfig PIN : %d", res);
147         return res;
148     }
149
150     //in case of OTM
151     if(false == otmCtx->selectedDeviceInfo->doxm->owned)
152     {
153         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForPreconfPinOxm))
154         {
155             OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
156             res = OC_STACK_ERROR;
157         }
158     }
159 #ifdef MULTIPLE_OWNER
160     //in case of MOT
161     else if(true == otmCtx->selectedDeviceInfo->doxm->owned &&
162             otmCtx->selectedDeviceInfo->doxm->mom &&
163             OIC_MULTIPLE_OWNER_DISABLE != otmCtx->selectedDeviceInfo->doxm->mom->mode)
164     {
165         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForMotPreconfPinOxm))
166         {
167             OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
168             res = OC_STACK_ERROR;
169         }
170     }
171 #endif //MULTIPLE_OWNER
172
173     //Set the device id to derive temporal PSK
174     SetUuidForPinBasedOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
175
176     OIC_LOG(INFO, TAG, "OUT LoadPreconfigPinCodeCallback");
177
178     return res;
179 }
180
181 OCStackResult CreateSecureSessionPreconfigPinCallback(OTMContext_t* otmCtx)
182 {
183     OIC_LOG(INFO, TAG, "IN CreateSecureSessionPreconfigPinCallback");
184
185     if (!otmCtx || !otmCtx->selectedDeviceInfo)
186     {
187         return OC_STACK_INVALID_PARAM;
188     }
189
190     CAResult_t caresult = CAEnableAnonECDHCipherSuite(false);
191     if (CA_STATUS_OK != caresult)
192     {
193         OIC_LOG_V(ERROR, TAG, "Unable to disable anon cipher suite");
194         return OC_STACK_ERROR;
195     }
196     OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
197
198     caresult  = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, otmCtx->selectedDeviceInfo->endpoint.adapter);
199     if (CA_STATUS_OK != caresult)
200     {
201         OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
202         return OC_STACK_ERROR;
203     }
204     OIC_LOG(INFO, TAG, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 cipher suite selected.");
205
206     CAEndpoint_t endpoint;
207     OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
208     CopyDevAddrToEndpoint(&selDevInfo->endpoint, &endpoint);
209
210     if (CA_ADAPTER_IP == endpoint.adapter)
211     {
212         endpoint.port = selDevInfo->securePort;
213     }
214 #ifdef WITH_TCP
215     else if (CA_ADAPTER_TCP == endpoint.adapter)
216     {
217         endpoint.port = selDevInfo->tcpSecurePort;
218     }
219 #endif
220
221     caresult = CAInitiateHandshake(&endpoint);
222     if (CA_STATUS_OK != caresult)
223     {
224         OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
225         return OC_STACK_ERROR;
226     }
227
228     OIC_LOG(INFO, TAG, "OUT CreateSecureSessionPreconfigPinCallback");
229
230     return OC_STACK_OK;
231 }