/*
// Copyright (c) 2016 Intel Corporation
//
// 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.
*/

#ifdef OC_SECURITY

#include "oc_cred.h"
#include "config.h"
#include "oc_api.h"
#include "oc_core_res.h"
#include "oc_doxm.h"
#include "oc_dtls.h"
#include "util/oc_list.h"
#include "util/oc_memb.h"

OC_LIST(creds_l);
OC_MEMB(creds, oc_sec_cred_t, MAX_NUM_SUBJECTS + 1);
#define OXM_JUST_WORKS "oic.sec.doxm.jw"

oc_sec_cred_t *
oc_sec_find_cred(oc_uuid_t *subjectuuid)
{
    oc_sec_cred_t *cred = oc_list_head(creds_l);

    while (cred != NULL) {
        if (strncmp(cred->subjectuuid.id, subjectuuid->id, 16) == 0) {
            return cred;
        }
        cred = cred->next;
    }
    return NULL;
}

oc_sec_cred_t *
oc_sec_get_cred(oc_uuid_t *subjectuuid)
{
    oc_sec_cred_t *cred = oc_sec_find_cred(subjectuuid);

    if (cred == NULL) {
        cred = oc_memb_alloc(&creds);
        strncpy(cred->subjectuuid.id, subjectuuid->id, 16);
        oc_list_add(creds_l, cred);
    }
    return cred;
}

void
oc_sec_encode_cred(void)
{
    oc_sec_cred_t *creds = oc_list_head(creds_l);
    char uuid[37];

    oc_rep_start_root_object();
    oc_process_baseline_interface(oc_core_get_resource_by_index(OCF_SEC_CRED));
    oc_rep_set_array(root, creds);
    if (creds == NULL) {
        oc_rep_object_array_start_item(creds);
        oc_rep_object_array_end_item(creds);
    }
    while (creds != NULL) {
        oc_rep_object_array_start_item(creds);
        oc_rep_set_int(creds, credid, creds->credid);
        oc_rep_set_int(creds, credtype, creds->credtype);
        oc_uuid_to_str(&creds->subjectuuid, uuid, 37);
        oc_rep_set_text_string(creds, subjectuuid, uuid);
        oc_rep_set_object(creds, privatedata);
        oc_rep_set_byte_string(privatedata, data, creds->key);
        oc_rep_set_text_string(privatedata, encoding, "oic.sec.encoding.raw");
        oc_rep_close_object(creds, privatedata);
        oc_rep_object_array_end_item(creds);
        creds = creds->next;
    }
    oc_rep_close_array(root, creds);
    oc_rep_end_root_object();
}

bool
oc_sec_decode_cred(oc_rep_t *rep, oc_sec_cred_t **owner)
{
    oc_sec_doxm_t *doxm = oc_sec_get_doxm();
    int credid = 0, credtype = 0;
    char subjectuuid[37] = { 0 };
    oc_uuid_t subject;
    oc_sec_cred_t *credobj;
    bool got_key = false;
    int len = 0;
    uint8_t key[16];

    while (rep != NULL) {
        len = oc_string_len(rep->name);
        switch (rep->type) {
        case STRING:
            if (len == 10 &&
                strncmp(oc_string(rep->name), "rowneruuid", 10) == 0) {
                oc_str_to_uuid(oc_string(rep->value_string), &doxm->rowneruuid);
            }
            break;
        case OBJECT_ARRAY: {
            oc_rep_t *creds_array = rep->value_object_array;
            while (creds_array != NULL) {
                oc_rep_t *cred = creds_array->value_object;
                bool valid_cred = false;
                while (cred != NULL) {
                    len = oc_string_len(cred->name);
                    valid_cred = true;
                    switch (cred->type) {
                    case INT:
                        if (len == 6 &&
                          strncmp(oc_string(cred->name), "credid", 6) == 0) {
                            credid = cred->value_int;
                        } else if (len == 8 &&
                          strncmp(oc_string(cred->name), "credtype", 8) == 0) {
                            credtype = cred->value_int;
                        }
                        break;
                    case STRING:
                        if (len == 11 &&
                            strncmp(oc_string(cred->name), "subjectuuid",
                                    11) == 0) {
                            strncpy(subjectuuid, oc_string(cred->value_string),
                                    oc_string_len(cred->value_string) + 1);
                        }
                        break;
                    case OBJECT: {
                        oc_rep_t *data = cred->value_object;

                        while (data != NULL) {
                            switch (data->type) {
                            case BYTE_STRING: {
                                got_key = true;
                                int psk = 0;
                                uint8_t *p = oc_cast(data->value_string,
                                                     uint8_t);
                                size_t size = oc_string_len(data->value_string);
                                if (size != 16) {
                                    return false;
                                }
                                while (psk < size) {
                                    key[psk] = p[psk];
                                    psk++;
                                }
                            }
                                break;
                            default:
                                break;
                            }
                            data = data->next;
                        }
                    }
                        break;
                    default:
                        break;
                    }
                    cred = cred->next;
                }
                if (valid_cred) {
                    oc_str_to_uuid(subjectuuid, &subject);
                    credobj = oc_sec_get_cred(&subject);
                    credobj->credid = credid;
                    credobj->credtype = credtype;

                    if (got_key) {
                        memcpy(credobj->key, key, 16);
                    } else {
                        if (owner) {
                            *owner = credobj;
                        }
                    }
                }
                creds_array = creds_array->next;
            }
        }
            break;
        default:
            break;
        }
        rep = rep->next;
    }
    return true;
}

void
post_cred(oc_request_t *request, oc_interface_mask_t interface)
{
    oc_sec_doxm_t *doxm = oc_sec_get_doxm();
    oc_sec_cred_t *owner = NULL;
    bool success = oc_sec_decode_cred(request->request_payload, &owner);

    if (owner && strncmp(owner->subjectuuid.id, doxm->rowneruuid.id, 16) == 0) {
        oc_uuid_t *dev = oc_core_get_device_id(0);
        oc_sec_derive_owner_psk(request->origin, OXM_JUST_WORKS,
                                strlen(OXM_JUST_WORKS), owner->subjectuuid.id,
                                       16,
                                dev->id, 16, owner->key, 16);
    }
    if (!success) {
        oc_send_response(request, OC_STATUS_BAD_REQUEST);
    } else {
        oc_send_response(request, OC_STATUS_CHANGED);
    }
}

#endif /* OC_SECURITY */
