2012-02-13 23:11:30 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ file x509_crt . h
2012-02-13 23:11:30 +00:00
*
2013-09-16 11:49:26 +00:00
* \ brief X .509 certificate parsing and writing
2012-02-13 23:11:30 +00:00
*
2013-06-27 12:29:21 +00:00
* Copyright ( C ) 2006 - 2013 , Brainspark B . V .
2012-02-13 23:11:30 +00:00
*
* This file is part of PolarSSL ( http : //www.polarssl.org)
* Lead Maintainer : Paul Bakker < polarssl_maintainer at polarssl . org >
*
* All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2013-09-16 11:49:26 +00:00
# ifndef POLARSSL_X509_CRT_H
# define POLARSSL_X509_CRT_H
2012-02-13 23:11:30 +00:00
2013-04-19 12:51:29 +00:00
# include "config.h"
2013-08-25 12:47:27 +00:00
# include "x509.h"
2012-02-13 23:11:30 +00:00
2013-09-16 11:49:26 +00:00
# include "x509_crl.h"
2013-08-25 09:47:51 +00:00
/**
* \ addtogroup x509_module
* \ {
*/
2013-06-27 12:29:21 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ name Structures and functions for parsing and writing X .509 certificates
2013-08-25 09:47:51 +00:00
* \ {
*/
/**
2013-09-16 11:49:26 +00:00
* Container for an X .509 certificate . The certificate may be chained .
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
typedef struct _x509_crt
2012-02-13 23:11:30 +00:00
{
2013-09-16 11:49:26 +00:00
x509_buf raw ; /**< The raw certificate data (DER). */
x509_buf tbs ; /**< The raw certificate body (DER). The part that is To Be Signed. */
int version ; /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
x509_buf serial ; /**< Unique id for certificate issued by a specific CA. */
x509_buf sig_oid1 ; /**< Signature algorithm, e.g. sha1RSA */
x509_buf issuer_raw ; /**< The raw issuer data (DER). Used for quick comparison. */
x509_buf subject_raw ; /**< The raw subject data (DER). Used for quick comparison. */
x509_name issuer ; /**< The parsed issuer data (named information object). */
x509_name subject ; /**< The parsed subject data (named information object). */
x509_time valid_from ; /**< Start time of certificate validity. */
x509_time valid_to ; /**< End time of certificate validity. */
pk_context pk ; /**< Container for the public key context. */
x509_buf issuer_id ; /**< Optional X.509 v2/v3 issuer unique identifier. */
x509_buf subject_id ; /**< Optional X.509 v2/v3 subject unique identifier. */
x509_buf v3_ext ; /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
x509_sequence subject_alt_names ; /**< Optional list of Subject Alternative Names (Only dNSName supported). */
int ext_types ; /**< Bit string containing detected and parsed extensions */
int ca_istrue ; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
int max_pathlen ; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
unsigned char key_usage ; /**< Optional key usage extension value: See the values below */
x509_sequence ext_key_usage ; /**< Optional list of extended key usage OIDs. */
unsigned char ns_cert_type ; /**< Optional Netscape certificate type extension value: See the values below */
x509_buf sig_oid2 ; /**< Signature algorithm. Must match sig_oid1. */
x509_buf sig ; /**< Signature: hash of the tbs part signed with the private key. */
md_type_t sig_md ; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ ;
2013-09-18 12:13:26 +00:00
struct _x509_crt * next ; /**< Next certificate in the CA-chain. */
2012-02-13 23:11:30 +00:00
}
2013-09-18 12:13:26 +00:00
x509_crt ;
2013-08-25 08:18:25 +00:00
2013-09-06 07:55:26 +00:00
# define X509_CRT_VERSION_1 0
# define X509_CRT_VERSION_2 1
# define X509_CRT_VERSION_3 2
# define X509_RFC5280_MAX_SERIAL_LEN 32
# define X509_RFC5280_UTC_TIME_LEN 15
2012-02-13 23:11:30 +00:00
2013-08-25 09:47:51 +00:00
/**
2013-09-06 07:55:26 +00:00
* Container for writing a certificate ( CRT )
2013-08-25 09:47:51 +00:00
*/
2013-09-06 07:55:26 +00:00
typedef struct _x509write_cert
2013-08-25 08:18:25 +00:00
{
2013-09-06 07:55:26 +00:00
int version ;
mpi serial ;
2013-09-12 03:39:46 +00:00
pk_context * subject_key ;
pk_context * issuer_key ;
2013-09-09 10:02:36 +00:00
asn1_named_data * subject ;
asn1_named_data * issuer ;
2013-08-25 08:18:25 +00:00
md_type_t md_alg ;
2013-09-06 07:55:26 +00:00
char not_before [ X509_RFC5280_UTC_TIME_LEN + 1 ] ;
char not_after [ X509_RFC5280_UTC_TIME_LEN + 1 ] ;
2013-08-26 10:05:14 +00:00
asn1_named_data * extensions ;
2013-08-25 08:18:25 +00:00
}
2013-09-06 07:55:26 +00:00
x509write_cert ;
2013-08-25 08:18:25 +00:00
2013-09-16 11:49:26 +00:00
# if defined(POLARSSL_X509_CRT_PARSE_C)
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Parse a single DER formatted certificate and add it
* to the chained list .
*
* \ param chain points to the start of the chain
* \ param buf buffer holding the certificate DER data
* \ param buflen size of the buffer
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ return 0 if successful , or a specific X509 or PEM error code
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
int x509_crt_parse_der ( x509_crt * chain , const unsigned char * buf ,
2013-09-18 11:46:23 +00:00
size_t buflen ) ;
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Parse one or more certificates and add them
* to the chained list . Parses permissively . If some
* certificates can be parsed , the result is the number
* of failed certificates it encountered . If none complete
* correctly , the first error is returned .
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ param chain points to the start of the chain
* \ param buf buffer holding the certificate data
* \ param buflen size of the buffer
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ return 0 if all certificates parsed successfully , a positive number
* if partly successful or a specific X509 or PEM error code
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
int x509_crt_parse ( x509_crt * chain , const unsigned char * buf , size_t buflen ) ;
2013-08-25 09:47:51 +00:00
2013-09-16 11:49:26 +00:00
# if defined(POLARSSL_FS_IO)
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Load one or more certificates and add them
* to the chained list . Parses permissively . If some
* certificates can be parsed , the result is the number
* of failed certificates it encountered . If none complete
* correctly , the first error is returned .
*
* \ param chain points to the start of the chain
* \ param path filename to read the certificates from
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ return 0 if all certificates parsed successfully , a positive number
* if partly successful or a specific X509 or PEM error code
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
int x509_crt_parse_file ( x509_crt * chain , const char * path ) ;
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Load one or more certificate files from a path and add them
* to the chained list . Parses permissively . If some
* certificates can be parsed , the result is the number
* of failed certificates it encountered . If none complete
* correctly , the first error is returned .
*
2013-11-28 16:16:41 +00:00
* \ warning This function is NOT thread - safe unless
* POLARSSL_THREADING_PTHREADS is defined . If you ' re using an
* alternative threading implementation , you should either use
* this function only in the main thread , or mutex it .
*
2013-09-16 11:49:26 +00:00
* \ param chain points to the start of the chain
* \ param path directory / folder to read the certificate files from
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ return 0 if all certificates parsed successfully , a positive number
* if partly successful or a specific X509 or PEM error code
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
int x509_crt_parse_path ( x509_crt * chain , const char * path ) ;
2013-09-16 11:49:26 +00:00
# endif /* POLARSSL_FS_IO */
2013-08-25 09:47:51 +00:00
2013-08-25 12:47:27 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Returns an informational string about the
* certificate .
2013-08-25 12:47:27 +00:00
*
2013-09-16 11:49:26 +00:00
* \ param buf Buffer to write to
* \ param size Maximum size of buffer
* \ param prefix A line prefix
* \ param crt The X509 certificate to represent
2013-08-26 10:05:14 +00:00
*
2013-09-16 11:49:26 +00:00
* \ return The amount of data written to the buffer , or - 1 in
* case of an error .
2013-08-25 12:47:27 +00:00
*/
2013-09-18 11:46:23 +00:00
int x509_crt_info ( char * buf , size_t size , const char * prefix ,
2013-09-18 12:13:26 +00:00
const x509_crt * crt ) ;
2013-08-25 12:47:27 +00:00
2013-08-26 11:41:01 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Verify the certificate signature
2013-08-26 11:41:01 +00:00
*
2013-09-16 11:49:26 +00:00
* The verify callback is a user - supplied callback that
* can clear / modify / add flags for a certificate . If set ,
* the verification callback is called for each
* certificate in the chain ( from the trust - ca down to the
* presented crt ) . The parameters for the callback are :
2013-09-18 12:13:26 +00:00
* ( void * parameter , x509_crt * crt , int certificate_depth ,
2013-09-16 11:49:26 +00:00
* int * flags ) . With the flags representing current flags for
* that specific certificate and the certificate depth from
* the bottom ( Peer cert depth = 0 ) .
2013-08-26 11:41:01 +00:00
*
2013-09-16 11:49:26 +00:00
* All flags left after returning from the callback
* are also returned to the application . The function should
* return 0 for anything but a fatal error .
*
* \ param crt a certificate to be verified
* \ param trust_ca the trusted CA chain
* \ param ca_crl the CRL chain for trusted CA ' s
* \ param cn expected Common Name ( can be set to
* NULL if the CN must not be verified )
* \ param flags result of the verification
* \ param f_vrfy verification function
* \ param p_vrfy verification parameter
*
* \ return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED ,
* in which case * flags will have one or more of
* the following values set :
* BADCERT_EXPIRED - -
* BADCERT_REVOKED - -
* BADCERT_CN_MISMATCH - -
* BADCERT_NOT_TRUSTED
* or another error in case of a fatal error encountered
* during the verification process .
2013-08-26 11:41:01 +00:00
*/
2013-09-18 12:13:26 +00:00
int x509_crt_verify ( x509_crt * crt ,
x509_crt * trust_ca ,
2013-09-18 11:46:23 +00:00
x509_crl * ca_crl ,
const char * cn , int * flags ,
2013-09-18 12:13:26 +00:00
int ( * f_vrfy ) ( void * , x509_crt * , int , int * ) ,
2013-09-18 11:46:23 +00:00
void * p_vrfy ) ;
2013-08-26 11:41:01 +00:00
2013-09-23 10:20:02 +00:00
# if defined(POLARSSL_X509_CRL_PARSE_C)
2013-08-26 11:41:01 +00:00
/**
2013-09-23 10:20:02 +00:00
* \ brief Verify the certificate revocation status
2013-08-26 11:41:01 +00:00
*
2013-09-16 11:49:26 +00:00
* \ param crt a certificate to be verified
* \ param crl the CRL to verify against
*
* \ return 1 if the certificate is revoked , 0 otherwise
2013-08-26 11:41:01 +00:00
*
*/
2013-09-18 12:13:26 +00:00
int x509_crt_revoked ( const x509_crt * crt , const x509_crl * crl ) ;
2013-09-16 11:49:26 +00:00
# endif /* POLARSSL_X509_CRL_PARSE_C */
2013-08-26 11:41:01 +00:00
2013-09-18 09:58:25 +00:00
/**
* \ brief Initialize a certificate ( chain )
*
* \ param crt Certificate chain to initialize
*/
2013-09-18 12:13:26 +00:00
void x509_crt_init ( x509_crt * crt ) ;
2013-09-18 09:58:25 +00:00
2013-08-25 09:47:51 +00:00
/**
2013-09-16 11:49:26 +00:00
* \ brief Unallocate all certificate data
2013-08-25 09:47:51 +00:00
*
2013-09-16 11:49:26 +00:00
* \ param crt Certificate chain to free
2013-08-25 09:47:51 +00:00
*/
2013-09-18 12:13:26 +00:00
void x509_crt_free ( x509_crt * crt ) ;
2013-09-16 11:49:26 +00:00
# endif /* POLARSSL_X509_CRT_PARSE_C */
/* \} name */
/* \} addtogroup x509_module */
2013-08-25 08:18:25 +00:00
2013-09-16 11:49:26 +00:00
# if defined(POLARSSL_X509_CRT_WRITE_C)
2013-09-06 07:55:26 +00:00
/**
* \ brief Initialize a CRT writing context
*
* \ param ctx CRT context to initialize
*/
void x509write_crt_init ( x509write_cert * ctx ) ;
/**
* \ brief Set the verion for a Certificate
* Default : X509_CRT_VERSION_3
*
* \ param ctx CRT context to use
* \ param version version to set ( X509_CRT_VERSION_1 , X509_CRT_VERSION_2 or
* X509_CRT_VERSION_3 )
*/
void x509write_crt_set_version ( x509write_cert * ctx , int version ) ;
/**
* \ brief Set the serial number for a Certificate .
*
* \ param ctx CRT context to use
* \ param serial serial number to set
*
* \ return 0 if successful
*/
int x509write_crt_set_serial ( x509write_cert * ctx , const mpi * serial ) ;
/**
* \ brief Set the validity period for a Certificate
* Timestamps should be in string format for UTC timezone
* i . e . " YYYYMMDDhhmmss "
* e . g . " 20131231235959 " for December 31 st 2013
* at 23 : 59 : 59
*
* \ param ctx CRT context to use
* \ param not_before not_before timestamp
* \ param not_after not_after timestamp
*
* \ return 0 if timestamp was parsed successfully , or
* a specific error code
*/
2013-10-28 20:19:10 +00:00
int x509write_crt_set_validity ( x509write_cert * ctx , const char * not_before ,
const char * not_after ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Set the issuer name for a Certificate
* Issuer names should contain a comma - separated list
* of OID types and values :
* e . g . " C=NL,O=Offspark,CN=PolarSSL CA "
*
* \ param ctx CRT context to use
* \ param issuer_name issuer name to set
*
* \ return 0 if issuer name was parsed successfully , or
* a specific error code
*/
2013-10-28 20:19:10 +00:00
int x509write_crt_set_issuer_name ( x509write_cert * ctx ,
const char * issuer_name ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Set the subject name for a Certificate
* Subject names should contain a comma - separated list
* of OID types and values :
* e . g . " C=NL,O=Offspark,CN=PolarSSL Server 1 "
*
* \ param ctx CRT context to use
* \ param subject_name subject name to set
*
* \ return 0 if subject name was parsed successfully , or
* a specific error code
*/
2013-10-28 20:19:10 +00:00
int x509write_crt_set_subject_name ( x509write_cert * ctx ,
const char * subject_name ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Set the subject public key for the certificate
*
* \ param ctx CRT context to use
2013-09-12 03:21:54 +00:00
* \ param key public key to include
2013-09-06 07:55:26 +00:00
*/
2013-09-12 03:21:54 +00:00
void x509write_crt_set_subject_key ( x509write_cert * ctx , pk_context * key ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Set the issuer key used for signing the certificate
*
* \ param ctx CRT context to use
2013-09-12 03:21:54 +00:00
* \ param key private key to sign with
2013-09-06 07:55:26 +00:00
*/
2013-09-12 03:21:54 +00:00
void x509write_crt_set_issuer_key ( x509write_cert * ctx , pk_context * key ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Set the MD algorithm to use for the signature
* ( e . g . POLARSSL_MD_SHA1 )
*
* \ param ctx CRT context to use
2013-12-30 16:57:27 +00:00
* \ param md_alg MD algorithm to use
2013-09-06 07:55:26 +00:00
*/
void x509write_crt_set_md_alg ( x509write_cert * ctx , md_type_t md_alg ) ;
2013-09-06 17:27:21 +00:00
/**
* \ brief Generic function to add to or replace an extension in the
* CRT
*
* \ param ctx CRT context to use
* \ param oid OID of the extension
* \ param oid_len length of the OID
* \ param critical if the extension is critical ( per the RFC ' s definition )
* \ param val value of the extension OCTET STRING
* \ param val_len length of the value data
*
* \ return 0 if successful , or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_extension ( x509write_cert * ctx ,
const char * oid , size_t oid_len ,
int critical ,
const unsigned char * val , size_t val_len ) ;
/**
* \ brief Set the basicConstraints extension for a CRT
*
* \ param ctx CRT context to use
* \ param is_ca is this a CA certificate
* \ param max_pathlen maximum length of certificate chains below this
* certificate ( only for CA certificates , - 1 is
* inlimited )
*
* \ return 0 if successful , or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_basic_constraints ( x509write_cert * ctx ,
int is_ca , int max_pathlen ) ;
2013-10-27 13:22:02 +00:00
# if defined(POLARSSL_SHA1_C)
2013-09-06 17:27:21 +00:00
/**
* \ brief Set the subjectKeyIdentifier extension for a CRT
* Requires that x509write_crt_set_subject_key ( ) has been
* called before
*
* \ param ctx CRT context to use
*
* \ return 0 if successful , or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_subject_key_identifier ( x509write_cert * ctx ) ;
/**
* \ brief Set the authorityKeyIdentifier extension for a CRT
* Requires that x509write_crt_set_issuer_key ( ) has been
* called before
*
* \ param ctx CRT context to use
*
* \ return 0 if successful , or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_authority_key_identifier ( x509write_cert * ctx ) ;
2013-10-27 13:22:02 +00:00
# endif /* POLARSSL_SHA1_C */
2013-08-25 08:18:25 +00:00
2013-08-25 09:47:51 +00:00
/**
2013-09-09 10:37:54 +00:00
* \ brief Set the Key Usage Extension flags
* ( e . g . KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN )
*
* \ param ctx CRT context to use
* \ param key_usage key usage flags to set
*
* \ return 0 if successful , or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_key_usage ( x509write_cert * ctx , unsigned char key_usage ) ;
/**
* \ brief Set the Netscape Cert Type flags
* ( e . g . NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL )
*
* \ param ctx CRT context to use
* \ param ns_cert_type Netscape Cert Type flags to set
*
* \ return 0 if successful , or POLARSSL_ERR_X509WRITE_MALLOC_FAILED
*/
int x509write_crt_set_ns_cert_type ( x509write_cert * ctx ,
unsigned char ns_cert_type ) ;
2013-09-06 07:55:26 +00:00
/**
* \ brief Free the contents of a CRT write context
*
* \ param ctx CRT context to free
*/
void x509write_crt_free ( x509write_cert * ctx ) ;
/**
* \ brief Write a built up certificate to a X509 DER structure
2013-08-25 09:47:51 +00:00
* Note : data is written at the end of the buffer ! Use the
* return value to determine where you should start
* using the buffer
*
2013-12-30 16:57:27 +00:00
* \ param ctx certificate to write away
2013-08-25 09:47:51 +00:00
* \ param buf buffer to write to
* \ param size size of the buffer
2013-09-12 03:59:05 +00:00
* \ param f_rng RNG function ( for signature , see note )
* \ param p_rng RNG parameter
2013-08-25 09:47:51 +00:00
*
* \ return length of data written if successful , or a specific
* error code
2013-09-12 03:59:05 +00:00
*
* \ note f_rng may be NULL if RSA is used for signature and the
* signature is made offline ( otherwise f_rng is desirable
* for countermeasures against timing attacks ) .
* ECDSA signatures always require a non - NULL f_rng .
2013-08-25 09:47:51 +00:00
*/
2013-09-12 03:59:05 +00:00
int x509write_crt_der ( x509write_cert * ctx , unsigned char * buf , size_t size ,
int ( * f_rng ) ( void * , unsigned char * , size_t ) ,
void * p_rng ) ;
2013-08-25 09:47:51 +00:00
2013-09-15 18:43:33 +00:00
# if defined(POLARSSL_PEM_WRITE_C)
2013-08-26 15:22:23 +00:00
/**
2013-09-06 07:55:26 +00:00
* \ brief Write a built up certificate to a X509 PEM string
*
2013-12-30 16:57:27 +00:00
* \ param ctx certificate to write away
2013-09-06 07:55:26 +00:00
* \ param buf buffer to write to
* \ param size size of the buffer
2013-09-12 03:59:05 +00:00
* \ param f_rng RNG function ( for signature , see note )
* \ param p_rng RNG parameter
2013-09-06 07:55:26 +00:00
*
* \ return 0 successful , or a specific error code
2013-09-12 03:59:05 +00:00
*
* \ note f_rng may be NULL if RSA is used for signature and the
* signature is made offline ( otherwise f_rng is desirable
* for countermeasures against timing attacks ) .
* ECDSA signatures always require a non - NULL f_rng .
2013-09-06 07:55:26 +00:00
*/
2013-09-12 03:59:05 +00:00
int x509write_crt_pem ( x509write_cert * ctx , unsigned char * buf , size_t size ,
int ( * f_rng ) ( void * , unsigned char * , size_t ) ,
void * p_rng ) ;
2013-09-15 18:43:33 +00:00
# endif /* POLARSSL_PEM_WRITE_C */
2013-09-16 11:49:26 +00:00
# endif /* POLARSSL_X509_CRT_WRITE_C */
2013-08-26 14:54:13 +00:00
2013-06-27 12:29:21 +00:00
# ifdef __cplusplus
}
# endif
2013-09-16 11:49:26 +00:00
# endif /* x509_crt.h */