1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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"
30 #include "crlresource.h"
32 #endif /* __WITH_X509__ */
37 #define SEPARATOR_LEN (1)
38 #define CBOR_CRL_NAME "\"CRL\""
39 #define CBOR_CRL_NAME_LEN (5)
40 #define OIC_CBOR_CRL_NAME "crl"
41 #define OIC_CBOR_CRL_ID "CRLId"
42 #define OIC_CBOR_CRL_THIS_UPDATE "ThisUpdate"
43 #define OIC_CBOR_CRL_DATA "CRLData"
44 #define CRL_DEFAULT_CRL_ID 1
45 #define CRL_DEFAULT_THIS_UPDATE "150101000000Z"
46 #define CRL_DEFAULT_CRL_DATA "-"
48 static OCResourceHandle gCrlHandle = NULL;
49 static OicSecCrl_t *gCrl = NULL;
51 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
52 * The value of payload size is increased until reaching below max cbor size. */
53 static const uint16_t CBOR_SIZE = 1024;
55 // Max cbor size payload.
56 static const uint16_t CBOR_MAX_SIZE = 4400;
58 // PSTAT Map size - Number of mandatory items
59 static const uint8_t CRL_MAP_SIZE = 3;
61 void DeleteCrlBinData(OicSecCrl_t *crl)
66 OICFree(crl->ThisUpdate.data);
69 OICFree(crl->CrlData.data);
76 OCStackResult CrlToCBORPayload(const OicSecCrl_t *crl, uint8_t **payload, size_t *size)
78 if (NULL == crl || NULL == payload || NULL != *payload || NULL == size)
80 return OC_STACK_INVALID_PARAM;
83 size_t cborLen = *size;
92 OCStackResult ret = OC_STACK_ERROR;
94 CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
95 CborEncoder crlMap = { {.ptr = NULL }, .end = 0 };
97 CborError cborEncoderResult = CborNoError;
99 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
100 VERIFY_NON_NULL(TAG, outPayload, ERROR);
101 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
103 cborEncoderResult = cbor_encoder_create_map(&encoder, &crlMap, CRL_MAP_SIZE);
104 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
107 cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_ID,
108 strlen(OIC_CBOR_CRL_ID));
109 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
110 cborEncoderResult = cbor_encode_int(&crlMap, crl->CrlId);
111 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
113 //ThisUpdate -- Mandatory
114 cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_THIS_UPDATE,
115 strlen(OIC_CBOR_CRL_THIS_UPDATE));
116 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
117 cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->ThisUpdate.data,
118 crl->ThisUpdate.len);
119 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
121 //CRLData -- Mandatory
122 cborEncoderResult = cbor_encode_text_string(&crlMap, OIC_CBOR_CRL_DATA,
123 strlen(OIC_CBOR_CRL_DATA));
124 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
125 cborEncoderResult = cbor_encode_byte_string(&crlMap, crl->CrlData.data,
127 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
129 cborEncoderResult = cbor_encoder_close_container(&encoder, &crlMap);
130 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, ERROR);
132 *size = encoder.ptr - outPayload;
133 *payload = outPayload;
137 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
139 // reallocate and try again!
141 // Since the allocated initial memory failed, double the memory.
142 cborLen += encoder.ptr - encoder.end;
143 cborEncoderResult = CborNoError;
144 ret = CrlToCBORPayload(crl, payload, &cborLen);
147 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
153 ret = OC_STACK_ERROR;
159 OCStackResult CBORPayloadToCrl(const uint8_t *cborPayload, const size_t size,
160 OicSecCrl_t **secCrl)
162 if (NULL == cborPayload || NULL == secCrl || NULL != *secCrl)
164 return OC_STACK_INVALID_PARAM;
167 OCStackResult ret = OC_STACK_ERROR;
170 CborValue crlCbor = { .parser = NULL };
171 CborParser parser = { .end = NULL };
172 CborError cborFindResult = CborNoError;
178 cbor_parser_init(cborPayload, cborLen, 0, &parser, &crlCbor);
179 CborValue crlMap = { .parser = NULL } ;
180 OicSecCrl_t *crl = NULL;
183 cborFindResult = cbor_value_enter_container(&crlCbor, &crlMap);
184 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
186 crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
187 VERIFY_NON_NULL(TAG, crl, ERROR);
189 while (cbor_value_is_valid(&crlMap))
192 cborFindResult = cbor_value_dup_text_string(&crlMap, &name, &len, NULL);
193 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
194 cborFindResult = cbor_value_advance(&crlMap);
195 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
197 CborType type = cbor_value_get_type(&crlMap);
199 if (0 == strcmp(OIC_CBOR_CRL_ID, name))
201 cborFindResult = cbor_value_get_int(&crlMap, (int *) &crl->CrlId);
202 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
204 if (0 == strcmp(OIC_CBOR_CRL_THIS_UPDATE, name))
206 uint8_t *crlByte = NULL;
207 cborFindResult = cbor_value_dup_byte_string(&crlMap, &crlByte, &len, NULL);
208 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
209 crl->ThisUpdate.data = (uint8_t*) OICMalloc(len);
210 VERIFY_NON_NULL(TAG, crl->ThisUpdate.data, ERROR);
211 memcpy(crl->ThisUpdate.data, crlByte, len);
212 crl->ThisUpdate.len = len;
215 if (0 == strcmp(OIC_CBOR_CRL_DATA, name))
217 uint8_t *crlByte = NULL;
218 cborFindResult = cbor_value_dup_byte_string(&crlMap, &crlByte, &len, NULL);
219 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
220 crl->CrlData.data = (uint8_t*) OICMalloc(len);
221 VERIFY_NON_NULL(TAG, crl->CrlData.data, ERROR);
222 memcpy(crl->CrlData.data, crlByte, len);
223 crl->CrlData.len = len;
226 if (CborMapType != type && cbor_value_is_valid(&crlMap))
228 cborFindResult = cbor_value_advance(&crlMap);
229 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
234 // PUT/POST CBOR may not have mandatory values set default values.
237 VERIFY_NON_NULL(TAG, gCrl, ERROR);
238 crl->CrlId = gCrl->CrlId;
240 if (!crl->ThisUpdate.data)
242 VERIFY_NON_NULL(TAG, gCrl, ERROR);
243 outLen = gCrl->ThisUpdate.len;
244 crl->ThisUpdate.data = (uint8_t*) OICMalloc(outLen);
245 VERIFY_NON_NULL(TAG, crl->ThisUpdate.data, ERROR);
246 memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
247 crl->ThisUpdate.len = outLen;
249 if (!crl->CrlData.data)
251 VERIFY_NON_NULL(TAG, gCrl, ERROR);
252 outLen = gCrl->CrlData.len;
253 crl->CrlData.data = (uint8_t*) OICMalloc(outLen);
254 VERIFY_NON_NULL(TAG, crl->CrlData.data, ERROR);
255 memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
256 crl->CrlData.len = outLen;
262 if (CborNoError != cborFindResult)
264 OIC_LOG (ERROR, TAG, "CBORPayloadToCrl failed");
265 DeleteCrlBinData(crl);
268 ret = OC_STACK_ERROR;
277 OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
279 uint8_t *payload = NULL;
282 OCStackResult res = CrlToCBORPayload((OicSecCrl_t *) crl, &payload, &size);
283 if (OC_STACK_OK != res)
288 return UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size);
291 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
293 OCEntityHandlerResult ehRet = OC_EH_ERROR;
294 OicSecCrl_t *crl = NULL;
295 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData1;
299 OIC_LOG(INFO, TAG, "UpdateSVRDB...");
300 CBORPayloadToCrl(payload, CBOR_SIZE, &crl);
301 VERIFY_NON_NULL(TAG, crl, ERROR);
303 gCrl->CrlId = crl->CrlId;
305 OICFree(gCrl->ThisUpdate.data);
306 gCrl->ThisUpdate.data = NULL;
307 gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
308 VERIFY_NON_NULL(TAG, gCrl->ThisUpdate.data, ERROR);
309 memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
310 gCrl->ThisUpdate.len = crl->ThisUpdate.len;
312 OICFree(gCrl->CrlData.data);
313 gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
314 VERIFY_NON_NULL(TAG, gCrl->CrlData.data, ERROR);
315 memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
316 gCrl->CrlData.len = crl->CrlData.len;
319 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_CBOR_CRL_NAME, payload, size))
324 DeleteCrlBinData(crl);
329 // Send payload to request originator
330 SendSRMResponse(ehRequest, ehRet, NULL);
332 OIC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
338 * This internal method is the entity handler for CRL resource and
339 * will handle REST request (GET/PUT/POST/DEL) for them.
341 static OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
342 OCEntityHandlerRequest *ehRequest,
343 void *callbackParameter)
345 OCEntityHandlerResult ehRet = OC_EH_ERROR;
346 (void)callbackParameter;
353 OIC_LOG(INFO, TAG, "Handle CRL resource");
355 if (flag & OC_REQUEST_FLAG)
357 // TODO : Handle PUT and DEL methods
358 OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
359 switch (ehRequest->method)
362 OIC_LOG (INFO, TAG, "Not implemented request method.");
363 //ehRet = HandleCRLGetRequest(ehRequest);
367 ehRet = HandleCRLPostRequest(ehRequest);
372 SendSRMResponse(ehRequest, ehRet, NULL);
380 * This internal method is used to create '/oic/sec/crl' resource.
382 static OCStackResult CreateCRLResource()
384 OCStackResult ret = OCCreateResource(&gCrlHandle,
385 OIC_RSRC_TYPE_SEC_CRL,
392 if (OC_STACK_OK != ret)
394 OIC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
401 * Get the default value.
402 * @return defaultCrl for now.
404 static OicSecCrl_t *GetCrlDefault()
406 OicSecCrl_t *defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
407 if (NULL == defaultCrl)
411 defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
413 defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
414 defaultCrl->CrlData.data = (uint8_t*) OICMalloc(defaultCrl->CrlData.len);
415 if (defaultCrl->CrlData.data)
417 memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
421 defaultCrl->CrlData.len = 0;
424 defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
425 defaultCrl->ThisUpdate.data = (uint8_t*) OICMalloc(defaultCrl->ThisUpdate.len);
426 if (defaultCrl->ThisUpdate.data)
428 memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
432 defaultCrl->ThisUpdate.len = 0;
439 * Initialize CRL resource by loading data from persistent storage.
442 * OC_STACK_OK - no errors
443 * OC_STACK_ERROR - stack process error
445 OCStackResult InitCRLResource()
447 OCStackResult ret = OC_STACK_ERROR;
448 // Read Crl resource from PS
449 uint8_t *data = NULL;
451 ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
452 // If database read failed
453 if (OC_STACK_OK != ret)
455 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
459 // Read ACL resource from PS
460 ret = CBORPayloadToCrl(data, size, &gCrl);
464 * If SVR database in persistent storage got corrupted or
465 * is not available for some reason, a default CrlResource is created
466 * which allows user to initiate CrlResource provisioning again.
468 if ((OC_STACK_OK != ret) || !data || !gCrl)
470 gCrl = GetCrlDefault();
473 ret = CreateCRLResource();
479 * Perform cleanup for ACL resources.
481 void DeInitCRLResource()
483 OCDeleteResource(gCrlHandle);
485 DeleteCrlBinData(gCrl);
489 OicSecCrl_t *GetCRLResource()
491 OicSecCrl_t *crl = NULL;
493 //Read CRL resource from PS
494 uint8_t *data = NULL;
496 OCStackResult ret = GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size);
499 //Convert CBOR CRL into binary format
500 ret = CBORPayloadToCrl(data, size, &crl);
503 * If SVR database in persistent storage got corrupted or
504 * is not available for some reason, a default CrlResource is created
505 * which allows user to initiate CrlResource provisioning again.
507 if ((OC_STACK_OK != ret) || !data || !crl)
509 crl = GetCrlDefault();
518 uint8_t *data = NULL;
520 OicSecCrl_t *crl = NULL;
521 if (OC_STACK_OK == GetSecureVirtualDatabaseFromPS(OIC_CBOR_CRL_NAME, &data, &size) && data &&
522 OC_STACK_OK == CBORPayloadToCrl(data, size, &crl))
524 return crl->CrlData.data;
529 void GetDerCrl(ByteArray crlArray)
531 OicSecCrl_t * crlRes = GetCRLResource();
532 if (crlRes && crlRes->CrlData.len <= crlArray.len)
534 memcpy(crlArray.data, crlRes->CrlData.data, crlRes->CrlData.len);
535 crlArray.len = crlRes->CrlData.len;
541 DeleteCrlBinData(crlRes);