credresource.c 58.9 KB
Newer Older
Sachin Agrawal's avatar
Sachin Agrawal committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//******************************************************************
//
// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

21
#define __STDC_LIMIT_MACROS
Sahil Bansal's avatar
Sahil Bansal committed
22 23

#include <stdlib.h>
24
#ifdef HAVE_STRING_H
Sahil Bansal's avatar
Sahil Bansal committed
25
#include <string.h>
26 27
#endif
#ifdef HAVE_STRINGS_H
Sahil Bansal's avatar
Sahil Bansal committed
28 29 30 31 32 33
#include <strings.h>
#endif
#include <stdint.h>

#include "cainterface.h"
#include "payload_logging.h"
Sachin Agrawal's avatar
Sachin Agrawal committed
34
#include "ocstack.h"
Sahil Bansal's avatar
Sahil Bansal committed
35 36 37
#include "ocrandom.h"
#include "base64.h"
#include "ocserverrequest.h"
Sachin Agrawal's avatar
Sachin Agrawal committed
38
#include "oic_malloc.h"
Sahil Bansal's avatar
Sahil Bansal committed
39
#include "ocpayload.h"
Sachin Agrawal's avatar
Sachin Agrawal committed
40 41 42
#include "utlist.h"
#include "credresource.h"
#include "doxmresource.h"
Sahil Bansal's avatar
Sahil Bansal committed
43
#include "pstatresource.h"
leechul's avatar
leechul committed
44
#include "iotvticalendar.h"
Sahil Bansal's avatar
Sahil Bansal committed
45 46 47 48 49 50
#include "pbkdf2.h"
#include "resourcemanager.h"
#include "srmresourcestrings.h"
#include "srmutility.h"
#include "psinterface.h"
#include "pinoxmcommon.h"
51

52 53
#ifdef __WITH_DTLS__
#include "global.h"
Sahil Bansal's avatar
Sahil Bansal committed
54
#endif
leechul's avatar
leechul committed
55

Sahil Bansal's avatar
Sahil Bansal committed
56 57 58 59
#define TAG  "SRM-CREDL"

/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
 * The value of payload size is increased until reaching belox max cbor size. */
leechul's avatar
leechul committed
60
static const uint16_t CBOR_SIZE = 2048;
61

Sahil Bansal's avatar
Sahil Bansal committed
62 63
/** Max cbor size payload. */
static const uint16_t CBOR_MAX_SIZE = 4400;
Sachin Agrawal's avatar
Sachin Agrawal committed
64

leechul's avatar
leechul committed
65 66 67 68
/** CRED size - Number of mandatory items. */
static const uint8_t CRED_ROOT_MAP_SIZE = 2;
static const uint8_t CRED_MAP_SIZE = 3;

Shilpa Sodani's avatar
Shilpa Sodani committed
69

Sachin Agrawal's avatar
Sachin Agrawal committed
70 71 72
static OicSecCred_t        *gCred = NULL;
static OCResourceHandle    gCredHandle = NULL;

73 74 75 76
/**
 * This function frees OicSecCred_t object's fields and object itself.
 */
static void FreeCred(OicSecCred_t *cred)
Sachin Agrawal's avatar
Sachin Agrawal committed
77
{
78
    if(NULL == cred)
Sachin Agrawal's avatar
Sachin Agrawal committed
79
    {
Sahil Bansal's avatar
Sahil Bansal committed
80
        OIC_LOG(ERROR, TAG, "Invalid Parameter");
81 82 83
        return;
    }
    //Note: Need further clarification on roleID data type
Sachin Agrawal's avatar
Sachin Agrawal committed
84
#if 0
85 86
    //Clean roleIds
    OICFree(cred->roleIds);
Sachin Agrawal's avatar
Sachin Agrawal committed
87 88
#endif

89
    //Clean PublicData
Sahil Bansal's avatar
Sahil Bansal committed
90
#ifdef __WITH_X509__
91
    OICFree(cred->publicData.data);
Sahil Bansal's avatar
Sahil Bansal committed
92
#endif
Sachin Agrawal's avatar
Sachin Agrawal committed
93

94 95
    //Clean PrivateData
    OICFree(cred->privateData.data);
Sachin Agrawal's avatar
Sachin Agrawal committed
96

97 98
    //Clean Period
    OICFree(cred->period);
Sachin Agrawal's avatar
Sachin Agrawal committed
99

100 101 102
    //Clean Cred node itself
    OICFree(cred);
}
Sachin Agrawal's avatar
Sachin Agrawal committed
103

104 105 106 107 108 109 110 111 112
void DeleteCredList(OicSecCred_t* cred)
{
    if (cred)
    {
        OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
        LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
        {
            LL_DELETE(cred, credTmp1);
            FreeCred(credTmp1);
Sachin Agrawal's avatar
Sachin Agrawal committed
113 114 115 116
        }
    }
}

Sahil Bansal's avatar
Sahil Bansal committed
117
static size_t OicSecCredCount(const OicSecCred_t *secCred)
Sachin Agrawal's avatar
Sachin Agrawal committed
118
{
Sahil Bansal's avatar
Sahil Bansal committed
119 120
    size_t size = 0;
    for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
Sachin Agrawal's avatar
Sachin Agrawal committed
121
    {
Sahil Bansal's avatar
Sahil Bansal committed
122 123 124 125
        size++;
    }
    return size;
}
126

Sahil Bansal's avatar
Sahil Bansal committed
127
OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
128
                                size_t *cborSize, int secureFlag)
