Imported Upstream version 0.9.1
[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 #include "cainterface.h"
26 #include <string.h>
27
28 static OCSecConfigData* secConfigData;
29 static int secConfigDataLen;
30
31
32 /**
33  * This internal API removes/clears the global variable holding the security
34  * config data. This needs to be invoked when OIC stack is shutting down.
35  *
36  * @retval none
37  */
38 void DeinitOCSecurityInfo()
39 {
40     if (secConfigData)
41     {
42         // Initialize sensitive data to zeroes before freeing.
43         memset(secConfigData, 0, secConfigDataLen);
44
45         OCFree(secConfigData);
46         secConfigData = NULL;
47     }
48 }
49
50 /**
51  * This internal callback is used by lower stack (i.e. CA layer) to
52  * retrieve PSK credentials from RI security layer.
53  *
54  * Note: When finished, caller should initialize memory to zeroes and
55  * invoke OCFree to delete @p credInfo.
56  *
57  * @param credInfo
58  *     binary blob containing PSK credentials
59  *
60  * @retval none
61  */
62 #ifdef __WITH_DTLS__
63 void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
64 {
65     // CA layer interface publishes security data structures ONLY if
66     // stack is compiled in SECURED mode
67     CADtlsPskCredsBlob_t * caBlob = NULL;
68     if(secConfigData && credInfo)
69     {
70         unsigned int i = 0;
71         OCSecBlob * osb = (OCSecBlob*)secConfigData->blob;
72         for ( ;(i<secConfigData->numBlob) && osb; i++)
73         {
74             if (osb->type == OC_BLOB_TYPE_PSK)
75             {
76                 caBlob = (CADtlsPskCredsBlob_t *)OCCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
77                 if (caBlob)
78                 {
79                     OCDtlsPskCredsBlob * ocBlob = (OCDtlsPskCredsBlob *)osb->val;
80
81                     memcpy(caBlob->identity, ocBlob->identity, sizeof(caBlob->identity));
82                     caBlob->num = ocBlob->num;
83                     caBlob->creds =
84                         (OCDtlsPskCreds*) OCMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
85                     if (caBlob->creds)
86                     {
87                         memcpy(caBlob->creds, ocBlob->creds,
88                                 caBlob->num * sizeof(OCDtlsPskCreds));
89                         *credInfo = caBlob;
90                         // We copied the credential blob in the CA data structure.
91                         // Let's get out of here.
92                         return;
93                     }
94                 }
95                 break;
96             }
97             osb = config_data_next_blob(osb);
98         }
99     }
100
101     // Clear memory if any memory allocation failed above
102     if(caBlob)
103     {
104         OCFree(caBlob->creds);
105         OCFree(caBlob);
106     }
107 }
108 #endif //__WITH_DTLS__
109
110
111 /**
112  * This method validates the sanctity of OCDtlsPskCredsBlob.
113  *
114  * @param secBlob
115  *     binary blob containing PSK credentials
116  *
117  * @retval OC_STACK_OK for Success, otherwise some error value
118  */
119 static
120 OCStackResult ValidateBlobTypePSK(const OCSecBlob *secBlob)
121 {
122     OCDtlsPskCredsBlob *pskCredsBlob;
123     uint16_t validLen;
124
125     if(!secBlob || secBlob->len == 0)
126     {
127         return OC_STACK_INVALID_PARAM;
128     }
129
130     pskCredsBlob = (OCDtlsPskCredsBlob *)secBlob->val;
131
132     //calculate the expected length of PSKCredsBlob
133     if(pskCredsBlob->num >= 1)
134     {
135         validLen = sizeof(OCDtlsPskCredsBlob) +
136             (pskCredsBlob->num - 1) * sizeof(OCDtlsPskCredsBlob);
137     }
138     else
139     {
140         validLen = sizeof(OCDtlsPskCredsBlob);
141     }
142
143     if(secBlob->len != validLen)
144         return OC_STACK_INVALID_PARAM;
145
146     return OC_STACK_OK;
147 }
148
149
150 /**
151  * This method validates the sanctity of configuration data provided
152  * by application to OC stack.
153  *
154  * @param cfgdata
155  *     binary blob containing credentials and other config data
156  * @param len
157  *     length of binary blob
158  *
159  * @retval OC_STACK_OK for Success, otherwise some error value
160  */
161 static
162 OCStackResult ValidateSecConfigData(const OCSecConfigData *cfgData,
163                 size_t len)
164 {
165     OCStackResult ret = OC_STACK_OK;
166     unsigned int i = 0;
167     OCSecBlob * osb = NULL;
168
169     if (!cfgData || (len == 0))
170     {
171         return OC_STACK_INVALID_PARAM;
172     }
173
174     if (cfgData->version != OCSecConfigVer_CurrentVersion)
175     {
176         return OC_STACK_INVALID_PARAM;
177     }
178
179     osb = (OCSecBlob*)cfgData->blob;
180     for ( ;(i<cfgData->numBlob) && osb; i++)
181     {
182         if (osb->type == OC_BLOB_TYPE_PSK)
183         {
184             ret = ValidateBlobTypePSK(osb);
185         }
186         else
187         {
188             return OC_STACK_INVALID_PARAM;
189         }
190
191         if (ret != OC_STACK_OK)
192         {
193             return ret;
194         }
195         osb = config_data_next_blob(osb);
196     }
197
198     return ret;
199 }
200
201
202
203 /**
204  * Provides the Security configuration data to OC stack.
205  *
206  * @param cfgdata
207  *     binary blob containing credentials and other config data
208  * @param len
209  *     length of binary blob
210  *
211  * @retval OC_STACK_OK for Success, otherwise some error value
212  */
213 OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData,
214                 size_t len)
215 {
216     // Validate the data inside blob before consuming
217     if (cfgData && ValidateSecConfigData(cfgData, len) == OC_STACK_OK)
218     {
219         // Remove existing blob
220         DeinitOCSecurityInfo();
221         // Allocate storage for new blob
222         secConfigData = (OCSecConfigData*)OCMalloc(len);
223         if (secConfigData)
224         {
225             memcpy(secConfigData, cfgData, len);
226             secConfigDataLen = len;
227             return OC_STACK_OK;
228         }
229
230         return OC_STACK_NO_MEMORY;
231     }
232
233     return OC_STACK_INVALID_PARAM;
234 }
235
236
237