Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / security / src / crlresource.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 "utlist.h"
22 #include "payload_logging.h"
23 #include "psinterface.h"
24 #include "resourcemanager.h"
25 #include "srmresourcestrings.h"
26 #include "srmutility.h"
27 #include "doxmresource.h"
28 #include "ocpayload.h"
29 #include "oic_malloc.h"
30 #ifdef __WITH_X509__
31 #include "crlresource.h"
32 #include "crl.h"
33 #endif /* __WITH_X509__ */
34
35 #define TAG  "SRM-CRL"
36
37 #define SEPARATOR                   ":"
38 #define SEPARATOR_LEN               (1)
39 #define CBOR_CRL_NAME               "\"CRL\""
40 #define CBOR_CRL_NAME_LEN           (5)
41 #define OIC_CBOR_CRL_NAME           "crl"
42 #define OIC_CBOR_CRL_ID             "CRLId"
43 #define OIC_CBOR_CRL_THIS_UPDATE    "ThisUpdate"
44 #define OIC_CBOR_CRL_DATA           "CRLData"
45 #define CRL_DEFAULT_CRL_ID          (1)
46 #define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
47 #define CRL_DEFAULT_CRL_DATA        "-"
48
49 static OCResourceHandle     gCrlHandle  = NULL;
50 static OicSecCrl_t         *gCrl        = NULL;
51
52 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
53  * The value of payload size is increased until reaching below max cbor size. */
54 static const uint16_t CBOR_SIZE = 1024;
55
56 // Max cbor size payload.
57 static const uint16_t CBOR_MAX_SIZE = 4400;
58
59 // PSTAT Map size - Number of mandatory items
60 static const uint8_t CRL_MAP_SIZE = 3;
61
62 void DeleteCrlBinData(OicSecCrl_t *crl)
63 {
64     if (crl)
65     {
66         //Clean ThisUpdate
67         OICFree(crl->ThisUpdate.data);
68
69         //clean CrlData
70         OICFree(crl->CrlData.data);
71
72         //Clean crl itself
73         OICFree(crl);
74     }
75 }
76
77 OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size)
78 {
79     if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
80     {
81         return OC_STACK_INVALID_PARAM;
82     }
83
84     size_t cborLen = *size;
85     if (0 == cborLen)
86     {
87         cborLen = CBOR_SIZE;
88     }
89
90     *payload = NULL;
91     *size = 0;
92
93     OCStackResult ret = OC_STACK_ERROR;
94
95     CborEncoder encoder;
96     CborEncoder crlMap;
97
98     CborError cborEncoderResult = CborNoError;
99
100     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
101     VERIFY_NON_NULL(TAG, outPayload, ERROR);
102     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
103
104     cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, CRL_MAP_SIZE);
105     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to create CRL Map");
106
107     //CRLId -- Mandatory
108     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_ID,
109         strlen(OIC_CBOR_CRL_ID));
110     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL ID");
111     cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
112     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add CRL Id value");
113
114     //ThisUpdate -- Mandatory
115     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_THIS_UPDATE,
116         strlen(OIC_CBOR_CRL_THIS_UPDATE));
117     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl update");
118     cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->ThisUpdate.data,
119                                                 crl->ThisUpdate.len);
120     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl Update value");
121
122     //CRLData -- Mandatory
123     cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_DATA,
124         strlen(OIC_CBOR_CRL_DATA));
125     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data name");
126     cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->CrlData.data,
127                                                 crl->CrlData.len);
128     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add Crl data value");
129
130     cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
131     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to add close Crl map");
132
133     *size = encoder.ptr - outPayload;
134     *payload = outPayload;
135     ret = OC_STACK_OK;
136
137 exit:
138     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
139     {
140         // reallocate and try again!
141         OICFree(outPayload);
142         // Since the allocated initial memory failed, double the memory.
143         cborLen += encoder.ptr - encoder.end;
144         cborEncoderResult = CborNoError;
145         ret = CrlToCBORPayload(crl, payload, &cborLen);
146     }
147
148     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
149     {
150         OICFree(outPayload);
151         outPayload = NULL;
152         *payload = NULL;
153         *size = 0;
154         ret = OC_STACK_ERROR;
155     }
156
157     return ret;
158 }
159
160 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
161                                OicSecCrl_t **secCrl)
162 {
163     if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl || 0 == size)
164     {
165         return OC_STACK_INVALID_PARAM;
166     }
167
168     OCStackResult ret = OC_STACK_ERROR;
169     *secCrl = NULL;
170
171     CborValue crlCbor = {.parser = NULL};
172     CborParser parser = {.end = NULL};
173     CborError cborFindResult = CborNoError;
174
175     cbor_parser_init(cborPayload, size, 0, &parser, &crlCbor);
176     CborValue crlMap = { .parser = NULL};
177     OicSecCrl_t *crl = NULL;
178     size_t outLen = 0;
179     cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
180     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to enter Crl map");
181
182     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
183     VERIFY_NON_NULL(TAG, crl, ERROR);
184
185     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_ID, &crlMap);
186     if (CborNoError == cborFindResult && cbor_value_is_integer(&crlMap))
187     {
188         cborFindResult = cbor_value_get_int(&crlMap, (int *) &crl->CrlId);
189         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CrlId.");
190     }
191
192     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_THIS_UPDATE, &crlMap);
193     if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
194     {
195         cborFindResult = cbor_value_dup_byte_string(&crlMap,
196             &crl->ThisUpdate.data, &crl->ThisUpdate.len, NULL);
197         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
198     }
199     cborFindResult = cbor_value_map_find_value(&crlCbor, OIC_CBOR_CRL_DATA, &crlMap);
200     if (CborNoError == cborFindResult && cbor_value_is_byte_string(&crlMap))
201     {
202         cborFindResult = cbor_value_dup_byte_string(&crlMap,
203                          &crl->CrlData.data, &crl->CrlData.len, NULL);
204         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
205     }
206
207     *secCrl = crl;
208     ret = OC_STACK_OK;
209 exit:
210     if (CborNoError != cborFindResult)
211     {
212         // PUT/POST CBOR may not have mandatory values set default values.
213         if (gCrl)
214         {
215             OIC_LOG (DEBUG, TAG, "Set default values");
216             crl->CrlId = gCrl->CrlId;
217             if (crl->ThisUpdate.data)
218             {
219                 OICFree(crl->ThisUpdate.data);
220             }
221             outLen = gCrl->ThisUpdate.len;
222             crl->ThisUpdate.data = (uint8_t*) OICMalloc(outLen);
223             if (crl->ThisUpdate.data)
224             {
225                 memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
226                 crl->ThisUpdate.len = outLen;
227             }
228             else
229             {
230                 crl->ThisUpdate.len = 0;
231                 OIC_LOG(ERROR, TAG, "Set default failed");
232             }
233             if (crl->CrlData.data)
234             {
235                 OICFree(crl->CrlData.data);
236             }
237             outLen = gCrl->CrlData.len;
238             crl->CrlData.data = (uint8_t*) OICMalloc(outLen);
239             if (crl->CrlData.data && gCrl->CrlData.data)
240             {
241                 memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
242                 crl->CrlData.len = outLen;
243             }
244             else
245             {
246                 crl->CrlData.len = 0;
247                 OIC_LOG (ERROR, TAG, "Set default failed");
248             }
249
250             *secCrl = crl;
251             ret = OC_STACK_OK;
252         }
253         else
254         {
255             OIC_LOG (ERROR, TAG, "CBORPayloadToCrl failed");
256             DeleteCrlBinData(crl);
257             crl = NULL;
258             ret = OC_STACK_ERROR;
259         }
260     }
261     return ret;
262 }
263
264 OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
265 {
266     uint8_t *payload = NULL;
267     size_t size = 0;
268
269     OCStackResult res = CrlToCBORPayload((OicSecCrl_t *) crl, &payload, &size);
270     if (OC_STACK_OK != res)
271     {
272         return res;
273     }
274
275     return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
276 }
277
278 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
279 {
280     OCEntityHandlerResult ehRet = OC_EH_ERROR;
281     OicSecCrl_t *crl = NULL;
282     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
283     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
284
285     if (payload)
286     {
287         OIC_LOG(INFO, TAG, "UpdateSVRDB...");
288         CBORPayloadToCrl(payload, size, &crl);
289         VERIFY_NON_NULL(TAG, crl, ERROR);
290
291         gCrl->CrlId = crl->CrlId;
292
293         OICFree(gCrl->ThisUpdate.data);
294         gCrl->ThisUpdate.data = NULL;
295         gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
296         VERIFY_NON_NULL(TAG, gCrl->ThisUpdate.data, ERROR);
297         memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
298         gCrl->ThisUpdate.len = crl->ThisUpdate.len;
299
300         OICFree(gCrl->CrlData.data);
301         gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
302         VERIFY_NON_NULL(TAG, gCrl->CrlData.data, ERROR);
303         memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
304         gCrl->CrlData.len = crl->CrlData.len;
305
306         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size))
307         {
308             ehRet = OC_EH_RESOURCE_CREATED;
309         }
310
311         DeleteCrlBinData(crl);
312     }
313
314 exit:
315     // Send payload to request originator
316     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
317     {
318         ehRet = OC_EH_ERROR;
319         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleCRLPostRequest");
320     }
321
322     OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
323     return ehRet;
324 }
325
326
327 /**
328  * This internal method is the entity handler for CRL resource and
329  * will handle REST request (GET/PUT/POST/DEL) for them.
330  */
331 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
332                                               OCEntityHandlerRequest *ehRequest,
333                                               void *callbackParameter)
334 {
335     OCEntityHandlerResult ehRet = OC_EH_ERROR;
336     (void)callbackParameter;
337
338     if (!ehRequest)
339     {
340         return ehRet;
341     }
342
343     OIC_LOG(INFO, TAG, "Handle CRL resource");
344
345     if (flag & OC_REQUEST_FLAG)
346     {
347         // TODO :  Handle PUT and DEL methods
348         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
349         switch (ehRequest->method)
350         {
351             case OC_REST_GET:
352                 OIC_LOG (INFO, TAG, "Not implemented request method.");
353                 //ehRet = HandleCRLGetRequest(ehRequest);
354                 break;
355
356             case OC_REST_POST:
357                 ehRet = HandleCRLPostRequest(ehRequest);
358                 break;
359
360             default:
361                 ehRet = OC_EH_ERROR;
362                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
363         }
364     }
365
366     return ehRet;
367 }
368
369 /**
370  * This internal method is used to create '/oic/sec/crl' resource.
371  */
372 static OCStackResult CreateCRLResource()
373 {
374     OCStackResult ret = OCCreateResource(&gCrlHandle,
375                                          OIC_RSRC_TYPE_SEC_CRL,
376                                          OIC_MI_DEF,
377                                          OIC_RSRC_CRL_URI,
378                                          CRLEntityHandler,
379                                          NULL,
380                                          OC_OBSERVABLE);
381
382     if (OC_STACK_OK != ret)
383     {
384         OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
385         DeInitCRLResource();
386     }
387     return ret;
388 }
389
390 /**
391  * Get the default value.
392  * @return defaultCrl for now.
393  */
394 static OicSecCrl_t *GetCrlDefault()
395 {
396     OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
397     if (NULL == defaultCrl)
398     {
399         return NULL;
400     }
401     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
402
403     defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
404     defaultCrl->CrlData.data = (uint8_t*) OICMalloc(defaultCrl->CrlData.len);
405     if (defaultCrl->CrlData.data)
406     {
407         memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
408     }
409     else
410     {
411         defaultCrl->CrlData.len = 0;
412     }
413
414     defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
415     defaultCrl->ThisUpdate.data = (uint8_t*) OICMalloc(defaultCrl->ThisUpdate.len);
416     if (defaultCrl->ThisUpdate.data)
417     {
418         memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
419     }
420     else
421     {
422         defaultCrl->ThisUpdate.len = 0;
423     }
424
425     return defaultCrl;
426 }
427
428 /**
429  * Initialize CRL resource by loading data from persistent storage.
430  *
431  * @retval
432  *     OC_STACK_OK    - no errors
433  *     OC_STACK_ERROR - stack process error
434  */
435 OCStackResult InitCRLResource()
436 {
437     OCStackResult ret = OC_STACK_ERROR;
438     // Read Crl resource from PS
439     uint8_t *data = NULL;
440     size_t size = 0;
441     ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
442     // If database read failed
443     if (OC_STACK_OK != ret)
444     {
445         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
446     }
447     if (data)
448     {
449         // Read ACL resource from PS
450         ret = CBORPayloadToCrl(data, size, &gCrl);
451     }
452
453     /*
454      * If SVR database in persistent storage got corrupted or
455      * is not available for some reason, a default CrlResource is created
456      * which allows user to initiate CrlResource provisioning again.
457      */
458     if ((OC_STACK_OK != ret) || !data || !gCrl)
459     {
460         gCrl = GetCrlDefault();
461     }
462
463     ret = CreateCRLResource();
464     OICFree(data);
465     return ret;
466 }
467
468 /**
469  * Perform cleanup for ACL resources.
470  */
471 void DeInitCRLResource()
472 {
473     OCDeleteResource(gCrlHandle);
474     gCrlHandle = NULL;
475     DeleteCrlBinData(gCrl);
476     gCrl = NULL;
477 }
478
479 OicSecCrl_t *GetCRLResource()
480 {
481     OicSecCrl_t *crl =  NULL;
482
483     //Read CRL resource from PS
484     uint8_t *data = NULL;
485     size_t size = 0;
486     OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
487     if (data)
488     {
489         //Convert CBOR CRL into binary format
490         ret = CBORPayloadToCrl(data, size, &crl);
491     }
492     /*
493      * If SVR database in persistent storage got corrupted or
494      * is not available for some reason, a default CrlResource is created
495      * which allows user to initiate CrlResource provisioning again.
496      */
497     if ((OC_STACK_OK != ret) || !data || !crl)
498     {
499         crl = GetCrlDefault();
500     }
501     OICFree(data);
502
503     return crl;
504 }
505
506 uint8_t *GetCrl()
507 {
508     uint8_t *data = NULL;
509     size_t size = 0;
510     OicSecCrl_t *crl = NULL;
511     if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
512         OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
513     {
514         return crl->CrlData.data;
515     }
516     return NULL;
517 }
518
519 void  GetDerCrl(ByteArray crlArray)
520 {
521     OicSecCrl_t * crlRes = GetCRLResource();
522     if (crlRes && crlRes->CrlData.len <= crlArray.len)
523     {
524         memcpy(crlArray.data, crlRes->CrlData.data, crlRes->CrlData.len);
525         crlArray.len = crlRes->CrlData.len;
526     }
527     else
528     {
529         crlArray.len = 0;
530     }
531     DeleteCrlBinData(crlRes);
532 }