Sahil Bansal's avatar
Sahil Bansal committed
129 130 131 132 133
{
    if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
    {
        return OC_STACK_INVALID_PARAM;
    }
134

Sahil Bansal's avatar
Sahil Bansal committed
135
    OCStackResult ret = OC_STACK_ERROR;
Sachin Agrawal's avatar
Sachin Agrawal committed
136

leechul's avatar
leechul committed
137 138 139
    CborError cborEncoderResult = CborNoError;
    uint8_t *outPayload = NULL;
    size_t cborLen = *cborSize;
Sahil Bansal's avatar
Sahil Bansal committed
140 141
    *cborSize = 0;
    *cborPayload = NULL;
leechul's avatar
leechul committed
142
    const OicSecCred_t *cred = credS;
143 144 145
    CborEncoder encoder;
    CborEncoder credArray;
    CborEncoder credRootMap;
Sachin Agrawal's avatar
Sachin Agrawal committed
146

leechul's avatar
leechul committed
147 148 149 150 151 152
    if (0 == cborLen)
    {
        cborLen = CBOR_SIZE;
    }

    outPayload = (uint8_t *)OICCalloc(1, cborLen);
Sahil Bansal's avatar
Sahil Bansal committed
153 154
    VERIFY_NON_NULL(TAG, outPayload, ERROR);
    cbor_encoder_init(&encoder, outPayload, cborLen, 0);
Sachin Agrawal's avatar
Sachin Agrawal committed
155

leechul's avatar
leechul committed
156 157 158 159 160 161 162 163 164 165 166 167
    // Create CRED Root Map (creds, rownerid)
    cborEncoderResult = cbor_encoder_create_map(&encoder, &credRootMap, CRED_ROOT_MAP_SIZE);
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Root Map");

    // creds
    cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_CREDS_NAME,
        strlen(OIC_JSON_CREDS_NAME));
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding creds Name Tag.");

    // creds array
    cborEncoderResult = cbor_encoder_create_array(&credRootMap, &credArray, OicSecCredCount(cred));
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Array.");
leechul's avatar
leechul committed
168

Sahil Bansal's avatar
Sahil Bansal committed
169 170
    while (cred)
    {
171
        CborEncoder credMap;
Sahil Bansal's avatar
Sahil Bansal committed
172
        size_t mapSize = CRED_MAP_SIZE;
leechul's avatar
leechul committed
173
        char *subject = NULL;
Sahil Bansal's avatar
Sahil Bansal committed
174 175 176 177 178
        if (cred->period)
        {
            mapSize++;
        }
#ifdef __WITH_X509__
Dmitriy Zhuravlev's avatar
Dmitriy Zhuravlev committed
179
        if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
Sahil Bansal's avatar
Sahil Bansal committed
180 181 182 183
        {
            mapSize++;
        }
#endif /* __WITH_X509__ */
184
        if (!secureFlag && cred->privateData.data)
Sahil Bansal's avatar
Sahil Bansal committed
185 186 187
        {
            mapSize++;
        }
leechul's avatar
leechul committed
188
        cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
Sahil Bansal's avatar
Sahil Bansal committed
189 190 191
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");

        //CredID -- Mandatory
leechul's avatar
leechul committed
192
        cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
Sahil Bansal's avatar
Sahil Bansal committed
193 194
            strlen(OIC_JSON_CREDID_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
leechul's avatar
leechul committed
195
        cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
Sahil Bansal's avatar
Sahil Bansal committed
196 197 198
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");

        //Subject -- Mandatory
leechul's avatar
leechul committed
199 200
        cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECTID_NAME,
            strlen(OIC_JSON_SUBJECTID_NAME));
Sahil Bansal's avatar
Sahil Bansal committed
201
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
leechul's avatar
leechul committed
202 203 204 205 206
        ret = ConvertUuidToStr(&cred->subject, &subject);
        VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
        cborEncoderResult = cbor_encode_text_string(&credMap, subject, strlen(subject));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
        OICFree(subject);
Sahil Bansal's avatar
Sahil Bansal committed
207 208

        //CredType -- Mandatory
leechul's avatar
leechul committed
209
        cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
Sahil Bansal's avatar
Sahil Bansal committed
210 211
            strlen(OIC_JSON_CREDTYPE_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
leechul's avatar
leechul committed
212
        cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
Sahil Bansal's avatar
Sahil Bansal committed
213
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
Sachin Agrawal's avatar
Sachin Agrawal committed
214

Dmitrii Zhuravlev's avatar
Dmitrii Zhuravlev committed
215
#ifdef __WITH_X509__
Sahil Bansal's avatar
Sahil Bansal committed
216
        //PublicData -- Not Mandatory
Dmitriy Zhuravlev's avatar
Dmitriy Zhuravlev committed
217
        if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
Sahil Bansal's avatar
Sahil Bansal committed
218
        {
219
            CborEncoder publicMap;
leechul's avatar
leechul committed
220 221 222 223 224 225 226 227 228
            const size_t publicMapSize = 2;

            cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PUBLICDATA_NAME,
                strlen(OIC_JSON_PUBLICDATA_NAME));
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Tag.");

            cborEncoderResult = cbor_encoder_create_map(&credMap, &publicMap, publicMapSize);
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Map");

229 230
            cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_DATA_NAME,
                strlen(OIC_JSON_DATA_NAME));
leechul's avatar
leechul committed
231 232 233 234 235 236 237 238 239
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Data Tag.");
            cborEncoderResult = cbor_encode_byte_string(&publicMap, cred->publicData.data,
                cred->publicData.len);
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Value.");

            // TODO: Need to data strucure modification for OicSecCert_t.
            cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_ENCODING_NAME,
                strlen(OIC_JSON_ENCODING_NAME));
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Tag.");
js126.lee's avatar
js126.lee committed
240 241
            cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_SEC_ENCODING_RAW,
                strlen(OIC_SEC_ENCODING_RAW));
