/*
 * Copyright (C) 2024 - 2026, Stephan Mueller <smueller@chronox.de>
 *
 * License: see LICENSE file in root directory
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
 * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#ifndef LC_X509_GENERATOR_H
#define LC_X509_GENERATOR_H

#include "lc_x509_common.h"

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup X509Gen X.509 Certificate Generate Handling
 *
 * Concept of X.509 certificate generate handling in leancrypto
 *
 * The leancrypto library provides an X.509 generator which can create
 * X.509 certificates. The generator does not enforce any X.509 limitations and
 * thus allows the caller to generate any combination of field offered by the
 * X.509 specification. To appropriately use the X.509 parser, please consider
 * the following rules:
 *
 * 1. The generated X.509 data blob is independent of the original X.509
 *    certificate data structure.
 *
 * 2. The generator does not allocate any memory. All memory MUST be provided
 *    by the caller. Thus, if the caller provides insufficient memory, the
 *    generator will return -EOVERFLOW.
 *
 * 3. Before invoking the X.509 generator, the caller must allocate an
 *    \p lc_x509_certificate data structure (e.g. on stack) and fill it with the
 *    numerous setter functions to add data.
 */

/**
 * @ingroup X509Gen
 * @brief Helper function for checking available buffer space
 *
 * This service function is intended to support the encoding operation. The
 * encoding operation uses \p avail_datalen indicating the yet available
 * buffer space in the ASN.1 target buffer. This function return 0 when
 * the \p requested_len still fits into \p avail_datalen. Otherwise it
 * returns an error.
 *
 * @param [in] avail_datalen Length of the raw X.509 certificate buffer that
 *			     is free (the input value must be equal to the
 * 			     \p data buffer size, the output refers to how
 *			     many bytes are unused)
 * @param [in] requested_len Length of the buffer that is supposed to be added
 *			     to the certificate buffer.
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_sufficient_size(size_t *avail_datalen, size_t requested_len);

/**
 * @ingroup X509Gen
 * @brief Encode an X.509 certificate
 *
 * The function generates an X.509 data blob from the filled X.509 data
 * structure.
 *
 * This function also performs the signature generation to sign the X.509
 * data with the provided signer.
 *
 * @param [in] x509 The data structure that is filled by the caller before this
 *		    invocation using the various setter functions.
 * @param [in,out] data Raw X.509 data blob in DER / BER format - the caller
 *			must provide the memory
 * @param [in,out] avail_datalen Length of the raw X.509 certificate buffer that
 *				 is free (the input value must be equal to the
 * 				 \p data buffer size, the output refers to how
 *				 many bytes are unused)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_encode(const struct lc_x509_certificate *x509, uint8_t *data,
			size_t *avail_datalen);

/**
 * @ingroup X509Gen
 * @brief Encode a private key DER structure
 *
 * The function generates a DER data blob from the private keys.
 *
 * \note Only a raw DER data blob is generated from this encoding operation.
 * Typically, however, you want a PKCS#8 message to encode the secret key.
 * For that, please consider \p lc_pkcs8_encode.
 *
 * @param [in] gendata The data structure holding the private keys
 * @param [in,out] data Raw X.509 data blob in DER / BER format - the caller
 *			must provide the memory
 * @param [in,out] avail_datalen Length of the raw DER structure buffer that
 *				 is free (the input value must be equal to the
 * 				 \p data buffer size, the output refers to how
 *				 many bytes are unused)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_sk_encode(const struct lc_x509_key_data *gendata, uint8_t *data,
		      size_t *avail_datalen);

/**
 * @ingroup X509Gen
 * @brief Generate signature over user-supplied data
 *
 * @param [out] sig_data Caller-supplied buffer with signature (it needs to be
 * 			 at least as large as reported by
 * 			 \p lc_x509_get_signature_size_from_sk or
 *			 \p lc_x509_get_signature_size_from_cert)
 * @param [in,out] siglen Length of the \p sig_data buffer, the value will be
 *			  updated such that it reflects the length of the
 *			  signature.
 * @param [in] keys The data structure holding the private keys
 * @param [in] m Message to be signed
 * @param [in] mlen Length of message
 * @param [in] prehash_algo It is permissible that the message is prehashed. If
 *			    so, it is indicated by this parameter which points
 *			    to the used message digest the caller used to
 *			    generate the prehashed message digest. This
 *			    forces the use of the Hash[ML|SLH|Composite]-DSA.
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_signature_gen(uint8_t *sig_data, size_t *siglen,
			  const struct lc_x509_key_data *keys, const uint8_t *m,
			  size_t mlen, const struct lc_hash *prehash_algo);

/**
 * @ingroup X509Gen
 * @brief Generate keypair and set it to the X.509 certificate
 *
 * \note After this call, the X.509 certificate acts as a self-signed
 * certificate. If another signer is to be used, use \p lc_x509_cert_set_signer.
 *
 * @param [out] cert X.509 certificate data structure to be filled
 * @param [out] key Buffer that is filled with the newly generated key data
 *		    where the buffer must have the same lifetime as \p cert.
 *		    This buffer may be allocated with
 *		    \p lc_x509_keypair_data_alloc.
 * @param [in] create_keypair_algo Algorithm to generate the key pair for
 *
 * \note If keys->sk_seed_set is set to 1 by the caller, the function stores
 * the ML-DSA seed key from which the full ML-DSA key pair is derived. When
 * creating a PKCS#8 datablob from the key, only the seed key is then stored.
 *
 * @return 0 on success, < 0 on error
 */
