/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    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.
 */

/**
 *    @file
 *      This file implements utility functions for OpenSSL, base-64
 *      encoding and decoding, date and time parsing, EUI64 parsing,
 *      OID translation, and file reading.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include <time.h>

#include "weave-tool.h"

#include <Weave/Support/Base64.h>

using namespace nl::Weave::Profiles::Security;
using namespace nl::Weave::ASN1;

int gNIDWeaveDeviceId;
int gNIDWeaveServiceEndpointId;
int gNIDWeaveCAId;
int gNIDWeaveSoftwarePublisherId;

// OBJ_length() and OBJ_get0_data() methods were introduced in OpenSSL
// version 1.1.0; for older versions of OpenSSL these methods are defined here.
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)

static size_t OBJ_length(const ASN1_OBJECT *obj)
{
    if (obj == NULL)
        return 0;
    return obj->length;
}

static const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
{
    if (obj == NULL)
        return NULL;
    return obj->data;
}

#endif

bool InitOpenSSL()
{
    bool res = true;

    // OPENSSL_malloc_init() is a new method, which was first introduced
    // in OpenSSL version 1.1.0. Older versions of OpenSSL implement
    // equivalent method CRYPTO_malloc_init().
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
    OPENSSL_malloc_init();
#else
    CRYPTO_malloc_init();
#endif

    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();

    gNIDWeaveDeviceId = OBJ_create("1.3.6.1.4.1.41387.1.1", "WeaveDeviceId", "WeaveDeviceId");
    if (gNIDWeaveDeviceId == 0)
        ReportOpenSSLErrorAndExit("OBJ_create", res = false);

    gNIDWeaveServiceEndpointId = OBJ_create("1.3.6.1.4.1.41387.1.2", "WeaveServiceEndpointId", "WeaveServiceEndpointId");
    if (gNIDWeaveServiceEndpointId == 0)
        ReportOpenSSLErrorAndExit("OBJ_create", res = false);

    gNIDWeaveCAId = OBJ_create("1.3.6.1.4.1.41387.1.3", "WeaveCAId", "WeaveCAId");
    if (gNIDWeaveCAId == 0)
        ReportOpenSSLErrorAndExit("OBJ_create", res = false);

    gNIDWeaveSoftwarePublisherId = OBJ_create("1.3.6.1.4.1.41387.1.4", "WeaveSoftwarePublisherId", "WeaveSoftwarePublisherId");
    if (gNIDWeaveSoftwarePublisherId == 0)
        ReportOpenSSLErrorAndExit("OBJ_create", res = false);

    ASN1_STRING_TABLE_add(gNIDWeaveDeviceId, 16, 16, B_ASN1_UTF8STRING, 0);
    ASN1_STRING_TABLE_add(gNIDWeaveServiceEndpointId, 16, 16, B_ASN1_UTF8STRING, 0);
    ASN1_STRING_TABLE_add(gNIDWeaveCAId, 16, 16, B_ASN1_UTF8STRING, 0);
    ASN1_STRING_TABLE_add(gNIDWeaveSoftwarePublisherId, 16, 16, B_ASN1_UTF8STRING, 0);

exit:
    return res;
}

OID NIDToWeaveOID(int nid)
{
    const ASN1_OBJECT *encodedOID;

    encodedOID = OBJ_nid2obj(nid);
    if (encodedOID == NULL)
        return kOID_Unknown;

    return ParseObjectID(OBJ_get0_data(encodedOID), OBJ_length(encodedOID));
}

char *Base64Encode(const uint8_t *inData, uint32_t inDataLen)
{
    uint32_t outDataLen;
    return (char *)Base64Encode(inData, inDataLen, NULL, 0, outDataLen);
}

uint8_t *Base64Encode(const uint8_t *inData, uint32_t inDataLen, uint8_t *outBuf, uint32_t outBufSize, uint32_t& outDataLen)
{
    uint8_t *res = NULL;

    outDataLen = BASE64_ENCODED_LEN(inDataLen);

    if (outBuf != NULL && (outDataLen + 1) > outBufSize)
    {
        fprintf(stderr, "Buffer overflow\n");
        ExitNow(res = NULL);
    }

    res = (uint8_t *)malloc(outDataLen + 1);
    if (res == NULL)
    {
        fprintf(stderr, "Memory allocation error\n");
        ExitNow(res = NULL);
    }
    memset(res, 0xAB, outDataLen + 1);

    outDataLen = nl::Base64Encode32(inData, inDataLen, (char *)res);
    res[outDataLen] = 0;

    if (outBuf != NULL)
    {
        memcpy(outBuf, res, outDataLen + 1);
        free(res);
        res = outBuf;
    }

exit:
    return res;
}

uint8_t *Base64Decode(const uint8_t *inData, uint32_t inDataLen, uint8_t *outBuf, uint32_t outBufSize, uint32_t& outDataLen)
{
    uint8_t *res = NULL;

    outDataLen = BASE64_MAX_DECODED_LEN(inDataLen);

    if (outBuf != NULL)
    {
        if (outDataLen > outBufSize)
        {
            fprintf(stderr, "Buffer overflow\n");
            ExitNow();
        }
        res = outBuf;
    }
    else
    {
        res = (uint8_t *)malloc(outDataLen);
        if (res == NULL)
        {
            fprintf(stderr, "Memory allocation error\n");
            ExitNow();
        }
    }

    outDataLen = nl::Base64Decode32((const char *)inData, inDataLen, res);
    if (outDataLen == UINT32_MAX)
    {
        fprintf(stderr, "Base-64 decode error\n");
        if (res != outBuf)
            free(res);
        ExitNow(res = NULL);
    }

exit:
    return res;
}

bool ContainsPEMMarker(const char *marker, const uint8_t *data, uint32_t dataLen)
{
    size_t markerLen = strlen(marker);

    if (dataLen > markerLen)
        for (uint32_t i = 0; i <= dataLen - markerLen; i++)
            if (strncmp((char *)data + i, marker, markerLen) == 0)
                return true;
    return false;
}

bool ParseEUI64(const char *str, uint64_t& nodeId)
{
    char *parseEnd;

    errno = 0;
    nodeId = strtoull(str, &parseEnd, 16);
    return parseEnd > str && *parseEnd == 0 && (nodeId != ULLONG_MAX || errno == 0);
}

bool ParseDateTime(const char *str, struct tm& date)
{
    const char *p;

    memset(&date, 0, sizeof(date));

    if ((p = strptime(str, "%Y-%m-%d %H:%M:%S", &date)) == NULL &&
        (p = strptime(str, "%Y/%m/%d %H:%M:%S", &date)) == NULL &&
        (p = strptime(str, "%Y%m%d%H%M%SZ", &date)) == NULL  &&
        (p = strptime(str, "%Y-%m-%d", &date)) == NULL &&
        (p = strptime(str, "%Y/%m/%d", &date)) == NULL &&
        (p = strptime(str, "%Y%m%d", &date)) == NULL)
    {
        return false;
    }

    if (*p != 0)
    {
        return false;
    }

    return true;
}

bool ReadFileIntoMem(const char *fileName, uint8_t *& data, uint32_t &dataLen)
{
    bool res = true;
    FILE *file = NULL;
    long int fileLen;
    size_t readRes;

    data = NULL;
    dataLen = 0;

    file = fopen(fileName, "r");
    if (file == NULL)
    {
        fprintf(stderr, "weave: Unable to open %s: %s\n", fileName, strerror(errno));
        ExitNow(res = false);
    }

    fseek(file, 0, SEEK_END);
    fileLen = ftell(file);
    fseek(file, 0, SEEK_SET);
    if (fileLen < 0 || ferror(file))
    {
        fprintf(stderr, "weave: Error reading %s: %s\n", fileName, strerror(errno));
        ExitNow(res = false);
    }

    dataLen = (uint32_t)fileLen;
    data = (uint8_t *)malloc((size_t)dataLen);
    if (data == NULL)
    {
        fprintf(stderr, "weave: Error reading %s: out of memory\n", fileName);
        ExitNow(res = false);
    }

    readRes = fread(data, 1, (size_t)dataLen, file);
    if (readRes < (size_t)dataLen || ferror(file))
    {
        fprintf(stderr, "weave: Error reading %s: %s\n", fileName, strerror(errno));
        ExitNow(res = false);
    }

exit:
    if (file != NULL)
        fclose(file);
    if (!res && data != NULL)
    {
        free(data);
        data = NULL;
    }
    return res;
}