leechul's avatar
leechul committed
242 243 244 245
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Value.");

            cborEncoderResult = cbor_encoder_close_container(&credMap, &publicMap);
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PublicData Map.");
Sahil Bansal's avatar
Sahil Bansal committed
246
        }
Dmitrii Zhuravlev's avatar
Dmitrii Zhuravlev committed
247
#endif /*__WITH_X509__*/
Sahil Bansal's avatar
Sahil Bansal committed
248
        //PrivateData -- Not Mandatory
249
        if(!secureFlag && cred->privateData.data)
Sahil Bansal's avatar
Sahil Bansal committed
250
        {
251
            CborEncoder privateMap;
leechul's avatar
leechul committed
252 253 254 255 256 257 258 259 260 261
            const size_t privateMapSize = 2;

            cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PRIVATEDATA_NAME,
                strlen(OIC_JSON_PRIVATEDATA_NAME));
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");

            cborEncoderResult = cbor_encoder_create_map(&credMap, &privateMap, privateMapSize);
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Map");

            // TODO: Need to data strucure modification for OicSecKey_t.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
            // TODO: Added as workaround, will be replaced soon.
            if(OIC_ENCODING_RAW == cred->privateData.encoding)
            {
                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
                    strlen(OIC_JSON_ENCODING_NAME));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_RAW,
                    strlen(OIC_SEC_ENCODING_RAW));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");

                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
                    strlen(OIC_JSON_DATA_NAME));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
                cborEncoderResult = cbor_encode_byte_string(&privateMap, cred->privateData.data,
                    cred->privateData.len);
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
            }
            else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
            {
                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
                    strlen(OIC_JSON_ENCODING_NAME));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_BASE64,
                    strlen(OIC_SEC_ENCODING_BASE64));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");

                cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
                    strlen(OIC_JSON_DATA_NAME));
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
                cborEncoderResult = cbor_encode_text_string(&privateMap, (char*)(cred->privateData.data),
                    cred->privateData.len);
                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
            }
            else
            {
                OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
                VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding Private Encoding Value.");
            }
leechul's avatar
leechul committed
300 301 302

            cborEncoderResult = cbor_encoder_close_container(&credMap, &privateMap);
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PrivateData Map.");
Sahil Bansal's avatar
Sahil Bansal committed
303
        }
Sachin Agrawal's avatar
Sachin Agrawal committed
304

Sahil Bansal's avatar
Sahil Bansal committed
305 306 307
        //Period -- Not Mandatory
        if(cred->period)
        {
leechul's avatar
leechul committed
308
            cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
Sahil Bansal's avatar
Sahil Bansal committed
309 310
                strlen(OIC_JSON_PERIOD_NAME));
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
leechul's avatar
leechul committed
311
            cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
Sahil Bansal's avatar
Sahil Bansal committed
312 313 314
                strlen(cred->period));
            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
        }
Sachin Agrawal's avatar
Sachin Agrawal committed
315

leechul's avatar
leechul committed
316 317

        cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
Sahil Bansal's avatar
Sahil Bansal committed
318
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
319

Sahil Bansal's avatar
Sahil Bansal committed
320
        cred = cred->next;
leechul's avatar
leechul committed
321 322 323 324 325
    }
    cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");

    cred = credS;
326

leechul's avatar
leechul committed
327 328 329 330 331 332
    // Rownerid
    {
        char *rowner = NULL;
        cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
            strlen(OIC_JSON_ROWNERID_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
333
        ret = ConvertUuidToStr(&cred->rownerID, &rowner);
leechul's avatar
leechul committed
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
        VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
        cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
        OICFree(rowner);
    }

    // Close CRED Root Map
    cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");

    if (CborNoError == cborEncoderResult)
    {
        OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
        *cborPayload = outPayload;
        *cborSize = encoder.ptr - outPayload;
Sahil Bansal's avatar
Sahil Bansal committed
349 350 351
        ret = OC_STACK_OK;
    }
    OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
Sachin Agrawal's avatar
Sachin Agrawal committed
352
exit:
leechul's avatar
leechul committed
353
    if (CborErrorOutOfMemory == cborEncoderResult)
354
    {
leechul's avatar
leechul committed
355 356 357 358 359 360
        OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
        // reallocate and try again!
        OICFree(outPayload);
        // Since the allocated initial memory failed, double the memory.
        cborLen += encoder.ptr - encoder.end;
        cborEncoderResult = CborNoError;
361
        ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
leechul's avatar
leechul committed
362
        *cborSize = cborLen;
363
    }
Sahil Bansal's avatar
Sahil Bansal committed
364 365 366

    if (CborNoError != cborEncoderResult)
    {
leechul's avatar
leechul committed
367 368 369 370 371 372
        OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
        OICFree(outPayload);
        outPayload = NULL;
        *cborSize = 0;
        *cborPayload = NULL;
        ret = OC_STACK_ERROR;
Sahil Bansal's avatar
Sahil Bansal committed
373 374 375
    }

    return ret;
Sachin Agrawal's avatar
Sachin Agrawal committed
376 377
}

