/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 * certt.h - public data structures for the certificate library
 */
#ifndef _PCERTT_H_
#define _PCERTT_H_

#include "prclist.h"
#include "pkcs11t.h"
#include "seccomon.h"
#include "secoidt.h"
#include "plarena.h"
#include "prcvar.h"
#include "prio.h"
#include "prmon.h"

/* Non-opaque objects */
typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle;
typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey;

typedef struct NSSLOWCERTTrustStr NSSLOWCERTTrust;
typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust;
typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate;
typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList;
typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN;
typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData;
typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo;
typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity;

/*
** An X.509 validity object
*/
struct NSSLOWCERTValidityStr {
    PLArenaPool *arena;
    SECItem notBefore;
    SECItem notAfter;
};

/*
 * A serial number and issuer name, which is used as a database key
 */
struct NSSLOWCERTCertKeyStr {
    SECItem serialNumber;
    SECItem derIssuer;
};

/*
** A signed data object. Used to implement the "signed" macro used
** in the X.500 specs.
*/
struct NSSLOWCERTSignedDataStr {
    SECItem data;
    SECAlgorithmID signatureAlgorithm;
    SECItem signature;
};

/*
** An X.509 subject-public-key-info object
*/
struct NSSLOWCERTSubjectPublicKeyInfoStr {
    PLArenaPool *arena;
    SECAlgorithmID algorithm;
    SECItem subjectPublicKey;
};

typedef struct _certDBEntryCert certDBEntryCert;
typedef struct _certDBEntryRevocation certDBEntryRevocation;

struct NSSLOWCERTCertTrustStr {
    unsigned int sslFlags;
    unsigned int emailFlags;
    unsigned int objectSigningFlags;
};

/*
** PKCS11 Trust representation
*/
struct NSSLOWCERTTrustStr {
    NSSLOWCERTTrust *next;
    NSSLOWCERTCertDBHandle *dbhandle;
    SECItem dbKey;            /* database key for this cert */
    certDBEntryCert *dbEntry; /* database entry struct */
    NSSLOWCERTCertTrust *trust;
    SECItem *derCert; /* original DER for the cert */
    unsigned char dbKeySpace[512];
};

/*
** An X.509 certificate object (the unsigned form)
*/
struct NSSLOWCERTCertificateStr {
    /* the arena is used to allocate any data structures that have the same
     * lifetime as the cert.  This is all stuff that hangs off of the cert
     * structure, and is all freed at the same time.  I is used when the
     * cert is decoded, destroyed, and at some times when it changes
     * state
     */
    NSSLOWCERTCertificate *next;
    NSSLOWCERTCertDBHandle *dbhandle;

    SECItem derCert;   /* original DER for the cert */
    SECItem derIssuer; /* DER for issuer name */
    SECItem derSN;
    SECItem serialNumber;
    SECItem derSubject; /* DER for subject name */
    SECItem derSubjKeyInfo;
    NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
    SECItem certKey; /* database key for this cert */
    SECItem validity;
    certDBEntryCert *dbEntry; /* database entry struct */
    SECItem subjectKeyID;     /* x509v3 subject key identifier */
    SECItem extensions;
    char *nickname;
    char *emailAddr;
    NSSLOWCERTCertTrust *trust;

    /* the reference count is modified whenever someone looks up, dups
     * or destroys a certificate
     */
    int referenceCount;

    char nicknameSpace[200];
    char emailAddrSpace[200];
    unsigned char certKeySpace[512];
};

#define SEC_CERTIFICATE_VERSION_1 0 /* default created */
#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */
#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */

#define SEC_CRL_VERSION_1 0 /* default */
#define SEC_CRL_VERSION_2 1 /* v2 extensions */

#define NSS_MAX_LEGACY_DB_KEY_SIZE (60 * 1024)

struct NSSLOWCERTIssuerAndSNStr {
    SECItem derIssuer;
    SECItem serialNumber;
};

typedef SECStatus (*NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg);

/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */
/* callback to return database name based on version number */
typedef char *(*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion);

