// Copyright 1999-2016 The OpenSSL Project Authors. 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
//
//     https://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.

#include <stdio.h>

#include <openssl/asn1t.h>
#include <openssl/conf.h>
#include <openssl/obj.h>
#include <openssl/x509.h>

#include "internal.h"


using namespace bssl;

ASN1_SEQUENCE(OTHERNAME) = {
    ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
    // Maybe have a true ANY DEFINED BY later
    ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0),
} ASN1_SEQUENCE_END(OTHERNAME)

IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OTHERNAME)

ASN1_SEQUENCE(EDIPARTYNAME) = {
    // DirectoryString is a CHOICE type, so use explicit tagging.
    ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
    ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1),
} ASN1_SEQUENCE_END(EDIPARTYNAME)

IMPLEMENT_ASN1_ALLOC_FUNCTIONS(EDIPARTYNAME)

BSSL_NAMESPACE_BEGIN

ASN1_CHOICE(GENERAL_NAME) = {
    ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
    ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
    ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
    // Don't decode this
    ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
    // X509_NAME is a CHOICE type so use EXPLICIT
    ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
    ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
    ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING,
             GEN_URI),
    ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
    ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID),
} ASN1_CHOICE_END(GENERAL_NAME)

BSSL_NAMESPACE_END

IMPLEMENT_ASN1_FUNCTIONS_const(GENERAL_NAME)

BSSL_NAMESPACE_BEGIN

ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF,
                                                          0, GeneralNames,
                                                          GENERAL_NAME)
ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)

BSSL_NAMESPACE_END

IMPLEMENT_ASN1_FUNCTIONS_const(GENERAL_NAMES)

IMPLEMENT_ASN1_DUP_FUNCTION_const(GENERAL_NAME)

static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) {
  // nameAssigner is optional and may be NULL.
  if (a->nameAssigner == nullptr) {
    if (b->nameAssigner != nullptr) {
      return -1;
    }
  } else {
    if (b->nameAssigner == nullptr ||
        ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner) != 0) {
      return -1;
    }
  }

  // partyName may not be NULL.
  return ASN1_STRING_cmp(a->partyName, b->partyName);
}

// Returns 0 if they are equal, != 0 otherwise.
static int othername_cmp(const OTHERNAME *a, const OTHERNAME *b) {
  int result = -1;

  if (!a || !b) {
    return -1;
  }
  // Check their type first.
  if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) {
    return result;
  }
  // Check the value.
  result = ASN1_TYPE_cmp(a->value, b->value);
  return result;
}

// Returns 0 if they are equal, != 0 otherwise.
int bssl::GENERAL_NAME_cmp(const GENERAL_NAME *a, const GENERAL_NAME *b) {
  if (!a || !b || a->type != b->type) {
    return -1;
  }

  switch (a->type) {
    case GEN_X400:
      return ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);

    case GEN_EDIPARTY:
      return edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);

    case GEN_OTHERNAME:
      return othername_cmp(a->d.otherName, b->d.otherName);

    case GEN_EMAIL:
    case GEN_DNS:
    case GEN_URI:
      return ASN1_STRING_cmp(a->d.ia5, b->d.ia5);

    case GEN_DIRNAME:
      return X509_NAME_cmp(a->d.dirn, b->d.dirn);

    case GEN_IPADD:
      return ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);

    case GEN_RID:
      return OBJ_cmp(a->d.rid, b->d.rid);
  }

  return -1;
}

void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) {
  switch (type) {
    case GEN_X400:
      a->d.x400Address = reinterpret_cast<ASN1_STRING *>(value);
      break;

    case GEN_EDIPARTY:
      a->d.ediPartyName = reinterpret_cast<EDIPARTYNAME *>(value);
      break;

    case GEN_OTHERNAME:
      a->d.otherName = reinterpret_cast<OTHERNAME *>(value);
      break;

    case GEN_EMAIL:
    case GEN_DNS:
    case GEN_URI:
      a->d.ia5 = reinterpret_cast<ASN1_STRING *>(value);
      break;

    case GEN_DIRNAME:
      a->d.dirn = reinterpret_cast<X509_NAME *>(value);
      break;

    case GEN_IPADD:
      a->d.ip = reinterpret_cast<ASN1_STRING *>(value);
      break;

    case GEN_RID:
      a->d.rid = reinterpret_cast<ASN1_OBJECT *>(value);
      break;
  }
  a->type = type;
}

void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *out_type) {
  if (out_type) {
    *out_type = a->type;
  }
  switch (a->type) {
    case GEN_X400:
      return a->d.x400Address;

    case GEN_EDIPARTY:
      return a->d.ediPartyName;

    case GEN_OTHERNAME:
      return a->d.otherName;

    case GEN_EMAIL:
    case GEN_DNS:
    case GEN_URI:
      return a->d.ia5;

    case GEN_DIRNAME:
      return a->d.dirn;

    case GEN_IPADD:
      return a->d.ip;

    case GEN_RID:
      return a->d.rid;

    default:
      return nullptr;
  }
}

int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid,
                                ASN1_TYPE *value) {
  OTHERNAME *oth;
  oth = OTHERNAME_new();
  if (!oth) {
    return 0;
  }
  ASN1_TYPE_free(oth->value);
  oth->type_id = oid;
  oth->value = value;
  GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
  return 1;
}

int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **out_oid,
                                ASN1_TYPE **out_value) {
  if (gen->type != GEN_OTHERNAME) {
    return 0;
  }
  if (out_oid != nullptr) {
    *out_oid = gen->d.otherName->type_id;
  }
  if (out_value != nullptr) {
    *out_value = gen->d.otherName->value;
  }
  return 1;
}