Sahil Bansal's avatar
Sahil Bansal committed
378 379
OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
                                OicSecCred_t **secCred)
Sachin Agrawal's avatar
Sachin Agrawal committed
380
{
Ashwini Kumar's avatar
Ashwini Kumar committed
381
    if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
Sahil Bansal's avatar
Sahil Bansal committed
382 383 384
    {
        return OC_STACK_INVALID_PARAM;
    }
Sachin Agrawal's avatar
Sachin Agrawal committed
385

Sahil Bansal's avatar
Sahil Bansal committed
386
    OCStackResult ret = OC_STACK_ERROR;
leechul's avatar
leechul committed
387 388
    CborValue credCbor = { .parser = NULL };
    CborParser parser = { .end = NULL };
Sahil Bansal's avatar
Sahil Bansal committed
389
    CborError cborFindResult = CborNoError;
leechul's avatar
leechul committed
390
    cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
leechul's avatar
leechul committed
391

leechul's avatar
leechul committed
392
    OicSecCred_t *headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
393

leechul's avatar
leechul committed
394 395 396 397
    // Enter CRED Root Map
    CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
    cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering CRED Root Map.");
Sachin Agrawal's avatar
Sachin Agrawal committed
398

leechul's avatar
leechul committed
399
    while (cbor_value_is_valid(&CredRootMap))
Sahil Bansal's avatar
Sahil Bansal committed
400
    {
leechul's avatar
leechul committed
401 402 403
        char* tagName = NULL;
        size_t len = 0;
        CborType type = cbor_value_get_type(&CredRootMap);
404
        if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
Sahil Bansal's avatar
Sahil Bansal committed
405
        {
leechul's avatar
leechul committed
406 407 408 409
            cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
            cborFindResult = cbor_value_advance(&CredRootMap);
            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
Sahil Bansal's avatar
Sahil Bansal committed
410
        }
leechul's avatar
leechul committed
411
        if(tagName)
Sahil Bansal's avatar
Sahil Bansal committed
412
        {
leechul's avatar
leechul committed
413
            if (strcmp(tagName, OIC_JSON_CREDS_NAME)  == 0)
414
            {
leechul's avatar
leechul committed
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
                // Enter CREDS Array
                size_t len = 0;
                int credCount = 0;
                CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
                cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");

                while (cbor_value_is_valid(&credArray))
                {
                    credCount++;
                    //CredId -- Mandatory
                    CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
                    cborFindResult = cbor_value_enter_container(&credArray, &credMap);
                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
                    OicSecCred_t *cred = NULL;

                    if(1 == credCount)
                    {
                        cred = headCred;
                    }
                    else
                    {
                        cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
                        OicSecCred_t *temp = headCred;
                        while (temp->next)
                        {
                            temp = temp->next;
                        }
                        temp->next = cred;
                    }

                    VERIFY_NON_NULL(TAG, cred, ERROR);

448
                    while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
leechul's avatar
leechul committed
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
                    {
                        char* name = NULL;
                        CborType type = cbor_value_get_type(&credMap);
                        if (type == CborTextStringType)
                        {
                            cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
                            cborFindResult = cbor_value_advance(&credMap);
                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
                        }
                        if(name)
                        {
                            //credid
                            if (strcmp(name, OIC_JSON_CREDID_NAME)  == 0)
                            {
464 465
                                uint64_t credId = 0;
                                cborFindResult = cbor_value_get_uint64(&credMap, &credId);
leechul's avatar
leechul committed
466
                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredId.");
467
                                cred->credId = (uint16_t)credId;
leechul's avatar
leechul committed
468 469 470 471 472 473 474 475 476 477 478
                            }
                            // subjectid
                            if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
                            {
                                char *subjectid = NULL;
                                cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &len, NULL);
                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subjectid Value.");
                                ret = ConvertStrToUuid(subjectid, &cred->subject);
                                VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
                                OICFree(subjectid);
                            }
479
                            // credtype
leechul's avatar
leechul committed
480 481
                            if (strcmp(name, OIC_JSON_CREDTYPE_NAME)  == 0)
                            {
482 483
                                uint64_t credType = 0;
                                cborFindResult = cbor_value_get_uint64(&credMap, &credType);
leechul's avatar
leechul committed
484
                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredType.");
485
                                cred->credType = (OicSecCredType_t)credType;
leechul's avatar
leechul committed
486 487 488 489 490 491 492 493 494 495 496
                            }
                            // privatedata
                            if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME)  == 0)
                            {
                                CborValue privateMap = { .parser = NULL };
                                cborFindResult = cbor_value_enter_container(&credMap, &privateMap);

                                while (cbor_value_is_valid(&privateMap))
                                {
                                    char* privname = NULL;
                                    CborType type = cbor_value_get_type(&privateMap);
497
                                    if (type == CborTextStringType && cbor_value_is_text_string(&privateMap))
leechul's avatar
leechul committed
498 499 500 501 502 503 504 505 506 507
                                    {
                                        cborFindResult = cbor_value_dup_text_string(&privateMap, &privname,
                                                &len, NULL);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
                                        cborFindResult = cbor_value_advance(&privateMap);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
                                    }
                                    if (privname)
                                    {
                                        // PrivateData::privdata -- Mandatory
508
                                        if (strcmp(privname, OIC_JSON_DATA_NAME) == 0)
leechul's avatar
leechul committed
509
                                        {
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
                                            if(cbor_value_is_byte_string(&privateMap))
                                            {
                                                cborFindResult = cbor_value_dup_byte_string(&privateMap, &cred->privateData.data,
                                                    &cred->privateData.len, NULL);
                                            }
                                            else if(cbor_value_is_text_string(&privateMap))
                                            {
                                                cborFindResult = cbor_value_dup_text_string(&privateMap, (char**)(&cred->privateData.data),
                                                    &cred->privateData.len, NULL);
                                            }
                                            else
                                            {
                                                cborFindResult = CborErrorUnknownType;
                                                OIC_LOG(ERROR, TAG, "Unknow type for private data.");
                                            }
leechul's avatar
leechul committed
525 526
                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PrivateData.");
                                        }
527

leechul's avatar
leechul committed
528 529 530
                                        // PrivateData::encoding -- Mandatory
                                        if (strcmp(privname, OIC_JSON_ENCODING_NAME) == 0)
                                        {
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
                                            // TODO: Added as workaround. Will be replaced soon.
                                            char* strEncoding = NULL;
                                            cborFindResult = cbor_value_dup_text_string(&privateMap, &strEncoding, &len, NULL);
                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding EncodingType");

                                            if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
                                            {
                                                cred->privateData.encoding = OIC_ENCODING_RAW;
                                            }
                                            else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
                                            {
                                                cred->privateData.encoding = OIC_ENCODING_BASE64;
                                            }
                                            else
                                            {
                                                //For unit test
                                                cred->privateData.encoding = OIC_ENCODING_RAW;
                                                OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for private data.");
                                            }

                                            OICFree(strEncoding);
leechul's avatar
leechul committed
552 553 554 555 556 557 558 559 560 561 562
                                        }
                                    }
                                    if (cbor_value_is_valid(&privateMap))
                                    {
                                        cborFindResult = cbor_value_advance(&privateMap);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing privatedata Map.");
                                    }
                                    OICFree(privname);
                                }

                            }
leechul's avatar
leechul committed
563
#ifdef __WITH_X509__
leechul's avatar
leechul committed
564 565 566 567 568 569 570 571 572
                            if (strcmp(name, OIC_JSON_PUBLICDATA_NAME)  == 0)
                            {
                                CborValue pubMap = { .parser = NULL };
                                cborFindResult = cbor_value_enter_container(&credMap, &pubMap);

                                while (cbor_value_is_valid(&pubMap))
                                {
                                    char* pubname = NULL;
                                    CborType type = cbor_value_get_type(&pubMap);
573
                                    if (type == CborTextStringType && cbor_value_is_text_string(&pubMap))
leechul's avatar
leechul committed
574 575 576 577 578 579 580 581 582 583
                                    {
                                        cborFindResult = cbor_value_dup_text_string(&pubMap, &pubname,
                                                &len, NULL);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
                                        cborFindResult = cbor_value_advance(&pubMap);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
                                    }
                                    if (pubname)
                                    {
                                        // PrivateData::privdata -- Mandatory
584
                                        if (strcmp(pubname, OIC_JSON_DATA_NAME) == 0 && cbor_value_is_byte_string(&pubMap))
leechul's avatar
leechul committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
                                        {
                                            cborFindResult = cbor_value_dup_byte_string(&pubMap, &cred->publicData.data,
                                                &cred->publicData.len, NULL);
                                            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PubData.");
                                        }
                                        // PublicData::encoding -- Mandatory
                                        if (strcmp(pubname, OIC_JSON_ENCODING_NAME) == 0)
                                        {
                                            // TODO: Need to update data structure, just ignore encoding value now.
                                        }
                                    }
                                    if (cbor_value_is_valid(&pubMap))
                                    {
                                        cborFindResult = cbor_value_advance(&pubMap);
                                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing publicdata Map.");
                                    }
                                    OICFree(pubname);
                                }
                            }
Sahil Bansal's avatar
Sahil Bansal committed
604
#endif  //__WITH_X509__
leechul's avatar
leechul committed
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628

                            if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
                            {
                                cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &len, NULL);
                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
                            }

                            if (cbor_value_is_valid(&credMap))
                            {
                                cborFindResult = cbor_value_advance(&credMap);
                                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Map.");
                            }
                            OICFree(name);
                        }
                    }
                    cred->next = NULL;
                    if (cbor_value_is_valid(&credArray))
                    {
                        cborFindResult = cbor_value_advance(&credArray);
                        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Array.");
                    }
                }
            }