int lc_x509_keypair_gen(struct lc_x509_certificate *cert,
			struct lc_x509_key_data *key,
			enum lc_sig_types create_keypair_algo);

enum lc_x509_keypair_data_alloc_flags {
	/** Allocate memory to hold full key pairs */
	lc_x509_keypair_data_alloc_flags_complete_key_pairs,
	/** Allocate memory to hold only seeds */
	lc_x509_keypair_data_alloc_flags_seeds,
};

/**
 * @ingroup X509Gen
 * @brief Allocate memory for holding keypair
 *
 * @param [out] key Buffer that can be used to hold any asymmetric key pair. It
 *		     has to be released with \p lc_x509_keypair_data_zero_free.
 * @param [in] flags Flags to alter allocation logic
 *
 * @return 0 on success, < 0 on error
 */
int lc_x509_keypair_data_alloc(struct lc_x509_key_data **key,
			       enum lc_x509_keypair_data_alloc_flags flags);

/**
 * @ingroup X509Gen
 * @brief Free memory for holding keypair
 *
 * @param [in] key Buffer that shall be freed.
 */
void lc_x509_keypair_data_zero_free(struct lc_x509_key_data *key);

/**
 * @ingroup X509Gen
 * @brief Load key pair it to the X.509 certificate
 *
 * This call allows secret and / or public keys to be loaded. If only one of
 * the types is loaded, the respective other type is not touched. For example,
 * such freedom is needed when decoding an X.509 certificate and wanting to
 * add the associated private key.
 *
 * \note If this call is used to load a full key pair, the X.509 certificate
 * acts as a self-signed certificate. If another signer is to be used,
 * use \p lc_x509_cert_set_signer.
 *
 * @param [out] cert X.509 certificate data structure to be filled
 * @param [in] key Buffer that holds the loaded key data where the buffer must
 *		    have the same lifetime as \p cert
 *
 * @return 0 on success, < 0 on error
 */
int lc_x509_keypair_load(struct lc_x509_certificate *cert,
			 const struct lc_x509_key_data *key);

/**
 * @ingroup X509Gen
 * @brief Return raw public key from key data
 *
 * @param [in] key Buffer that holds the loaded key data
 * @param [out] dst_data Caller-provided buffer to copy public key into. If NULL
 *			 then the required data length is set in
 *			 \p avail_datalen.
 * @param [in,out] avail_datalen Length of the available data to store the
 *				 key into. At the end, the value is reduced
 *				 by the size of the key to return the remaining
 *				 available buffer size.
 *
 * @return 0 on success, < 0 on error
 */
int lc_x509_keypair_pk(const struct lc_x509_key_data *key, uint8_t *dst_data,
		       size_t *avail_datalen);

/**
 * @ingroup X509Gen
 * @brief Set the signer X.509 certificate for a X.509 certificate
 *
 * \note This call also sets the issuer name components in the \p signed_x509
 * from the \p signer_x509. Thus, when invoking this call, ensure that
 * all name components in \p signer_x509 are properly set. If this cannot be
 * guaranteed, the issuer information needs to be set with a sequence of
 * \p lc_x509_cert_get_subject_*(signer_x509) and
 * \p lc_x509_cert_set_issuer_*(signed_x509).
 *
 * @param [out] signed_x509 Signed X.509 certificate data structure to be filled
 * @param [in] signer_key_data Buffer that holds the loaded key data
 *				where the buffer must have the same
 *				lifetime as \p signer_x509
 * @param [in] signer_x509 Signer X.509 certificate data that shall sign the
 *			   \p signed_x509
 *
 * @return 0 on success, < 0 on error
 */