/* XXX Lisa thinks the template declarations belong in cert.h, not here? */

#include "secasn1t.h" /* way down here because I expect template stuff to
             * move out of here anyway */

/*
 * Certificate Database related definitions and data structures
 */

/* version number of certificate database */
#define CERT_DB_FILE_VERSION 8
#define CERT_DB_V7_FILE_VERSION 7
#define CERT_DB_CONTENT_VERSION 2

#define SEC_DB_ENTRY_HEADER_LEN 3
#define SEC_DB_KEY_HEADER_LEN 1

/* All database entries have this form:
 *
 *  byte offset field
 *  ----------- -----
 *  0       version
 *  1       type
 *  2       flags
 */

/* database entry types */
typedef enum {
    certDBEntryTypeVersion = 0,
    certDBEntryTypeCert = 1,
    certDBEntryTypeNickname = 2,
    certDBEntryTypeSubject = 3,
    certDBEntryTypeRevocation = 4,
    certDBEntryTypeKeyRevocation = 5,
    certDBEntryTypeSMimeProfile = 6,
    certDBEntryTypeContentVersion = 7,
    certDBEntryTypeBlob = 8
} certDBEntryType;

typedef struct {
    certDBEntryType type;
    unsigned int version;
    unsigned int flags;
    PLArenaPool *arena;
} certDBEntryCommon;

/*
 * Certificate entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       sslFlags-msb
 *  1       sslFlags-lsb
 *  2       emailFlags-msb
 *  3       emailFlags-lsb
 *  4       objectSigningFlags-msb
 *  5       objectSigningFlags-lsb
 *  6       derCert-len-msb
 *  7       derCert-len-lsb
 *  8       nickname-len-msb
 *  9       nickname-len-lsb
 *  ...     derCert
 *  ...     nickname
 *
 * NOTE: the nickname string as stored in the database is null terminated,
 *      in other words, the last byte of the db entry is always 0
 *      if a nickname is present.
 * NOTE: if nickname is not present, then nickname-len-msb and
 *      nickname-len-lsb will both be zero.
 */
struct _certDBEntryCert {
    certDBEntryCommon common;
    certDBEntryCert *next;
    NSSLOWCERTCertTrust trust;
    SECItem derCert;
    char *nickname;
    char nicknameSpace[200];
    unsigned char derCertSpace[2048];
};

/*
 * Certificate Nickname entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       subjectname-len-msb
 *  1           subjectname-len-lsb
 *  2...        subjectname
 *
 * The database key for this type of entry is a nickname string
 * The "subjectname" value is the DER encoded DN of the identity
 *   that matches this nickname.
 */
typedef struct {
    certDBEntryCommon common;
    char *nickname;
    SECItem subjectName;
} certDBEntryNickname;

#define DB_NICKNAME_ENTRY_HEADER_LEN 2

/*
 * Certificate Subject entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       ncerts-msb
 *  1       ncerts-lsb
 *  2       nickname-msb
 *  3       nickname-lsb
 *  4       emailAddr-msb
 *  5       emailAddr-lsb
 *  ...     nickname
 *  ...     emailAddr
 *  ...+2*i     certkey-len-msb
 *  ...+1+2*i       certkey-len-lsb
 *  ...+2*ncerts+2*i keyid-len-msb
 *  ...+1+2*ncerts+2*i keyid-len-lsb
 *  ...     certkeys
 *  ...     keyids
 *
 * The database key for this type of entry is the DER encoded subject name
 * The "certkey" value is an array of  certificate database lookup keys that
 *   points to the database entries for the certificates that matche
 *   this subject.
 *
 */
typedef struct _certDBEntrySubject {
    certDBEntryCommon common;
    SECItem derSubject;
    unsigned int ncerts;
    char *nickname;
    SECItem *certKeys;
    SECItem *keyIDs;
    char **emailAddrs;
    unsigned int nemailAddrs;
} certDBEntrySubject;

#define DB_SUBJECT_ENTRY_HEADER_LEN 6