629
            //ROwner -- Mandatory
630
            if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0 && cbor_value_is_text_string(&CredRootMap))
Sachin Agrawal's avatar
Sachin Agrawal committed
631
            {
leechul's avatar
leechul committed
632 633 634
                char *stRowner = NULL;
                cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
635 636

                ret = ConvertStrToUuid(stRowner, &headCred->rownerID);
leechul's avatar
leechul committed
637 638
                VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
                OICFree(stRowner);
Sachin Agrawal's avatar
Sachin Agrawal committed
639
            }
leechul's avatar
leechul committed
640
            OICFree(tagName);
Sahil Bansal's avatar
Sahil Bansal committed
641
        }
leechul's avatar
leechul committed
642
        if (cbor_value_is_valid(&CredRootMap))
Sahil Bansal's avatar
Sahil Bansal committed
643
        {
leechul's avatar
leechul committed
644 645
            cborFindResult = cbor_value_advance(&CredRootMap);
            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
Sahil Bansal's avatar
Sahil Bansal committed
646
        }
Sachin Agrawal's avatar
Sachin Agrawal committed
647
    }
leechul's avatar
leechul committed
648

Sahil Bansal's avatar
Sahil Bansal committed
649
    *secCred = headCred;
Sachin Agrawal's avatar
Sachin Agrawal committed
650
    ret = OC_STACK_OK;