int lc_x509_cert_set_signer(struct lc_x509_certificate *signed_x509,
			    const struct lc_x509_key_data *signer_key_data,
			    const struct lc_x509_certificate *signer_x509);

/**
 * @ingroup X509Gen
 * @brief Set the extended key usage from human readable form
 *
 * The service function can be called repeadetly to set all intended EKU
 * flags.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] name Human readable string (any wrong string will create the
 *		    list of allowed strings on stdout)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_eku(struct lc_x509_certificate *cert, const char *name);

/**
 * @ingroup X509Gen
 * @brief Set the extended key usage in integer form
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] val EKU value holding the LC_KEY_EKU_* flags
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_eku_val(struct lc_x509_certificate *cert, uint16_t val);

/**
 * @ingroup X509Gen
 * @brief Set the key usage from human readable form
 *
 * The service function can be called repeadetly to set all intended key usage
 * flags.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] name Human readable string (any wrong string will craete the
 *		    list of allowed strings on stdout)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_keyusage(struct lc_x509_certificate *cert,
			      const char *name);

/**
 * @ingroup X509Gen
 * @brief Set the key usage in integer form
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [out] val key usage value holding the LC_KEY_USAGE_* flags
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_keyusage_val(struct lc_x509_certificate *cert,
				  uint16_t val);

/**
 * @ingroup X509Gen
 * @brief Mark the certificate to bear the basicConstraint CA
 *
 * \note This call also sets the issuer name components in the \p cert based
 * on the subject data. Thus, when invoking this call, ensure that
 * all name components in \p cert are properly set. If this cannot be
 * guaranteed, the issuer information needs to be set with a sequence of
 * \p lc_x509_cert_set_issuer_*(cert).
 *
 * @param [in] cert Certificate data structure to be filled with the data
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_ca(struct lc_x509_certificate *cert);

/**
 * @ingroup X509Gen
 * @brief Set the path length for the CA certificate
 *
 * \note This length is only applied if the basicConstraint CA is set with
 * \p lc_x509_cert_set_ca. Otherwise the result of the call is ignored
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] ca_pathlen Path length
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_ca_pathlen(struct lc_x509_certificate *cert,
				unsigned int ca_pathlen);

/**
 * @ingroup X509Gen
 * @brief Check and set issuer to subject for CA
 *
 * For a CA, the issuer is intended to be identically to the subject. If
 * the certificate is marked as a CA and the issuer is empty, set the issuer to
 * the subject with this call. This call is considered to be a safety measure
 * invoked right before the certificate is created.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_check_issuer_ca(struct lc_x509_certificate *cert);

/**
 * @ingroup X509Gen
 * @brief Get the Email DNS name
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] san_email_name SAN email name to add to the certificate
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_san_email(struct lc_x509_certificate *cert,
			       const char *san_email_name);

/**
 * @ingroup X509Gen
 * @brief Get the SAN DNS name
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] san_dns_name SAN DNS name to add to the certificate
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_san_dns(struct lc_x509_certificate *cert,
			     const char *san_dns_name);

/**
 * @ingroup X509Gen
 * @brief Get the SAN IP value
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] san_ip Binary representation of IP address
 * @param [in] san_ip_len Length of the IP address buffer
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_san_ip(struct lc_x509_certificate *cert,
			    const uint8_t *san_ip, size_t san_ip_len);

/**
 * @ingroup X509Gen
 * @brief Set the SKID value
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note If no SKID is set by the caller, leancrypto generates the SHA3-256
 * hash of the public key as an SKID.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] skid Binary representation of SKID
 * @param [in] skidlen length of the SKID buffer
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_skid(struct lc_x509_certificate *cert, const uint8_t *skid,
			  size_t skidlen);

/**
 * @ingroup X509Gen
 * @brief Set the AKID value
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note If the certificate to be generated is marked as a CA certificate and
 * no AKID is set, the AKID is set to be identical to the SKID.
 *
 * \note If a signer of a certificate is set, its SKID is used as AKID.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] akid Binary representation of AKID
 * @param [in] akidlen length of the AKID buffer
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_akid(struct lc_x509_certificate *cert, const uint8_t *akid,
			  size_t akidlen);

/**
 * @ingroup X509Gen
 * @brief Set the valid-from data to the certificate
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] time_since_epoch Time in seconds since EPOCH to set
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_valid_from(struct lc_x509_certificate *cert,
				time64_t time_since_epoch);

/**
 * @ingroup X509Gen
 * @brief Set the valid-to data to the certificate
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] time_since_epoch Time in seconds since EPOCH to set
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_valid_to(struct lc_x509_certificate *cert,
			      time64_t time_since_epoch);

/**
 * @ingroup X509Gen
 * @brief Set the subject CN field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_cn(struct lc_x509_certificate *cert,
				const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the subject email field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_email(struct lc_x509_certificate *cert,
				   const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the subject OU field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_ou(struct lc_x509_certificate *cert,
				const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the subject O field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_o(struct lc_x509_certificate *cert,
			       const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the subject ST field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_st(struct lc_x509_certificate *cert,
				const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the subject C field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_subject_c(struct lc_x509_certificate *cert,
			       const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer CN field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_cn(struct lc_x509_certificate *cert,
			       const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer email field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_email(struct lc_x509_certificate *cert,
				  const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer OU field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_ou(struct lc_x509_certificate *cert,
			       const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer O field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_o(struct lc_x509_certificate *cert,
			      const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer ST field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_st(struct lc_x509_certificate *cert,
			       const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the issuer C field tp the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * \note The returned pointer may *not* be NULL-terminated which implies that
 * this function returns also the size of the string. Yet, it is a human
 * readable string.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] string Data field to set
 * @param [in] len Length of the data field
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_issuer_c(struct lc_x509_certificate *cert,
			      const char *string, size_t len);

/**
 * @ingroup X509Gen
 * @brief Set the serial number of the certificate
 *
 * \note The caller must keep the input data available for the lifetime of
 * \p cert.
 *
 * @param [in] cert Certificate data structure to be filled with the data
 * @param [in] serial Binary representation of serial number
 * @param [in] serial_len Length of the serial number
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_cert_set_serial(struct lc_x509_certificate *cert,
			    const uint8_t *serial, size_t serial_len);

/**
 * @ingroup X509Gen
 * @brief Helper to convert the human readable name of a public key algorithm to
 *	  its internal representation
 *
 * If there is no match, the function prints out the allowed strings.
 *
 * @param [in] name public key algorithm in human readable form
 * @param [out] pkey_algo leancrypto algorithm reference
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_pkey_name_to_algorithm(const char *name,
				   enum lc_sig_types *pkey_algo);

/**
 * @ingroup X509Gen
 * @brief Helper to convert the human readable name of a hash algorithm to
 *	  its internal representation
 *
 * If there is no match, the function prints out the allowed strings.
 *
 * @param [in] hash_name hash algorithm in human readable form
 * @param [out] hash_algo leancrypto algorithm reference
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_name_to_hash(const char *hash_name,
			 const struct lc_hash **hash_algo);

/**
 * @ingroup X509Gen
 * @brief Helper to convert the internal representation of a hash algorithm to
 *	  its human readable form
 *
 * @param [in] hash_algo leancrypto algorithm reference
 * @param [out] hash_name hash algorithm in human readable form
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_hash_to_name(const struct lc_hash *hash_algo,
			 const char **hash_name);
/**
 * @ingroup X509Gen
 * @brief Helper to convert the human readable name of a keyusage to
 *	  its internal representation
 *
 * If there is no match, the function prints out the allowed strings.
 *
 * @param [in] name hash algorithm in human readable form
 * @param [out] keyusage leancrypto keyusage (note, the function ORs the value
 *			 into \p keyusage)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_name_to_keyusage(const char *name, uint16_t *keyusage);

/**
 * @ingroup X509Gen
 * @brief Helper to convert the human readable name of a EKU to
 *	  its internal representation
 *
 * If there is no match, the function prints out the allowed strings.
 *
 * @param [in] name hash algorithm in human readable form
 * @param [out] eku leancrypto eku (note, the function ORs the value
 *			 into \p eku)
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_name_to_eku(const char *name, uint16_t *eku);

/**
 * @ingroup X509Gen
 * @brief Helper to convert the a hash reference to an OID
 *
 * @param [in] hash_algo hash algorithm reference
 * @param [out] oid OID reference
 *
 * @return 0 on success or < 0 on error
 */
int lc_x509_hash_to_oid(const struct lc_hash *hash_algo, enum OID *oid);

#ifdef __cplusplus
}
#endif

#endif /* LC_X509_GENERATOR_H */