/*
 * Certificate SMIME profile entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       subjectname-len-msb
 *  1           subjectname-len-lsb
 *  2       smimeoptions-len-msb
 *  3       smimeoptions-len-lsb
 *  4       options-date-len-msb
 *  5       options-date-len-lsb
 *  6...        subjectname
 *  ...     smimeoptions
 *  ...     options-date
 *
 * The database key for this type of entry is the email address string
 * The "subjectname" value is the DER encoded DN of the identity
 *   that matches this nickname.
 * The "smimeoptions" value is a string that represents the algorithm
 *   capabilities on the remote user.
 * The "options-date" is the date that the smime options value was created.
 *   This is generally the signing time of the signed message that contained
 *   the options.  It is a UTCTime value.
 */
typedef struct {
    certDBEntryCommon common;
    char *emailAddr;
    SECItem subjectName;
    SECItem smimeOptions;
    SECItem optionsDate;
} certDBEntrySMime;

#define DB_SMIME_ENTRY_HEADER_LEN 6

/*
 * Crl/krl entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       derCert-len-msb
 *  1       derCert-len-lsb
 *  2       url-len-msb
 *  3       url-len-lsb
 *  ...     derCert
 *  ...     url
 *
 * NOTE: the url string as stored in the database is null terminated,
 *      in other words, the last byte of the db entry is always 0
 *      if a nickname is present.
 * NOTE: if url is not present, then url-len-msb and
 *      url-len-lsb will both be zero.
 */
#define DB_CRL_ENTRY_HEADER_LEN 4
struct _certDBEntryRevocation {
    certDBEntryCommon common;
    SECItem derCrl;
    char *url; /* where to load the crl from */
};

/*
 * Database Version Entry:
 *
 *  byte offset field
 *  ----------- -----
 *  only the low level header...
 *
 * The database key for this type of entry is the string "Version"
 */
typedef struct {
    certDBEntryCommon common;
} certDBEntryVersion;

#define SEC_DB_VERSION_KEY "Version"
#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY)

/*
 * Database Content Version Entry:
 *
 *  byte offset field
 *  ----------- -----
 *  0       contentVersion
 *
 * The database key for this type of entry is the string "ContentVersion"
 */
typedef struct {
    certDBEntryCommon common;
    char contentVersion;
} certDBEntryContentVersion;

#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion"
#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY)

typedef union {
    certDBEntryCommon common;
    certDBEntryCert cert;
    certDBEntryContentVersion content;
    certDBEntryNickname nickname;
    certDBEntryRevocation revocation;
    certDBEntrySMime smime;
    certDBEntrySubject subject;
    certDBEntryVersion version;
} certDBEntry;

/* length of the fixed part of a database entry */
#define DBCERT_V4_HEADER_LEN 7
#define DB_CERT_V5_ENTRY_HEADER_LEN 7
#define DB_CERT_V6_ENTRY_HEADER_LEN 7
#define DB_CERT_ENTRY_HEADER_LEN 10

/* common flags for all types of certificates */
#define CERTDB_TERMINAL_RECORD (1u << 0)
#define CERTDB_TRUSTED (1u << 1)
#define CERTDB_SEND_WARN (1u << 2)
#define CERTDB_VALID_CA (1u << 3)
#define CERTDB_TRUSTED_CA (1u << 4) /* trusted for issuing server certs */
#define CERTDB_NS_TRUSTED_CA (1u << 5)
#define CERTDB_USER (1u << 6)
#define CERTDB_TRUSTED_CLIENT_CA (1u << 7) /* trusted for issuing client certs */
#define CERTDB_INVISIBLE_CA (1u << 8)      /* don't show in UI */
#define CERTDB_GOVT_APPROVED_CA (1u << 9)  /* can do strong crypto in export ver */
#define CERTDB_MUST_VERIFY (1u << 10)      /* explicitly don't trust this cert */
#define CERTDB_TRUSTED_UNKNOWN (1u << 11)  /* accept trust from another source */

/* bits not affected by the CKO_NETSCAPE_TRUST object */
#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER |                                                  \
                                    CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \
                                    CERTDB_GOVT_APPROVED_CA)

#endif /* _PCERTT_H_ */