leechul's avatar
leechul committed
651

Sachin Agrawal's avatar
Sachin Agrawal committed
652
exit:
Sahil Bansal's avatar
Sahil Bansal committed
653
    if (CborNoError != cborFindResult)
Sachin Agrawal's avatar
Sachin Agrawal committed
654 655 656
    {
        DeleteCredList(headCred);
        headCred = NULL;
leechul's avatar
leechul committed
657
        *secCred = NULL;
Sahil Bansal's avatar
Sahil Bansal committed
658
        ret = OC_STACK_ERROR;
659
    }
Sahil Bansal's avatar
Sahil Bansal committed
660 661

    return ret;
Sachin Agrawal's avatar
Sachin Agrawal committed
662 663 664
}

OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
Sahil Bansal's avatar
Sahil Bansal committed
665
                                  const OicSecCert_t * publicData, const OicSecKey_t* privateData,
666
                                  const OicUuid_t * rownerID)
Sachin Agrawal's avatar
Sachin Agrawal committed
667
{
Jon A. Cruz's avatar
Jon A. Cruz committed
668
    (void)publicData;
Sachin Agrawal's avatar
Sachin Agrawal committed
669 670
    OCStackResult ret = OC_STACK_ERROR;

Sahil Bansal's avatar
Sahil Bansal committed
671
    OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
Sachin Agrawal's avatar
Sachin Agrawal committed
672 673
    VERIFY_NON_NULL(TAG, cred, ERROR);

674 675 676
    //CredId is assigned before appending new cred to the existing
    //credential list and updating svr database in AddCredential().
    cred->credId = 0;
Sachin Agrawal's avatar
Sachin Agrawal committed
677 678 679 680

    VERIFY_NON_NULL(TAG, subject, ERROR);
    memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));

681 682
    VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
            SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
Sachin Agrawal's avatar
Sachin Agrawal committed
683 684
    cred->credType = credType;

Dmitrii Zhuravlev's avatar
Dmitrii Zhuravlev committed
685
#ifdef __WITH_X509__
Sahil Bansal's avatar
Sahil Bansal committed
686
    if (publicData && publicData->data)
Sachin Agrawal's avatar
Sachin Agrawal committed
687
    {
Sahil Bansal's avatar
Sahil Bansal committed
688
        cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
Sachin Agrawal's avatar
Sachin Agrawal committed
689
        VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
Sahil Bansal's avatar
Sahil Bansal committed
690 691
        memcpy(cred->publicData.data, publicData->data, publicData->len);
        cred->publicData.len = publicData->len;
Sachin Agrawal's avatar
Sachin Agrawal committed
692
    }
Dmitrii Zhuravlev's avatar
Dmitrii Zhuravlev committed
693
#endif // __WITH_X509__
Sachin Agrawal's avatar
Sachin Agrawal committed
694

Sahil Bansal's avatar
Sahil Bansal committed
695
    if (privateData && privateData->data)
Sachin Agrawal's avatar
Sachin Agrawal committed
696
    {
Sahil Bansal's avatar
Sahil Bansal committed
697
        cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
Sachin Agrawal's avatar
Sachin Agrawal committed
698
        VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
Sahil Bansal's avatar
Sahil Bansal committed
699 700
        memcpy(cred->privateData.data, privateData->data, privateData->len);
        cred->privateData.len = privateData->len;
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722

        // TODO: Added as workaround. Will be replaced soon.
        cred->privateData.encoding = OIC_ENCODING_RAW;

#if 0
        // NOTE: Test codes to use base64 for credential.
        uint32_t outSize = 0;
        size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((privateData->len + 1));
        char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
        VERIFY_NON_NULL(TAG, b64Buf, ERROR);
        b64Encode(privateData->data, privateData->len, b64Buf, b64BufSize, &outSize);

        OICFree( cred->privateData.data );
        cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
        VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);

        strcpy(cred->privateData.data, b64Buf);
        cred->privateData.encoding = OIC_ENCODING_BASE64;
        cred->privateData.len = outSize;
        OICFree(b64Buf);
#endif //End of Test codes

Sachin Agrawal's avatar
Sachin Agrawal committed
723 724
    }

725 726
    VERIFY_NON_NULL(TAG, rownerID, ERROR);
    memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
Sachin Agrawal's avatar
Sachin Agrawal committed
727 728 729 730 731 732 733 734 735 736 737

    ret = OC_STACK_OK;
exit:
    if (OC_STACK_OK != ret)
    {
        DeleteCredList(cred);
        cred = NULL;
    }
    return cred;
}

738 739 740 741 742
static bool UpdatePersistentStorage(const OicSecCred_t *cred)
{
    bool ret = false;

    // Convert Cred data into JSON for update to persistent storage
Sahil Bansal's avatar
Sahil Bansal committed
743
    if (cred)
744
    {
Sahil Bansal's avatar
Sahil Bansal committed
745 746
        uint8_t *payload = NULL;
        size_t size = 0;
747 748
        int secureFlag = 0;
        OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
Sahil Bansal's avatar
Sahil Bansal committed
749
        if ((OC_STACK_OK == res) && payload)
750
        {
Sahil Bansal's avatar
Sahil Bansal committed
751 752 753 754 755
            if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
            {
                ret = true;
            }
            OICFree(payload);
756 757 758 759
        }
    }
    else //Empty cred list
    {
Sahil Bansal's avatar
Sahil Bansal committed
760
        if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
761 762 763 764 765 766 767 768
        {
            ret = true;
        }
    }
    return ret;
}

