#ifndef __PARSER_CERTIFICATE_H__
#define __PARSER_CERTIFICATE_H__


#include "basedef.h"

#define KEYHANDLE_KEY_LENGTH_LENGTH       (2)


/*
    X.509 v3 certificate basic syntax(rfc5280)
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form
} TlvCertDecodeData;

/*
AlgorithmIdentifier  ::=  SEQUENCE  {
    algorithm               OBJECT IDENTIFIER,
    parameters              ANY DEFINED BY algorithm OPTIONAL  }
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData algorithm;        //[M]
    TlvCertDecodeData parameters;       //[M]
} TlvSignatureAlgorithm;

/*
AlgorithmIdentifier  ::=  SEQUENCE  {
    algorithm               OBJECT IDENTIFIER,
    parameters              ANY DEFINED BY algorithm OPTIONAL  }
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData algorithm;        //[M]
    TlvCertDecodeData parameters;       //[M]
} TlvSubjectPublicKeyAlgorithm;

/*
SubjectPublicKeyInfo  ::=  SEQUENCE  {
    algorithm            AlgorithmIdentifier,
    subjectPublicKey     BIT STRING  }
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvSubjectPublicKeyAlgorithm algorithm;     //[M]
    TlvCertDecodeData subjectPublicKey;         //[M]
} TlvSubjectPublicKeyInfo;

/*
TBSCertificate  ::=  SEQUENCE  {
    version         [0]  EXPLICIT Version DEFAULT v1,
    serialNumber         CertificateSerialNumber,
    signature            AlgorithmIdentifier,
    issuer               Name,
    validity             Validity,
    subject              Name,
    subjectPublicKeyInfo SubjectPublicKeyInfo,
    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                       -- If present, version MUST be v2 or v3
    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                       -- If present, version MUST be v2 or v3
    extensions      [3]  EXPLICIT Extensions OPTIONAL
                       -- If present, version MUST be v3
    }

Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }

CertificateSerialNumber  ::=  INTEGER

Validity ::= SEQUENCE {
    notBefore      Time,
    notAfter       Time }

Time ::= CHOICE {
    utcTime        UTCTime,
    generalTime    GeneralizedTime }

UniqueIdentifier  ::=  BIT STRING

Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension

Extension  ::=  SEQUENCE  {
    extnID      OBJECT IDENTIFIER,
    critical    BOOLEAN DEFAULT FALSE,
    extnValue   OCTET STRING
                -- contains the DER encoding of an ASN.1 value
                -- corresponding to the extension type identified
                -- by extnID
    }

Name ::= CHOICE { -- only one possibility for now --
    rdnSequence  RDNSequence }

RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName ::=
    SET SIZE (1..MAX) OF AttributeTypeAndValue

AttributeTypeAndValue ::= SEQUENCE {
    type     AttributeType,
    value    AttributeValue }

AttributeType ::= OBJECT IDENTIFIER

AttributeValue ::= ANY -- DEFINED BY AttributeType

DirectoryString ::= CHOICE {
    teletexString           TeletexString (SIZE (1..MAX)),
    printableString         PrintableString (SIZE (1..MAX)),
    universalString         UniversalString (SIZE (1..MAX)),
    utf8String              UTF8String (SIZE (1..MAX)),
    bmpString               BMPString (SIZE (1..MAX)) }
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData version;                      //[M]
    TlvCertDecodeData serialNumber;                 //[M]
    TlvCertDecodeData signature;                    //[M]
    TlvCertDecodeData issuer;                       //[M]
    TlvCertDecodeData validity;                     //[M]
    TlvCertDecodeData subject;                      //[M]
    TlvSubjectPublicKeyInfo subjectPublicKeyInfo;   //[M]
    TlvCertDecodeData issuerUniqueID;               //[O]
    TlvCertDecodeData subjectUniqueID;              //[O]
    TlvCertDecodeData extensions;                   //[O]
} TlvTbsCertificate;

/*
Certificate  ::=  SEQUENCE  {
    tbsCertificate       TBSCertificate,
    signatureAlgorithm   AlgorithmIdentifier,
    signatureValue       BIT STRING  }
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvTbsCertificate tbsCertificate;           //[M]
    TlvSignatureAlgorithm signatureAlgorithm;   //[M]
    TlvCertDecodeData signatureValue;           //[M]
} TlvCertificate;


/*
Explicit
 */

/*
ECPrivateKey ::= SEQUENCE {
    version     INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
    privateKey  OCTET STRING,
    parameters  [0] ECParameters {{ NamedCurve }} OPTIONAL,
    publicKey   [1] BIT STRING OPTIONAL
}
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData version;      //[M]
    TlvCertDecodeData privatekey;   //[M]
    TlvCertDecodeData namedCurve;   //[O]
    TlvCertDecodeData publicKey;    //[O]
} TlvECPrivateKey;


typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData version;      //[M]
    TlvCertDecodeData privatekey;   //[M]
    TlvCertDecodeData namedCurve;   //[O]
    TlvCertDecodeData publicKey;    //[O]
} TlvRsaPrivateKey;


/*
RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}
*/
typedef struct
{
    uint16 tag;
    uint16 length;
    uint16 offset;          // The offset of value pointer in blob data
    uint16 lengthOctets;    // It would be more than 1 for the long form

    TlvCertDecodeData modulus;                //[M]
    TlvCertDecodeData publicExponent;         //[M]
} TlvRSAPublicKey;



boolean parseECPrivateKey(const BlobData* pBlobInput, uint16 offset, TlvECPrivateKey* pTlvECPrivateKey);
boolean getEcPrivateKeyWithLength(const BlobData* pBlobInput, BlobData* pBlobPrivateKey);
AuthnrResult getPrivateKeyWithLength(const BlobData* pBlobInput, BlobData* pBlobKey, uint32 keyLength);
boolean parseCertificate(const BlobData* pBlobInput, uint16 offset, TlvCertificate* pTlvCertificate);
boolean parseRSAPublicKey(const BlobData* pBlobInput, uint16 offset, TlvRSAPublicKey* pTlvRSAPublicKey);
boolean getCertificateSubjectDn(const BlobData* pBlobCertificate, BlobData* pBlobDn);

#endif  //end of __PARSER_CERTIFICATE_H__
