Changeset for reviewing RI-CA integration changes.
[platform/upstream/iotivity.git] / resource / csdk / security / src / ocsecurity.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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 "ocstack.h"
22 #include "ocmalloc.h"
23 #include "ocsecurity.h"
24 #include "ocsecurityconfig.h"
25 #ifdef CA_SEC_MERGE_WORKAROUND
26 #include "ocsecurityinternal.h"
27 #endif //CA_SEC_MERGE_WORKAROUND
28 #include <string.h>
29
30 static OCSecConfigData* secConfigData;
31 static int secConfigDataLen;
32
33 /**
34  * Currently, there is a disconnect in the data structure used between RI layer
35  * and CA layer to convey DTLS PSK credentials. We cannot update this data
36  * structure until all reviews of CA layer is completed. To enable security
37  * feature in CA branch this workaround is added as a temporary stop-gap.
38  *
39  */
40 #ifdef CA_SEC_MERGE_WORKAROUND
41 static CADtlsPskCredsBlob *caBlob;
42 #endif //CA_SEC_MERGE_WORKAROUND
43
44 /**
45  * This internal API removes/clears the global variable holding the security
46  * config data. This needs to be invoked when OIC stack is shutting down.
47  *
48  * @retval none
49  */
50 void DeinitOCSecurityInfo()
51 {
52     if (secConfigData)
53     {
54         // Initialize sensitive data to zeroes before freeing.
55         memset(secConfigData, 0, secConfigDataLen);
56
57         OCFree(secConfigData);
58         secConfigData = NULL;
59     }
60
61 #ifdef CA_SEC_MERGE_WORKAROUND
62     if (caBlob)
63     {
64         OCFree(caBlob->creds);
65     }
66     OCFree(caBlob);
67 #endif
68
69 }
70
71 /**
72  * This internal callback is used by lower stack (i.e. CA layer) to
73  * retrieve PSK credentials from RI security layer.
74  *
75  * Note: When finished, caller should initialize memory to zeroes and
76  * invoke OCFree to delete @p credInfo.
77  *
78  * @param credInfo
79  *     binary blob containing PSK credentials
80  *
81  * @retval none
82  */
83 void GetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo)
84 {
85     if(secConfigData && credInfo)
86     {
87         unsigned int i = 0;
88         OCSecBlob * osb = (OCSecBlob*)secConfigData->blob;
89         for ( ;(i<secConfigData->numBlob) && osb; i++)
90         {
91             if (osb->type == OC_BLOB_TYPE_PSK)
92             {
93 #ifdef CA_SEC_MERGE_WORKAROUND
94                 OCDtlsPskCredsBlob * ocBlob = (OCDtlsPskCredsBlob *)osb->val;
95                 if (!caBlob)
96                 {
97                     caBlob = (CADtlsPskCredsBlob *)OCCalloc(sizeof(CADtlsPskCredsBlob), 1);
98                     if (caBlob)
99                     {
100                         memcpy(caBlob->identity, ocBlob->identity, sizeof(caBlob->identity));
101                         caBlob->num = ocBlob->num;
102                         caBlob->creds =
103                             (OCDtlsPskCreds*) OCMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
104                         if (caBlob->creds)
105                         {
106                             memcpy(caBlob->creds, ocBlob->creds,
107                                     caBlob->num * sizeof(OCDtlsPskCreds));
108                         }
109                     }
110                 }
111                 *credInfo = (OCDtlsPskCredsBlob *) caBlob;
112                 break;
113 #else
114                 OCDtlsPskCredsBlob * blob;
115                 blob = (OCDtlsPskCredsBlob *)OCMalloc(osb->len);
116                 if (blob)
117                 {
118                     memcpy(blob, osb->val, osb->len);
119                     *credInfo = blob;
120                     break;
121                 }
122 #endif //CA_SEC_MERGE_WORKAROUND
123             }
124             osb = config_data_next_blob(osb);
125         }
126     }
127 }
128
129
130 /**
131  * This method validates the sanctity of OCDtlsPskCredsBlob.
132  *
133  * @param secBlob
134  *     binary blob containing PSK credentials
135  *
136  * @retval OC_STACK_OK for Success, otherwise some error value
137  */
138 static
139 OCStackResult ValidateBlobTypePSK(const OCSecBlob *secBlob)
140 {
141     OCDtlsPskCredsBlob *pskCredsBlob;
142     uint16_t validLen;
143
144     if(!secBlob || secBlob->len == 0)
145     {
146         return OC_STACK_INVALID_PARAM;
147     }
148
149     pskCredsBlob = (OCDtlsPskCredsBlob *)secBlob->val;
150
151     //calculate the expected length of PSKCredsBlob
152     if(pskCredsBlob->num >= 1)
153     {
154         validLen = sizeof(OCDtlsPskCredsBlob) +
155             (pskCredsBlob->num - 1) * sizeof(OCDtlsPskCredsBlob);
156     }
157     else
158     {
159         validLen = sizeof(OCDtlsPskCredsBlob);
160     }
161
162     if(secBlob->len != validLen)
163         return OC_STACK_INVALID_PARAM;
164
165     return OC_STACK_OK;
166 }
167
168
169 /**
170  * This method validates the sanctity of configuration data provided
171  * by application to OC stack.
172  *
173  * @param cfgdata
174  *     binary blob containing credentials and other config data
175  * @param len
176  *     length of binary blob
177  *
178  * @retval OC_STACK_OK for Success, otherwise some error value
179  */
180 static
181 OCStackResult ValidateSecConfigData(const OCSecConfigData *cfgData,
182                 size_t len)
183 {
184     OCStackResult ret = OC_STACK_OK;
185     unsigned int i = 0;
186     OCSecBlob * osb = NULL;
187
188     if (!cfgData || (len == 0))
189     {
190         return OC_STACK_INVALID_PARAM;
191     }
192
193     if (cfgData->version != OCSecConfigVer_CurrentVersion)
194     {
195         return OC_STACK_INVALID_PARAM;
196     }
197
198     osb = (OCSecBlob*)cfgData->blob;
199     for ( ;(i<cfgData->numBlob) && osb; i++)
200     {
201         if (osb->type == OC_BLOB_TYPE_PSK)
202         {
203             ret = ValidateBlobTypePSK(osb);
204         }
205         else
206         {
207             return OC_STACK_INVALID_PARAM;
208         }
209
210         if (ret != OC_STACK_OK)
211         {
212             return ret;
213         }
214         osb = config_data_next_blob(osb);
215     }
216
217     return ret;
218 }
219
220
221
222 /**
223  * Provides the Security configuration data to OC stack.
224  *
225  * @param cfgdata
226  *     binary blob containing credentials and other config data
227  * @param len
228  *     length of binary blob
229  *
230  * @retval OC_STACK_OK for Success, otherwise some error value
231  */
232 OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData,
233                 size_t len)
234 {
235     // Validate the data inside blob before consuming
236     if (cfgData && ValidateSecConfigData(cfgData, len) == OC_STACK_OK)
237     {
238         // Remove existing blob
239         DeinitOCSecurityInfo();
240         // Allocate storage for new blob
241         secConfigData = (OCSecConfigData*)OCMalloc(len);
242         if (secConfigData)
243         {
244             memcpy(secConfigData, cfgData, len);
245             secConfigDataLen = len;
246             return OC_STACK_OK;
247         }
248
249         return OC_STACK_NO_MEMORY;
250     }
251
252     return OC_STACK_INVALID_PARAM;
253 }
254
255
256