/**
Sahil Bansal's avatar
Sahil Bansal committed
769
 * Compare function used LL_SORT for sorting credentials.
770
 *
Sahil Bansal's avatar
Sahil Bansal committed
771 772
 * @param first pointer to OicSecCred_t struct.
 * @param second  pointer to OicSecCred_t struct.
773
 *
Sahil Bansal's avatar
Sahil Bansal committed
774 775 776
 *@return -1, if credId of first is less than credId of second.
 * 0, if credId of first is equal to credId of second.
 * 1, if credId of first is greater than credId of second.
777 778 779
 */
static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
{
Sahil Bansal's avatar
Sahil Bansal committed
780
    if (first->credId < second->credId)
781 782 783
    {
        return -1;
    }
Sahil Bansal's avatar
Sahil Bansal committed
784
    else if (first->credId > second->credId)
785 786 787 788 789 790 791 792 793 794 795 796 797
    {
        return 1;
    }
    else
        return 0;
}

/**
 * GetCredId goes through the cred list and returns the next
 * available credId. The next credId could be the credId that is
 * available due deletion of OicSecCred_t object or one more than
 * credId of last credential in the list.
 *
Sahil Bansal's avatar
Sahil Bansal committed
798
 * @return next available credId if successful, else 0 for error.
799 800 801 802 803 804 805 806 807 808 809
 */
static uint16_t GetCredId()
{
    //Sorts credential list in incremental order of credId
    LL_SORT(gCred, CmpCredId);

    OicSecCred_t *currentCred = NULL, *credTmp = NULL;
    uint16_t nextCredId = 1;

    LL_FOREACH_SAFE(gCred, currentCred, credTmp)
    {
Sahil Bansal's avatar
Sahil Bansal committed
810
        if (currentCred->credId == nextCredId)
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
        {
            nextCredId += 1;
        }
        else
        {
            break;
        }
    }

    VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
    return nextCredId;

exit:
    return 0;
}
826

827
/**
Sahil Bansal's avatar
Sahil Bansal committed
828 829 830
 * Get the default value.
 *
 * @return  NULL for now.
831 832 833
 */
static OicSecCred_t* GetCredDefault()
{
Sahil Bansal's avatar
Sahil Bansal committed
834
    // TODO:Update it when we finalize the default info.
835 836
    return NULL;
}
837

Sachin Agrawal's avatar
Sachin Agrawal committed
838 839 840
OCStackResult AddCredential(OicSecCred_t * newCred)
{
    OCStackResult ret = OC_STACK_ERROR;
841 842 843 844 845
    VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);

    //Assigning credId to the newCred
    newCred->credId = GetCredId();
    VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
Sachin Agrawal's avatar
Sachin Agrawal committed
846 847 848

    //Append the new Cred to existing list
    LL_APPEND(gCred, newCred);
849

Sahil Bansal's avatar
Sahil Bansal committed
850
    if (UpdatePersistentStorage(gCred))
Sachin Agrawal's avatar
Sachin Agrawal committed
851
    {
852 853 854 855 856 857 858 859 860 861 862 863 864
        ret = OC_STACK_OK;
    }

exit:
    return ret;
}

OCStackResult RemoveCredential(const OicUuid_t *subject)
{
    OCStackResult ret = OC_STACK_ERROR;
    OicSecCred_t *cred = NULL;
    OicSecCred_t *tempCred = NULL;
    bool deleteFlag = false;
Sachin Agrawal's avatar
Sachin Agrawal committed
865

866 867
    LL_FOREACH_SAFE(gCred, cred, tempCred)
    {
Sahil Bansal's avatar
Sahil Bansal committed
868
        if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
Sachin Agrawal's avatar
Sachin Agrawal committed
869
        {
870 871 872
            LL_DELETE(gCred, cred);
            FreeCred(cred);
            deleteFlag = 1;
Sachin Agrawal's avatar
Sachin Agrawal committed
873 874 875
        }
    }

Sahil Bansal's avatar
Sahil Bansal committed
876
    if (deleteFlag)
877
    {
Sahil Bansal's avatar
Sahil Bansal committed
878
        if (UpdatePersistentStorage(gCred))
879 880 881 882
        {
            ret = OC_STACK_RESOURCE_DELETED;
        }
    }
Sachin Agrawal's avatar
Sachin Agrawal committed
883
    return ret;
884

Sachin Agrawal's avatar
Sachin Agrawal committed
885 886
}

887 888 889 890 891 892 893 894 895 896 897 898
/**
 * Remove all credential data on credential resource and persistent storage
 *
 * @retval
 *     OC_STACK_OK              - no errors
 *     OC_STACK_ERROR           - stack process error
 */
OCStackResult RemoveAllCredentials(void)
{
    DeleteCredList(gCred);
    gCred = GetCredDefault();

Sahil Bansal's avatar
Sahil Bansal committed
899
    if (!UpdatePersistentStorage(gCred))
900 901 902 903 904 905
    {
        return OC_STACK_ERROR;
    }
    return OC_STACK_OK;
}

906 907
#ifdef __WITH_DTLS__
/**
908
 * Internal function to fill private data of owner PSK.
909
 *
910
 * @param receviedCred recevied owner credential from OBT(PT)
911 912 913
 * @param ownerAdd address of OBT(PT)
 * @param doxm current device's doxm resource
 *
Sahil Bansal's avatar
Sahil Bansal committed
914
 * @return
915 916
 *     true successfully done and valid ower psk information
 *     false Invalid owner psk information or failed to owner psk generation
917
 */
918
static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
919 920 921 922 923 924 925 926 927 928 929 930 931 932
                           const OicSecDoxm_t* doxm)
{
    //Derive OwnerPSK locally
    const char* oxmLabel = GetOxmString(doxm->oxmSel);
    VERIFY_NON_NULL(TAG, oxmLabel, ERROR);

    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
    CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
        (uint8_t*)oxmLabel, strlen(oxmLabel),
        doxm->owner.id, sizeof(doxm->owner.id),
        doxm->deviceID.id, sizeof(doxm->deviceID.id),
        ownerPSK, OWNER_PSK_LENGTH_128);
    VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);

933 934 935 936
    OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
    OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);

    //Generate owner credential based on recevied credential information
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957

    // TODO: Added as workaround, will be replaced soon.
    if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
    {
        receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
        VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
        receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
        memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
    }
    else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
    {
        uint32_t b64OutSize = 0;
        size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
        char* b64Buf = OICCalloc(1, b64BufSize);
        VERIFY_NON_NULL(TAG, b64Buf, ERROR);

        b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);

        receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
        VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
        receviedCred->privateData.len = b64OutSize;
Vinay Bhatia's avatar
Vinay Bhatia committed
958 959
        strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
        receviedCred->privateData.data[b64OutSize] = '\0';
960 961 962 963 964 965
    }
    else
    {
        // TODO: error
        VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
    }
966

967 968 969 970 971
    OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");

    //Verify OwnerPSK information
    return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
            receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
972
exit:
973
    //receviedCred->privateData.data will be deallocated when deleting credential.
974 975 976 977 978
    return false;
}

#endif //__WITH_DTLS__

979
static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
980 981
{
    OCEntityHandlerResult ret = OC_EH_ERROR;
982
    OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest IN");
Sahil Bansal's avatar
Sahil Bansal committed
983

984
    static uint16_t previousMsgId = 0;
Sahil Bansal's avatar
Sahil Bansal committed
985 986
    //Get binary representation of cbor
    OicSecCred_t *cred  = NULL;
Ashwini Kumar's avatar
Ashwini Kumar committed
987
    uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
Sahil Bansal's avatar
Sahil Bansal committed
988
    size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
989

Sahil Bansal's avatar
Sahil Bansal committed
990 991
    OCStackResult res = CBORPayloadToCred(payload, size, &cred);
    if (res == OC_STACK_OK)
992 993 994 995
    {
#ifdef __WITH_DTLS__
        OicUuid_t emptyUuid = {.id={0}};
        const OicSecDoxm_t* doxm = GetDoxmResourceData();
996
        if(doxm && false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
997 998 999 1000 1001 1002 1003
        {
            //in case of owner PSK
            switch(cred->credType)
            {
                case SYMMETRIC_PAIR_WISE_KEY:
                {
                    OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
1004
                    if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
1005
                    {
1006 1007 1008 1009 1010 1011
                        if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
                        {
                            OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
                        }

                        OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
                        if(OC_STACK_OK == AddCredential(cred))
                        {
                            ret = OC_EH_RESOURCE_CREATED;
                        }
                        else
                        {
                            OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
                            ret = OC_EH_ERROR;
                        }
                    }
                    else
                    {
                        OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
                        ret = OC_EH_ERROR;
                    }

1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
                    if(OC_EH_RESOURCE_CREATED == ret)
                    {
                        /**
                         * in case of random PIN based OxM,
                         * revert get_psk_info callback of tinyDTLS to use owner credential.
                         */
                        if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
                        {
                            OicUuid_t emptyUuid = { .id={0}};
                            SetUuidForRandomPinOxm(&emptyUuid);

                            if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
                            {
                                OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
                                ret = OC_EH_ERROR;
                                break;
                            }
                        }

                        //Select cipher suite to use owner PSK
                        if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
                        {
                            OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
                            ret = OC_EH_ERROR;
                        }
                        else
                        {
                            OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
                        }

                        if(CA_STATUS_OK !=
                           CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
                        {
                            OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
                            ret = OC_EH_ERROR;
                        }
                    }

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
                    break;
                }
                case SYMMETRIC_GROUP_KEY:
                case ASYMMETRIC_KEY:
                case SIGNED_ASYMMETRIC_KEY:
                case PIN_PASSWORD:
                case ASYMMETRIC_ENCRYPTION_KEY:
                {
                    OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
                    ret = OC_EH_ERROR;
                    break;
                }
                default:
                {
                    OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
                    ret = OC_EH_ERROR;
                    break;
                }
            }
1085 1086 1087 1088 1089 1090 1091

            if(OC_EH_RESOURCE_CREATED != ret)
            {
                /*
                  * If some error is occured while ownership transfer,
                  * ownership transfer related resource should be revert back to initial status.
                  */
1092 1093
                const OicSecDoxm_t* doxm =  GetDoxmResourceData();
                if(doxm)
1094
                {
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
                    if(!doxm->owned && previousMsgId != ehRequest->messageID)
                    {
                        OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
                                            "DOXM will be reverted.");
                        RestoreDoxmToInitState();
                        RestorePstatToInitState();
                    }
                }
                else
                {
                    OIC_LOG(ERROR, TAG, "Invalid DOXM resource");
1106
                }
1107
            }
1108 1109 1110 1111 1112 1113