Split up X509 files into smaller modules
This commit is contained in:
parent
ace02867f6
commit
7c6b2c320e
31 changed files with 3838 additions and 3212 deletions
|
@ -49,13 +49,18 @@ set(src
|
|||
sha512.c
|
||||
ssl_cache.c
|
||||
ssl_ciphersuites.c
|
||||
ssl_cli.c
|
||||
ssl_srv.c
|
||||
ssl_cli.c
|
||||
ssl_srv.c
|
||||
ssl_tls.c
|
||||
timing.c
|
||||
version.c
|
||||
x509parse.c
|
||||
x509write.c
|
||||
x509.c
|
||||
x509_crt.c
|
||||
x509_crl.c
|
||||
x509_csr.c
|
||||
x509_create.c
|
||||
x509_crt_write.c
|
||||
x509_csr_write.c
|
||||
xtea.c
|
||||
)
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ void debug_print_mpi( const ssl_context *ssl, int level,
|
|||
}
|
||||
#endif /* POLARSSL_BIGNUM_C */
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
static void debug_print_pk( const ssl_context *ssl, int level,
|
||||
const char *file, int line,
|
||||
const char *text, const pk_context *pk )
|
||||
|
@ -288,6 +288,6 @@ void debug_print_crt( const ssl_context *ssl, int level,
|
|||
crt = crt->next;
|
||||
}
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "polarssl/oid.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C)
|
||||
#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
|
||||
#include "polarssl/x509.h"
|
||||
#endif
|
||||
|
||||
|
@ -207,7 +207,7 @@ static const oid_x520_attr_t oid_x520_attr_type[] =
|
|||
FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type);
|
||||
FN_OID_GET_ATTR1(oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name);
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C)
|
||||
#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
|
||||
/*
|
||||
* For X509 extensions
|
||||
*/
|
||||
|
@ -260,7 +260,7 @@ static const oid_descriptor_t oid_ext_key_usage[] =
|
|||
|
||||
FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage);
|
||||
FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description);
|
||||
#endif /* POLARSSL_X509_PARSE_C || POLARSSL_X509_WRITE_C */
|
||||
#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
|
||||
|
||||
#if defined(POLARSSL_MD_C)
|
||||
/*
|
||||
|
|
|
@ -85,7 +85,7 @@ int ssl_cache_get( void *data, ssl_session *session )
|
|||
|
||||
session->verify_result = entry->session.verify_result;
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
/*
|
||||
* Restore peer certificate (without rest of the original chain)
|
||||
*/
|
||||
|
@ -104,7 +104,7 @@ int ssl_cache_get( void *data, ssl_session *session )
|
|||
return( 1 );
|
||||
}
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -163,13 +163,13 @@ int ssl_cache_set( void *data, const ssl_session *session )
|
|||
{
|
||||
cur = old;
|
||||
memset( &cur->session, 0, sizeof(ssl_session) );
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( cur->peer_cert.p != NULL )
|
||||
{
|
||||
polarssl_free( cur->peer_cert.p );
|
||||
memset( &cur->peer_cert, 0, sizeof(x509_buf) );
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
}
|
||||
#else /* POLARSSL_HAVE_TIME */
|
||||
/*
|
||||
|
@ -184,13 +184,13 @@ int ssl_cache_set( void *data, const ssl_session *session )
|
|||
cur = cache->chain;
|
||||
cache->chain = cur->next;
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( cur->peer_cert.p != NULL )
|
||||
{
|
||||
polarssl_free( cur->peer_cert.p );
|
||||
memset( &cur->peer_cert, 0, sizeof(x509_buf) );
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
memset( cur, 0, sizeof(ssl_cache_entry) );
|
||||
prv->next = cur;
|
||||
|
@ -217,7 +217,7 @@ int ssl_cache_set( void *data, const ssl_session *session )
|
|||
|
||||
memcpy( &cur->session, session, sizeof( ssl_session ) );
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
/*
|
||||
* Store peer certificate
|
||||
*/
|
||||
|
@ -233,7 +233,7 @@ int ssl_cache_set( void *data, const ssl_session *session )
|
|||
|
||||
cur->session.peer_cert = NULL;
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -267,10 +267,10 @@ void ssl_cache_free( ssl_cache_context *cache )
|
|||
|
||||
ssl_session_free( &prv->session );
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( prv->peer_cert.p != NULL )
|
||||
polarssl_free( prv->peer_cert.p );
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
polarssl_free( prv );
|
||||
}
|
||||
|
|
|
@ -62,9 +62,9 @@ static int ssl_save_session( const ssl_session *session,
|
|||
{
|
||||
unsigned char *p = buf;
|
||||
size_t left = buf_len;
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
size_t cert_len;
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
if( left < sizeof( ssl_session ) )
|
||||
return( -1 );
|
||||
|
@ -73,7 +73,7 @@ static int ssl_save_session( const ssl_session *session,
|
|||
p += sizeof( ssl_session );
|
||||
left -= sizeof( ssl_session );
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
((ssl_session *) buf)->peer_cert = NULL;
|
||||
|
||||
if( session->peer_cert == NULL )
|
||||
|
@ -92,7 +92,7 @@ static int ssl_save_session( const ssl_session *session,
|
|||
memcpy( p, session->peer_cert->raw.p, cert_len );
|
||||
|
||||
p += cert_len;
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
*olen = p - buf;
|
||||
|
||||
|
@ -107,9 +107,9 @@ static int ssl_load_session( ssl_session *session,
|
|||
{
|
||||
const unsigned char *p = buf;
|
||||
const unsigned char * const end = buf + len;
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
size_t cert_len;
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
if( p + sizeof( ssl_session ) > end )
|
||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
@ -117,7 +117,7 @@ static int ssl_load_session( ssl_session *session,
|
|||
memcpy( session, p, sizeof( ssl_session ) );
|
||||
p += sizeof( ssl_session );
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( p + 3 > end )
|
||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
|
@ -144,7 +144,7 @@ static int ssl_load_session( ssl_session *session,
|
|||
|
||||
if( ( ret = x509parse_crt( session->peer_cert, p, cert_len ) ) != 0 )
|
||||
{
|
||||
x509_free( session->peer_cert );
|
||||
x509_crt_free( session->peer_cert );
|
||||
polarssl_free( session->peer_cert );
|
||||
session->peer_cert = NULL;
|
||||
return( ret );
|
||||
|
@ -152,7 +152,7 @@ static int ssl_load_session( ssl_session *session,
|
|||
|
||||
p += cert_len;
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
if( p != end )
|
||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
|
|
@ -75,7 +75,7 @@ static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
|
|||
ssl_session_free( dst );
|
||||
memcpy( dst, src, sizeof( ssl_session ) );
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( src->peer_cert != NULL )
|
||||
{
|
||||
int ret;
|
||||
|
@ -93,7 +93,7 @@ static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
|
|||
return( ret );
|
||||
}
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(POLARSSL_SSL_SESSION_TICKETS)
|
||||
if( src->ticket != NULL )
|
||||
|
@ -2482,7 +2482,7 @@ int ssl_parse_certificate( ssl_context *ssl )
|
|||
/* In case we tried to reuse a session but it failed */
|
||||
if( ssl->session_negotiate->peer_cert != NULL )
|
||||
{
|
||||
x509_free( ssl->session_negotiate->peer_cert );
|
||||
x509_crt_free( ssl->session_negotiate->peer_cert );
|
||||
polarssl_free( ssl->session_negotiate->peer_cert );
|
||||
}
|
||||
|
||||
|
@ -3377,7 +3377,7 @@ void ssl_set_authmode( ssl_context *ssl, int authmode )
|
|||
ssl->authmode = authmode;
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
void ssl_set_verify( ssl_context *ssl,
|
||||
int (*f_vrfy)(void *, x509_cert *, int, int *),
|
||||
void *p_vrfy )
|
||||
|
@ -3385,7 +3385,7 @@ void ssl_set_verify( ssl_context *ssl,
|
|||
ssl->f_vrfy = f_vrfy;
|
||||
ssl->p_vrfy = p_vrfy;
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
void ssl_set_rng( ssl_context *ssl,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
|
@ -3463,7 +3463,7 @@ void ssl_set_ciphersuites_for_version( ssl_context *ssl, const int *ciphersuites
|
|||
ssl->ciphersuite_list[minor] = ciphersuites;
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
|
||||
x509_crl *ca_crl, const char *peer_cn )
|
||||
{
|
||||
|
@ -3523,7 +3523,7 @@ int ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
|
|||
return( pk_init_ctx_rsa_alt( ssl->pk_key, rsa_key,
|
||||
rsa_decrypt, rsa_sign, rsa_key_len ) );
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
|
||||
void ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
|
||||
|
@ -3730,7 +3730,7 @@ const char *ssl_get_version( const ssl_context *ssl )
|
|||
return( "unknown" );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
const x509_cert *ssl_get_peer_cert( const ssl_context *ssl )
|
||||
{
|
||||
if( ssl == NULL || ssl->session == NULL )
|
||||
|
@ -3738,7 +3738,7 @@ const x509_cert *ssl_get_peer_cert( const ssl_context *ssl )
|
|||
|
||||
return ssl->session->peer_cert;
|
||||
}
|
||||
#endif /* POLARSSL_X509_PARSE_C */
|
||||
#endif /* POLARSSL_X509_CRT_PARSE_C */
|
||||
|
||||
int ssl_get_session( const ssl_context *ssl, ssl_session *dst )
|
||||
{
|
||||
|
@ -4076,10 +4076,10 @@ void ssl_handshake_free( ssl_handshake_params *handshake )
|
|||
|
||||
void ssl_session_free( ssl_session *session )
|
||||
{
|
||||
#if defined(POLARSSL_X509_PARSE_C)
|
||||
#if defined(POLARSSL_X509_CRT_PARSE_C)
|
||||
if( session->peer_cert != NULL )
|
||||
{
|
||||
x509_free( session->peer_cert );
|
||||
x509_crt_free( session->peer_cert );
|
||||
polarssl_free( session->peer_cert );
|
||||
}
|
||||
#endif
|
||||
|
|
798
library/x509.c
Normal file
798
library/x509.c
Normal file
|
@ -0,0 +1,798 @@
|
|||
/*
|
||||
* X.509 certificate and private key decoding
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* The ITU-T X.509 standard defines a certificate format for PKI.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc3279.txt
|
||||
* http://www.ietf.org/rfc/rfc3280.txt
|
||||
*
|
||||
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
|
||||
*
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_USE_C)
|
||||
|
||||
#include "polarssl/x509.h"
|
||||
#include "polarssl/asn1.h"
|
||||
#include "polarssl/oid.h"
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_MEMORY_C)
|
||||
#include "polarssl/memory.h"
|
||||
#else
|
||||
#define polarssl_malloc malloc
|
||||
#define polarssl_free free
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
#include <stdio.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CertificateSerialNumber ::= INTEGER
|
||||
*/
|
||||
int x509_get_serial( unsigned char **p, const unsigned char *end,
|
||||
x509_buf *serial )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
|
||||
**p != ASN1_INTEGER )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
|
||||
POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
|
||||
|
||||
serial->tag = *(*p)++;
|
||||
|
||||
if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret );
|
||||
|
||||
serial->p = *p;
|
||||
*p += serial->len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Get an algorithm identifier without parameters (eg for signatures)
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
*/
|
||||
int x509_get_alg_null( unsigned char **p, const unsigned char *end,
|
||||
x509_buf *alg )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* AttributeTypeAndValue ::= SEQUENCE {
|
||||
* type AttributeType,
|
||||
* value AttributeValue }
|
||||
*
|
||||
* AttributeType ::= OBJECT IDENTIFIER
|
||||
*
|
||||
* AttributeValue ::= ANY DEFINED BY AttributeType
|
||||
*/
|
||||
static int x509_get_attr_type_value( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
x509_name *cur )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
x509_buf *oid;
|
||||
x509_buf *val;
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
oid = &cur->oid;
|
||||
oid->tag = **p;
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
|
||||
|
||||
oid->p = *p;
|
||||
*p += oid->len;
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
|
||||
**p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
|
||||
**p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
|
||||
POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
|
||||
|
||||
val = &cur->val;
|
||||
val->tag = *(*p)++;
|
||||
|
||||
if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
|
||||
|
||||
val->p = *p;
|
||||
*p += val->len;
|
||||
|
||||
cur->next = NULL;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* RelativeDistinguishedName ::=
|
||||
* SET OF AttributeTypeAndValue
|
||||
*
|
||||
* AttributeTypeAndValue ::= SEQUENCE {
|
||||
* type AttributeType,
|
||||
* value AttributeValue }
|
||||
*
|
||||
* AttributeType ::= OBJECT IDENTIFIER
|
||||
*
|
||||
* AttributeValue ::= ANY DEFINED BY AttributeType
|
||||
*/
|
||||
int x509_get_name( unsigned char **p, const unsigned char *end,
|
||||
x509_name *cur )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
const unsigned char *end2;
|
||||
x509_name *use;
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
|
||||
|
||||
end2 = end;
|
||||
end = *p + len;
|
||||
use = cur;
|
||||
|
||||
do
|
||||
{
|
||||
if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( *p != end )
|
||||
{
|
||||
use->next = (x509_name *) polarssl_malloc(
|
||||
sizeof( x509_name ) );
|
||||
|
||||
if( use->next == NULL )
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
|
||||
memset( use->next, 0, sizeof( x509_name ) );
|
||||
|
||||
use = use->next;
|
||||
}
|
||||
}
|
||||
while( *p != end );
|
||||
|
||||
/*
|
||||
* recurse until end of SEQUENCE is reached
|
||||
*/
|
||||
if( *p == end2 )
|
||||
return( 0 );
|
||||
|
||||
cur->next = (x509_name *) polarssl_malloc(
|
||||
sizeof( x509_name ) );
|
||||
|
||||
if( cur->next == NULL )
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
|
||||
memset( cur->next, 0, sizeof( x509_name ) );
|
||||
|
||||
return( x509_get_name( p, end2, cur->next ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Time ::= CHOICE {
|
||||
* utcTime UTCTime,
|
||||
* generalTime GeneralizedTime }
|
||||
*/
|
||||
int x509_get_time( unsigned char **p, const unsigned char *end,
|
||||
x509_time *time )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
char date[64];
|
||||
unsigned char tag;
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
tag = **p;
|
||||
|
||||
if ( tag == ASN1_UTC_TIME )
|
||||
{
|
||||
(*p)++;
|
||||
ret = asn1_get_len( p, end, &len );
|
||||
|
||||
if( ret != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
|
||||
|
||||
memset( date, 0, sizeof( date ) );
|
||||
memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
|
||||
len : sizeof( date ) - 1 );
|
||||
|
||||
if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
|
||||
&time->year, &time->mon, &time->day,
|
||||
&time->hour, &time->min, &time->sec ) < 5 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
|
||||
|
||||
time->year += 100 * ( time->year < 50 );
|
||||
time->year += 1900;
|
||||
|
||||
*p += len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
else if ( tag == ASN1_GENERALIZED_TIME )
|
||||
{
|
||||
(*p)++;
|
||||
ret = asn1_get_len( p, end, &len );
|
||||
|
||||
if( ret != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
|
||||
|
||||
memset( date, 0, sizeof( date ) );
|
||||
memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
|
||||
len : sizeof( date ) - 1 );
|
||||
|
||||
if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
|
||||
&time->year, &time->mon, &time->day,
|
||||
&time->hour, &time->min, &time->sec ) < 5 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
|
||||
|
||||
*p += len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
|
||||
}
|
||||
|
||||
int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
sig->tag = **p;
|
||||
|
||||
if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
|
||||
|
||||
sig->len = len;
|
||||
sig->p = *p;
|
||||
|
||||
*p += len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
|
||||
pk_type_t *pk_alg )
|
||||
{
|
||||
int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
|
||||
|
||||
if( ret != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG + ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* X.509 Extensions (No parsing of extensions, pointer should
|
||||
* be either manually updated or extensions should be parsed!
|
||||
*/
|
||||
int x509_get_ext( unsigned char **p, const unsigned char *end,
|
||||
x509_buf *ext, int tag )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
if( *p == end )
|
||||
return( 0 );
|
||||
|
||||
ext->tag = **p;
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &ext->len,
|
||||
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ext->p = *p;
|
||||
end = *p + ext->len;
|
||||
|
||||
/*
|
||||
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||
*
|
||||
* Extension ::= SEQUENCE {
|
||||
* extnID OBJECT IDENTIFIER,
|
||||
* critical BOOLEAN DEFAULT FALSE,
|
||||
* extnValue OCTET STRING }
|
||||
*/
|
||||
if( ( ret = asn1_get_tag( p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
|
||||
|
||||
if( end != *p + len )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
/*
|
||||
* Load all data from a file into a given buffer.
|
||||
*/
|
||||
int x509_load_file( const char *path, unsigned char **buf, size_t *n )
|
||||
{
|
||||
FILE *f;
|
||||
long size;
|
||||
|
||||
if( ( f = fopen( path, "rb" ) ) == NULL )
|
||||
return( POLARSSL_ERR_X509_FILE_IO_ERROR );
|
||||
|
||||
fseek( f, 0, SEEK_END );
|
||||
if( ( size = ftell( f ) ) == -1 )
|
||||
{
|
||||
fclose( f );
|
||||
return( POLARSSL_ERR_X509_FILE_IO_ERROR );
|
||||
}
|
||||
fseek( f, 0, SEEK_SET );
|
||||
|
||||
*n = (size_t) size;
|
||||
|
||||
if( *n + 1 == 0 ||
|
||||
( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
|
||||
{
|
||||
fclose( f );
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
if( fread( *buf, 1, *n, f ) != *n )
|
||||
{
|
||||
fclose( f );
|
||||
polarssl_free( *buf );
|
||||
return( POLARSSL_ERR_X509_FILE_IO_ERROR );
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
|
||||
(*buf)[*n] = '\0';
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_RSA_C)
|
||||
/*
|
||||
* Load and parse a private RSA key
|
||||
*/
|
||||
int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd )
|
||||
{
|
||||
int ret;
|
||||
pk_context pk;
|
||||
|
||||
pk_init( &pk );
|
||||
|
||||
ret = pk_parse_keyfile( &pk, path, pwd );
|
||||
|
||||
if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
|
||||
if( ret == 0 )
|
||||
rsa_copy( rsa, pk_rsa( pk ) );
|
||||
else
|
||||
rsa_free( rsa );
|
||||
|
||||
pk_free( &pk );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Load and parse a public RSA key
|
||||
*/
|
||||
int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path )
|
||||
{
|
||||
int ret;
|
||||
pk_context pk;
|
||||
|
||||
pk_init( &pk );
|
||||
|
||||
ret = pk_parse_public_keyfile( &pk, path );
|
||||
|
||||
if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
|
||||
if( ret == 0 )
|
||||
rsa_copy( rsa, pk_rsa( pk ) );
|
||||
else
|
||||
rsa_free( rsa );
|
||||
|
||||
pk_free( &pk );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* POLARSSL_RSA_C */
|
||||
#endif /* POLARSSL_FS_IO */
|
||||
|
||||
#if defined(POLARSSL_RSA_C)
|
||||
/*
|
||||
* Parse a private RSA key
|
||||
*/
|
||||
int x509parse_key_rsa( rsa_context *rsa,
|
||||
const unsigned char *key, size_t keylen,
|
||||
const unsigned char *pwd, size_t pwdlen )
|
||||
{
|
||||
int ret;
|
||||
pk_context pk;
|
||||
|
||||
pk_init( &pk );
|
||||
|
||||
ret = pk_parse_key( &pk, key, keylen, pwd, pwdlen );
|
||||
|
||||
if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
|
||||
if( ret == 0 )
|
||||
rsa_copy( rsa, pk_rsa( pk ) );
|
||||
else
|
||||
rsa_free( rsa );
|
||||
|
||||
pk_free( &pk );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a public RSA key
|
||||
*/
|
||||
int x509parse_public_key_rsa( rsa_context *rsa,
|
||||
const unsigned char *key, size_t keylen )
|
||||
{
|
||||
int ret;
|
||||
pk_context pk;
|
||||
|
||||
pk_init( &pk );
|
||||
|
||||
ret = pk_parse_public_key( &pk, key, keylen );
|
||||
|
||||
if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) )
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
|
||||
if( ret == 0 )
|
||||
rsa_copy( rsa, pk_rsa( pk ) );
|
||||
else
|
||||
rsa_free( rsa );
|
||||
|
||||
pk_free( &pk );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* POLARSSL_RSA_C */
|
||||
|
||||
#if defined _MSC_VER && !defined snprintf
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif // vsnprintf
|
||||
|
||||
/*
|
||||
* Windows _snprintf and _vsnprintf are not compatible to linux versions.
|
||||
* Result value is not size of buffer needed, but -1 if no fit is possible.
|
||||
*
|
||||
* This fuction tries to 'fix' this by at least suggesting enlarging the
|
||||
* size by 20.
|
||||
*/
|
||||
static int compat_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int res = -1;
|
||||
|
||||
va_start( ap, format );
|
||||
|
||||
res = vsnprintf( str, size, format, ap );
|
||||
|
||||
va_end( ap );
|
||||
|
||||
// No quick fix possible
|
||||
if ( res < 0 )
|
||||
return( (int) size + 20 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define snprintf compat_snprintf
|
||||
#endif
|
||||
|
||||
#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
|
||||
|
||||
#define SAFE_SNPRINTF() \
|
||||
{ \
|
||||
if( ret == -1 ) \
|
||||
return( -1 ); \
|
||||
\
|
||||
if ( (unsigned int) ret > n ) { \
|
||||
p[n - 1] = '\0'; \
|
||||
return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
|
||||
} \
|
||||
\
|
||||
n -= (unsigned int) ret; \
|
||||
p += (unsigned int) ret; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the name in printable form into buf; no more
|
||||
* than size characters will be written
|
||||
*/
|
||||
int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
|
||||
{
|
||||
int ret;
|
||||
size_t i, n;
|
||||
unsigned char c;
|
||||
const x509_name *name;
|
||||
const char *short_name = NULL;
|
||||
char s[128], *p;
|
||||
|
||||
memset( s, 0, sizeof( s ) );
|
||||
|
||||
name = dn;
|
||||
p = buf;
|
||||
n = size;
|
||||
|
||||
while( name != NULL )
|
||||
{
|
||||
if( !name->oid.p )
|
||||
{
|
||||
name = name->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( name != dn )
|
||||
{
|
||||
ret = snprintf( p, n, ", " );
|
||||
SAFE_SNPRINTF();
|
||||
}
|
||||
|
||||
ret = oid_get_attr_short_name( &name->oid, &short_name );
|
||||
|
||||
if( ret == 0 )
|
||||
ret = snprintf( p, n, "%s=", short_name );
|
||||
else
|
||||
ret = snprintf( p, n, "\?\?=" );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
for( i = 0; i < name->val.len; i++ )
|
||||
{
|
||||
if( i >= sizeof( s ) - 1 )
|
||||
break;
|
||||
|
||||
c = name->val.p[i];
|
||||
if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
|
||||
s[i] = '?';
|
||||
else s[i] = c;
|
||||
}
|
||||
s[i] = '\0';
|
||||
ret = snprintf( p, n, "%s", s );
|
||||
SAFE_SNPRINTF();
|
||||
name = name->next;
|
||||
}
|
||||
|
||||
return( (int) ( size - n ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the serial in printable form into buf; no more
|
||||
* than size characters will be written
|
||||
*/
|
||||
int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
|
||||
{
|
||||
int ret;
|
||||
size_t i, n, nr;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
n = size;
|
||||
|
||||
nr = ( serial->len <= 32 )
|
||||
? serial->len : 28;
|
||||
|
||||
for( i = 0; i < nr; i++ )
|
||||
{
|
||||
if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
|
||||
continue;
|
||||
|
||||
ret = snprintf( p, n, "%02X%s",
|
||||
serial->p[i], ( i < nr - 1 ) ? ":" : "" );
|
||||
SAFE_SNPRINTF();
|
||||
}
|
||||
|
||||
if( nr != serial->len )
|
||||
{
|
||||
ret = snprintf( p, n, "...." );
|
||||
SAFE_SNPRINTF();
|
||||
}
|
||||
|
||||
return( (int) ( size - n ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for writing "RSA key size", "EC key size", etc
|
||||
*/
|
||||
int x509_key_size_helper( char *buf, size_t size, const char *name )
|
||||
{
|
||||
char *p = buf;
|
||||
size_t n = size;
|
||||
int ret;
|
||||
|
||||
if( strlen( name ) + sizeof( " key size" ) > size )
|
||||
return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
|
||||
|
||||
ret = snprintf( p, n, "%s key size", name );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an informational string describing the given OID
|
||||
*/
|
||||
const char *x509_oid_get_description( x509_buf *oid )
|
||||
{
|
||||
const char *desc = NULL;
|
||||
int ret;
|
||||
|
||||
ret = oid_get_extended_key_usage( oid, &desc );
|
||||
|
||||
if( ret != 0 )
|
||||
return( NULL );
|
||||
|
||||
return( desc );
|
||||
}
|
||||
|
||||
/* Return the x.y.z.... style numeric string for the given OID */
|
||||
int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
|
||||
{
|
||||
return oid_get_numeric_string( buf, size, oid );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if the x509_time is still valid, or 1 otherwise.
|
||||
*/
|
||||
#if defined(POLARSSL_HAVE_TIME)
|
||||
int x509parse_time_expired( const x509_time *to )
|
||||
{
|
||||
int year, mon, day;
|
||||
int hour, min, sec;
|
||||
|
||||
#if defined(_WIN32)
|
||||
SYSTEMTIME st;
|
||||
|
||||
GetLocalTime(&st);
|
||||
|
||||
year = st.wYear;
|
||||
mon = st.wMonth;
|
||||
day = st.wDay;
|
||||
hour = st.wHour;
|
||||
min = st.wMinute;
|
||||
sec = st.wSecond;
|
||||
#else
|
||||
struct tm *lt;
|
||||
time_t tt;
|
||||
|
||||
tt = time( NULL );
|
||||
lt = localtime( &tt );
|
||||
|
||||
year = lt->tm_year + 1900;
|
||||
mon = lt->tm_mon + 1;
|
||||
day = lt->tm_mday;
|
||||
hour = lt->tm_hour;
|
||||
min = lt->tm_min;
|
||||
sec = lt->tm_sec;
|
||||
#endif
|
||||
|
||||
if( year > to->year )
|
||||
return( 1 );
|
||||
|
||||
if( year == to->year &&
|
||||
mon > to->mon )
|
||||
return( 1 );
|
||||
|
||||
if( year == to->year &&
|
||||
mon == to->mon &&
|
||||
day > to->day )
|
||||
return( 1 );
|
||||
|
||||
if( year == to->year &&
|
||||
mon == to->mon &&
|
||||
day == to->day &&
|
||||
hour > to->hour )
|
||||
return( 1 );
|
||||
|
||||
if( year == to->year &&
|
||||
mon == to->mon &&
|
||||
day == to->day &&
|
||||
hour == to->hour &&
|
||||
min > to->min )
|
||||
return( 1 );
|
||||
|
||||
if( year == to->year &&
|
||||
mon == to->mon &&
|
||||
day == to->day &&
|
||||
hour == to->hour &&
|
||||
min == to->min &&
|
||||
sec > to->sec )
|
||||
return( 1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#else /* POLARSSL_HAVE_TIME */
|
||||
int x509parse_time_expired( const x509_time *to )
|
||||
{
|
||||
((void) to);
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* POLARSSL_HAVE_TIME */
|
||||
|
||||
#endif /* POLARSSL_X509_USE_C */
|
267
library/x509_create.c
Normal file
267
library/x509_create.c
Normal file
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* X.509 base functions for creating certificates / CSRs
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_CREATE_C)
|
||||
|
||||
#include "polarssl/x509.h"
|
||||
#include "polarssl/asn1write.h"
|
||||
#include "polarssl/oid.h"
|
||||
|
||||
int x509write_string_to_names( asn1_named_data **head, char *name )
|
||||
{
|
||||
int ret = 0;
|
||||
char *s = name, *c = s;
|
||||
char *end = s + strlen( s );
|
||||
char *oid = NULL;
|
||||
int in_tag = 1;
|
||||
asn1_named_data *cur;
|
||||
|
||||
/* Clear existing chain if present */
|
||||
asn1_free_named_data_list( head );
|
||||
|
||||
while( c <= end )
|
||||
{
|
||||
if( in_tag && *c == '=' )
|
||||
{
|
||||
if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_CN;
|
||||
else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_COUNTRY;
|
||||
else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_ORGANIZATION;
|
||||
else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_LOCALITY;
|
||||
else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_PKCS9_EMAIL;
|
||||
else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_ORG_UNIT;
|
||||
else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_STATE;
|
||||
else
|
||||
{
|
||||
ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
s = c + 1;
|
||||
in_tag = 0;
|
||||
}
|
||||
|
||||
if( !in_tag && ( *c == ',' || c == end ) )
|
||||
{
|
||||
if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
|
||||
(unsigned char *) s,
|
||||
c - s ) ) == NULL )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
while( c < end && *(c + 1) == ' ' )
|
||||
c++;
|
||||
|
||||
s = c + 1;
|
||||
in_tag = 1;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* The first byte of the value in the asn1_named_data structure is reserved
|
||||
* to store the critical boolean for us
|
||||
*/
|
||||
int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
|
||||
int critical, const unsigned char *val, size_t val_len )
|
||||
{
|
||||
asn1_named_data *cur;
|
||||
|
||||
if( ( cur = asn1_store_named_data( head, oid, oid_len,
|
||||
NULL, val_len + 1 ) ) == NULL )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
cur->val.p[0] = critical;
|
||||
memcpy( cur->val.p + 1, val, val_len );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* RelativeDistinguishedName ::=
|
||||
* SET OF AttributeTypeAndValue
|
||||
*
|
||||
* AttributeTypeAndValue ::= SEQUENCE {
|
||||
* type AttributeType,
|
||||
* value AttributeValue }
|
||||
*
|
||||
* AttributeType ::= OBJECT IDENTIFIER
|
||||
*
|
||||
* AttributeValue ::= ANY DEFINED BY AttributeType
|
||||
*/
|
||||
static int x509_write_name( unsigned char **p, unsigned char *start,
|
||||
const char *oid, size_t oid_len,
|
||||
const unsigned char *name, size_t name_len )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
// Write PrintableString for all except OID_PKCS9_EMAIL
|
||||
//
|
||||
if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
|
||||
memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
|
||||
(const char *) name,
|
||||
name_len ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
|
||||
(const char *) name,
|
||||
name_len ) );
|
||||
}
|
||||
|
||||
// Write OID
|
||||
//
|
||||
ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int x509_write_names( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *first )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
asn1_named_data *cur = first;
|
||||
|
||||
while( cur != NULL )
|
||||
{
|
||||
ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
|
||||
cur->oid.len,
|
||||
cur->val.p, cur->val.len ) );
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int x509_write_sig( unsigned char **p, unsigned char *start,
|
||||
const char *oid, size_t oid_len,
|
||||
unsigned char *sig, size_t size )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
if( *p - start < (int) size + 1 )
|
||||
return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
len = size;
|
||||
(*p) -= len;
|
||||
memcpy( *p, sig, len );
|
||||
|
||||
*--(*p) = 0;
|
||||
len += 1;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
|
||||
|
||||
// Write OID
|
||||
//
|
||||
ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
|
||||
oid_len, 0 ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
static int x509_write_extension( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *ext )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
|
||||
ext->val.len - 1 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
|
||||
|
||||
if( ext->val.p[0] != 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
|
||||
ext->oid.len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* }
|
||||
*/
|
||||
int x509_write_extensions( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *first )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
asn1_named_data *cur_ext = first;
|
||||
|
||||
while( cur_ext != NULL )
|
||||
{
|
||||
ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
|
||||
cur_ext = cur_ext->next;
|
||||
}
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
#endif /* POLARSSL_X509_CREATE_C */
|
740
library/x509_crl.c
Normal file
740
library/x509_crl.c
Normal file
|
@ -0,0 +1,740 @@
|
|||
/*
|
||||
* X.509 certificate and private key decoding
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* The ITU-T X.509 standard defines a certificate format for PKI.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc3279.txt
|
||||
* http://www.ietf.org/rfc/rfc3280.txt
|
||||
*
|
||||
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
|
||||
*
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_CRL_PARSE_C)
|
||||
|
||||
#include "polarssl/x509_crl.h"
|
||||
#include "polarssl/oid.h"
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_MEMORY_C)
|
||||
#include "polarssl/memory.h"
|
||||
#else
|
||||
#define polarssl_malloc malloc
|
||||
#define polarssl_free free
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1) }
|
||||
*/
|
||||
static int x509_crl_get_version( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
int *ver )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
|
||||
{
|
||||
if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
|
||||
{
|
||||
*ver = 0;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* X.509 CRL v2 extensions (no extensions parsed yet.)
|
||||
*/
|
||||
static int x509_get_crl_ext( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
x509_buf *ext )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
/* Get explicit tag */
|
||||
if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
|
||||
{
|
||||
if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
|
||||
return( 0 );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
while( *p < end )
|
||||
{
|
||||
if( ( ret = asn1_get_tag( p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
|
||||
|
||||
*p += len;
|
||||
}
|
||||
|
||||
if( *p != end )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* X.509 CRL v2 entry extensions (no extensions parsed yet.)
|
||||
*/
|
||||
static int x509_get_crl_entry_ext( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
x509_buf *ext )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
/* OPTIONAL */
|
||||
if (end <= *p)
|
||||
return( 0 );
|
||||
|
||||
ext->tag = **p;
|
||||
ext->p = *p;
|
||||
|
||||
/*
|
||||
* Get CRL-entry extension sequence header
|
||||
* crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
|
||||
*/
|
||||
if( ( ret = asn1_get_tag( p, end, &ext->len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
|
||||
{
|
||||
ext->p = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
|
||||
}
|
||||
|
||||
end = *p + ext->len;
|
||||
|
||||
if( end != *p + ext->len )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
|
||||
while( *p < end )
|
||||
{
|
||||
if( ( ret = asn1_get_tag( p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
|
||||
|
||||
*p += len;
|
||||
}
|
||||
|
||||
if( *p != end )
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* X.509 CRL Entries
|
||||
*/
|
||||
static int x509_get_entries( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
x509_crl_entry *entry )
|
||||
{
|
||||
int ret;
|
||||
size_t entry_len;
|
||||
x509_crl_entry *cur_entry = entry;
|
||||
|
||||
if( *p == end )
|
||||
return( 0 );
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &entry_len,
|
||||
ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
|
||||
{
|
||||
if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
|
||||
return( 0 );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
end = *p + entry_len;
|
||||
|
||||
while( *p < end )
|
||||
{
|
||||
size_t len2;
|
||||
const unsigned char *end2;
|
||||
|
||||
if( ( ret = asn1_get_tag( p, end, &len2,
|
||||
ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
cur_entry->raw.tag = **p;
|
||||
cur_entry->raw.p = *p;
|
||||
cur_entry->raw.len = len2;
|
||||
end2 = *p + len2;
|
||||
|
||||
if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if ( *p < end )
|
||||
{
|
||||
cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) );
|
||||
|
||||
if( cur_entry->next == NULL )
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
|
||||
cur_entry = cur_entry->next;
|
||||
memset( cur_entry, 0, sizeof( x509_crl_entry ) );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse one or more CRLs and add them to the chained list
|
||||
*/
|
||||
int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
unsigned char *p, *end;
|
||||
x509_crl *crl;
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
size_t use_len;
|
||||
pem_context pem;
|
||||
#endif
|
||||
|
||||
crl = chain;
|
||||
|
||||
/*
|
||||
* Check for valid input
|
||||
*/
|
||||
if( crl == NULL || buf == NULL )
|
||||
return( POLARSSL_ERR_X509_INVALID_INPUT );
|
||||
|
||||
while( crl->version != 0 && crl->next != NULL )
|
||||
crl = crl->next;
|
||||
|
||||
/*
|
||||
* Add new CRL on the end of the chain if needed.
|
||||
*/
|
||||
if ( crl->version != 0 && crl->next == NULL)
|
||||
{
|
||||
crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
|
||||
|
||||
if( crl->next == NULL )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
crl = crl->next;
|
||||
memset( crl, 0, sizeof( x509_crl ) );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
pem_init( &pem );
|
||||
ret = pem_read_buffer( &pem,
|
||||
"-----BEGIN X509 CRL-----",
|
||||
"-----END X509 CRL-----",
|
||||
buf, NULL, 0, &use_len );
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
/*
|
||||
* Was PEM encoded
|
||||
*/
|
||||
buflen -= use_len;
|
||||
buf += use_len;
|
||||
|
||||
/*
|
||||
* Steal PEM buffer
|
||||
*/
|
||||
p = pem.buf;
|
||||
pem.buf = NULL;
|
||||
len = pem.buflen;
|
||||
pem_free( &pem );
|
||||
}
|
||||
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
|
||||
{
|
||||
pem_free( &pem );
|
||||
return( ret );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* nope, copy the raw DER data
|
||||
*/
|
||||
p = (unsigned char *) polarssl_malloc( len = buflen );
|
||||
|
||||
if( p == NULL )
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
|
||||
memcpy( p, buf, buflen );
|
||||
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
crl->raw.p = p;
|
||||
crl->raw.len = len;
|
||||
end = p + len;
|
||||
|
||||
/*
|
||||
* CertificateList ::= SEQUENCE {
|
||||
* tbsCertList TBSCertList,
|
||||
* signatureAlgorithm AlgorithmIdentifier,
|
||||
* signatureValue BIT STRING }
|
||||
*/
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
|
||||
}
|
||||
|
||||
if( len != (size_t) ( end - p ) )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
}
|
||||
|
||||
/*
|
||||
* TBSCertList ::= SEQUENCE {
|
||||
*/
|
||||
crl->tbs.p = p;
|
||||
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
|
||||
}
|
||||
|
||||
end = p + len;
|
||||
crl->tbs.len = end - crl->tbs.p;
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
|
||||
* -- if present, MUST be v2
|
||||
*
|
||||
* signature AlgorithmIdentifier
|
||||
*/
|
||||
if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
|
||||
( ret = x509_get_alg_null( &p, end, &crl->sig_oid1 ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
crl->version++;
|
||||
|
||||
if( crl->version > 2 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_md,
|
||||
&crl->sig_pk ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
|
||||
}
|
||||
|
||||
/*
|
||||
* issuer Name
|
||||
*/
|
||||
crl->issuer_raw.p = p;
|
||||
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
crl->issuer_raw.len = p - crl->issuer_raw.p;
|
||||
|
||||
/*
|
||||
* thisUpdate Time
|
||||
* nextUpdate Time OPTIONAL
|
||||
*/
|
||||
if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
|
||||
{
|
||||
if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
|
||||
POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
|
||||
ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
|
||||
POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* revokedCertificates SEQUENCE OF SEQUENCE {
|
||||
* userCertificate CertificateSerialNumber,
|
||||
* revocationDate Time,
|
||||
* crlEntryExtensions Extensions OPTIONAL
|
||||
* -- if present, MUST be v2
|
||||
* } OPTIONAL
|
||||
*/
|
||||
if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* crlExtensions EXPLICIT Extensions OPTIONAL
|
||||
* -- if present, MUST be v2
|
||||
*/
|
||||
if( crl->version == 2 )
|
||||
{
|
||||
ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
||||
if( p != end )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
}
|
||||
|
||||
end = crl->raw.p + crl->raw.len;
|
||||
|
||||
/*
|
||||
* signatureAlgorithm AlgorithmIdentifier,
|
||||
* signatureValue BIT STRING
|
||||
*/
|
||||
if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( crl->sig_oid1.len != crl->sig_oid2.len ||
|
||||
memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( p != end )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
}
|
||||
|
||||
if( buflen > 0 )
|
||||
{
|
||||
crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
|
||||
|
||||
if( crl->next == NULL )
|
||||
{
|
||||
x509_crl_free( crl );
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
crl = crl->next;
|
||||
memset( crl, 0, sizeof( x509_crl ) );
|
||||
|
||||
return( x509parse_crl( crl, buf, buflen ) );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
/*
|
||||
* Load one or more CRLs and add them to the chained list
|
||||
*/
|
||||
int x509parse_crlfile( x509_crl *chain, const char *path )
|
||||
{
|
||||
int ret;
|
||||
size_t n;
|
||||
unsigned char *buf;
|
||||
|
||||
if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = x509parse_crl( chain, buf, n );
|
||||
|
||||
memset( buf, 0, n + 1 );
|
||||
polarssl_free( buf );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* POLARSSL_FS_IO */
|
||||
|
||||
#if defined _MSC_VER && !defined snprintf
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif // vsnprintf
|
||||
|
||||
/*
|
||||
* Windows _snprintf and _vsnprintf are not compatible to linux versions.
|
||||
* Result value is not size of buffer needed, but -1 if no fit is possible.
|
||||
*
|
||||
* This fuction tries to 'fix' this by at least suggesting enlarging the
|
||||
* size by 20.
|
||||
*/
|
||||
static int compat_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int res = -1;
|
||||
|
||||
va_start( ap, format );
|
||||
|
||||
res = vsnprintf( str, size, format, ap );
|
||||
|
||||
va_end( ap );
|
||||
|
||||
// No quick fix possible
|
||||
if ( res < 0 )
|
||||
return( (int) size + 20 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define snprintf compat_snprintf
|
||||
#endif
|
||||
|
||||
#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
|
||||
|
||||
#define SAFE_SNPRINTF() \
|
||||
{ \
|
||||
if( ret == -1 ) \
|
||||
return( -1 ); \
|
||||
\
|
||||
if ( (unsigned int) ret > n ) { \
|
||||
p[n - 1] = '\0'; \
|
||||
return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
|
||||
} \
|
||||
\
|
||||
n -= (unsigned int) ret; \
|
||||
p += (unsigned int) ret; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an informational string about the certificate.
|
||||
*/
|
||||
#define BEFORE_COLON 14
|
||||
#define BC "14"
|
||||
/*
|
||||
* Return an informational string about the CRL.
|
||||
*/
|
||||
int x509parse_crl_info( char *buf, size_t size, const char *prefix,
|
||||
const x509_crl *crl )
|
||||
{
|
||||
int ret;
|
||||
size_t n;
|
||||
char *p;
|
||||
const char *desc;
|
||||
const x509_crl_entry *entry;
|
||||
|
||||
p = buf;
|
||||
n = size;
|
||||
|
||||
ret = snprintf( p, n, "%sCRL version : %d",
|
||||
prefix, crl->version );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n%sissuer name : ", prefix );
|
||||
SAFE_SNPRINTF();
|
||||
ret = x509parse_dn_gets( p, n, &crl->issuer );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n%sthis update : " \
|
||||
"%04d-%02d-%02d %02d:%02d:%02d", prefix,
|
||||
crl->this_update.year, crl->this_update.mon,
|
||||
crl->this_update.day, crl->this_update.hour,
|
||||
crl->this_update.min, crl->this_update.sec );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n%snext update : " \
|
||||
"%04d-%02d-%02d %02d:%02d:%02d", prefix,
|
||||
crl->next_update.year, crl->next_update.mon,
|
||||
crl->next_update.day, crl->next_update.hour,
|
||||
crl->next_update.min, crl->next_update.sec );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
entry = &crl->entry;
|
||||
|
||||
ret = snprintf( p, n, "\n%sRevoked certificates:",
|
||||
prefix );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
while( entry != NULL && entry->raw.len != 0 )
|
||||
{
|
||||
ret = snprintf( p, n, "\n%sserial number: ",
|
||||
prefix );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = x509parse_serial_gets( p, n, &entry->serial);
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, " revocation date: " \
|
||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
entry->revocation_date.year, entry->revocation_date.mon,
|
||||
entry->revocation_date.day, entry->revocation_date.hour,
|
||||
entry->revocation_date.min, entry->revocation_date.sec );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
ret = snprintf( p, n, "\n%ssigned using : ", prefix );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = oid_get_sig_alg_desc( &crl->sig_oid1, &desc );
|
||||
if( ret != 0 )
|
||||
ret = snprintf( p, n, "???" );
|
||||
else
|
||||
ret = snprintf( p, n, "%s", desc );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n" );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
return( (int) ( size - n ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Unallocate all CRL data
|
||||
*/
|
||||
void x509_crl_free( x509_crl *crl )
|
||||
{
|
||||
x509_crl *crl_cur = crl;
|
||||
x509_crl *crl_prv;
|
||||
x509_name *name_cur;
|
||||
x509_name *name_prv;
|
||||
x509_crl_entry *entry_cur;
|
||||
x509_crl_entry *entry_prv;
|
||||
|
||||
if( crl == NULL )
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
name_cur = crl_cur->issuer.next;
|
||||
while( name_cur != NULL )
|
||||
{
|
||||
name_prv = name_cur;
|
||||
name_cur = name_cur->next;
|
||||
memset( name_prv, 0, sizeof( x509_name ) );
|
||||
polarssl_free( name_prv );
|
||||
}
|
||||
|
||||
entry_cur = crl_cur->entry.next;
|
||||
while( entry_cur != NULL )
|
||||
{
|
||||
entry_prv = entry_cur;
|
||||
entry_cur = entry_cur->next;
|
||||
memset( entry_prv, 0, sizeof( x509_crl_entry ) );
|
||||
polarssl_free( entry_prv );
|
||||
}
|
||||
|
||||
if( crl_cur->raw.p != NULL )
|
||||
{
|
||||
memset( crl_cur->raw.p, 0, crl_cur->raw.len );
|
||||
polarssl_free( crl_cur->raw.p );
|
||||
}
|
||||
|
||||
crl_cur = crl_cur->next;
|
||||
}
|
||||
while( crl_cur != NULL );
|
||||
|
||||
crl_cur = crl;
|
||||
do
|
||||
{
|
||||
crl_prv = crl_cur;
|
||||
crl_cur = crl_cur->next;
|
||||
|
||||
memset( crl_prv, 0, sizeof( x509_crl ) );
|
||||
if( crl_prv != crl )
|
||||
polarssl_free( crl_prv );
|
||||
}
|
||||
while( crl_cur != NULL );
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
426
library/x509_crt_write.c
Normal file
426
library/x509_crt_write.c
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*
|
||||
* X.509 certificate writing
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* References:
|
||||
* - certificates: RFC 5280, updated by RFC 6818
|
||||
* - CSRs: PKCS#10 v1.7 aka RFC 2986
|
||||
* - attributes: PKCS#9 v2.0 aka RFC 2985
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_CRT_WRITE_C)
|
||||
|
||||
#include "polarssl/x509_crt.h"
|
||||
#include "polarssl/oid.h"
|
||||
#include "polarssl/asn1write.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif /* POLARSSL_PEM_WRITE_C */
|
||||
|
||||
void x509write_crt_init( x509write_cert *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof(x509write_cert) );
|
||||
|
||||
mpi_init( &ctx->serial );
|
||||
ctx->version = X509_CRT_VERSION_3;
|
||||
}
|
||||
|
||||
void x509write_crt_free( x509write_cert *ctx )
|
||||
{
|
||||
mpi_free( &ctx->serial );
|
||||
|
||||
asn1_free_named_data_list( &ctx->subject );
|
||||
asn1_free_named_data_list( &ctx->issuer );
|
||||
asn1_free_named_data_list( &ctx->extensions );
|
||||
|
||||
memset( ctx, 0, sizeof(x509write_cert) );
|
||||
}
|
||||
|
||||
void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
|
||||
{
|
||||
ctx->md_alg = md_alg;
|
||||
}
|
||||
|
||||
void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
|
||||
{
|
||||
ctx->subject_key = key;
|
||||
}
|
||||
|
||||
void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
|
||||
{
|
||||
ctx->issuer_key = key;
|
||||
}
|
||||
|
||||
int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->subject, subject_name );
|
||||
}
|
||||
|
||||
int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->issuer, issuer_name );
|
||||
}
|
||||
|
||||
int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
|
||||
char *not_after )
|
||||
{
|
||||
if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
|
||||
strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
|
||||
}
|
||||
strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
|
||||
strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
|
||||
ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
|
||||
ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
return x509_set_extension( &ctx->extensions, oid, oid_len,
|
||||
critical, val, val_len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_basic_constraints( x509write_cert *ctx,
|
||||
int is_ca, int max_pathlen )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[9];
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf) );
|
||||
|
||||
if( is_ca && max_pathlen > 127 )
|
||||
return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
|
||||
|
||||
if( is_ca )
|
||||
{
|
||||
if( max_pathlen >= 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
|
||||
}
|
||||
ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
|
||||
OID_SIZE( OID_BASIC_CONSTRAINTS ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf));
|
||||
ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
|
||||
|
||||
sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
|
||||
c = buf + sizeof(buf) - 20;
|
||||
len = 20;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
|
||||
OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf));
|
||||
ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
|
||||
|
||||
sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
|
||||
c = buf + sizeof(buf) - 20;
|
||||
len = 20;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
|
||||
OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
|
||||
OID_SIZE( OID_KEY_USAGE ),
|
||||
1, buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
|
||||
unsigned char ns_cert_type )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
|
||||
OID_SIZE( OID_NS_CERT_TYPE ),
|
||||
0, buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int x509_write_time( unsigned char **p, unsigned char *start,
|
||||
const char *time, size_t size )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
/*
|
||||
* write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
|
||||
*/
|
||||
if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) time + 2,
|
||||
size - 2 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) time,
|
||||
size ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
|
||||
}
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
const char *sig_oid;
|
||||
size_t sig_oid_len = 0;
|
||||
unsigned char *c, *c2;
|
||||
unsigned char hash[64];
|
||||
unsigned char sig[POLARSSL_MPI_MAX_SIZE];
|
||||
unsigned char tmp_buf[2048];
|
||||
size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
|
||||
size_t len = 0;
|
||||
pk_type_t pk_alg;
|
||||
|
||||
/*
|
||||
* Prepare data to be signed in tmp_buf
|
||||
*/
|
||||
c = tmp_buf + sizeof( tmp_buf );
|
||||
|
||||
/* Signature algorithm needed in TBS, and later for actual signature */
|
||||
pk_alg = pk_get_type( ctx->issuer_key );
|
||||
if( pk_alg == POLARSSL_PK_ECKEY )
|
||||
pk_alg = POLARSSL_PK_ECDSA;
|
||||
|
||||
if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
|
||||
&sig_oid, &sig_oid_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
|
||||
|
||||
/*
|
||||
* SubjectPublicKeyInfo
|
||||
*/
|
||||
ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
|
||||
tmp_buf, c - tmp_buf ) );
|
||||
c -= pub_len;
|
||||
len += pub_len;
|
||||
|
||||
/*
|
||||
* Subject ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
|
||||
|
||||
/*
|
||||
* Validity ::= SEQUENCE {
|
||||
* notBefore Time,
|
||||
* notAfter Time }
|
||||
*/
|
||||
sub_len = 0;
|
||||
|
||||
ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
|
||||
X509_RFC5280_UTC_TIME_LEN ) );
|
||||
|
||||
ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
|
||||
X509_RFC5280_UTC_TIME_LEN ) );
|
||||
|
||||
len += sub_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Issuer ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
|
||||
|
||||
/*
|
||||
* Signature ::= AlgorithmIdentifier
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
|
||||
sig_oid, strlen( sig_oid ), 0 ) );
|
||||
|
||||
/*
|
||||
* Serial ::= INTEGER
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
|
||||
*/
|
||||
sub_len = 0;
|
||||
ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
|
||||
len += sub_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Make signature
|
||||
*/
|
||||
md( md_info_from_type( ctx->md_alg ), c, len, hash );
|
||||
|
||||
if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
|
||||
f_rng, p_rng ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to output buffer
|
||||
*/
|
||||
c2 = buf + size;
|
||||
ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
|
||||
sig_oid, sig_oid_len, sig, sig_len ) );
|
||||
|
||||
c2 -= len;
|
||||
memcpy( c2, c, len );
|
||||
|
||||
len += sig_and_oid_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
|
||||
#define PEM_END_CRT "-----END CERTIFICATE-----\n"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
unsigned char output_buf[4096];
|
||||
size_t olen = 0;
|
||||
|
||||
if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
|
||||
f_rng, p_rng ) ) < 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
|
||||
output_buf + sizeof(output_buf) - ret,
|
||||
ret, buf, size, &olen ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* POLARSSL_PEM_WRITE_C */
|
||||
|
||||
#endif /* POLARSSL_X509_CRT_WRITE_C */
|
439
library/x509_csr.c
Normal file
439
library/x509_csr.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* X.509 Certificate Signing Request (CSR) parsing
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* The ITU-T X.509 standard defines a certificate format for PKI.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc3279.txt
|
||||
* http://www.ietf.org/rfc/rfc3280.txt
|
||||
*
|
||||
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
|
||||
*
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
|
||||
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_CSR_PARSE_C)
|
||||
|
||||
#include "polarssl/x509_csr.h"
|
||||
#include "polarssl/oid.h"
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif
|
||||
#if defined(POLARSSL_ASN1_WRITE_C)
|
||||
#include "polarssl/asn1write.h"
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_MEMORY_C)
|
||||
#include "polarssl/memory.h"
|
||||
#else
|
||||
#define polarssl_malloc malloc
|
||||
#define polarssl_free free
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0) }
|
||||
*/
|
||||
static int x509_csr_get_version( unsigned char **p,
|
||||
const unsigned char *end,
|
||||
int *ver )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
|
||||
{
|
||||
if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
|
||||
{
|
||||
*ver = 0;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a CSR
|
||||
*/
|
||||
int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
unsigned char *p, *end;
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
size_t use_len;
|
||||
pem_context pem;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for valid input
|
||||
*/
|
||||
if( csr == NULL || buf == NULL )
|
||||
return( POLARSSL_ERR_X509_INVALID_INPUT );
|
||||
|
||||
memset( csr, 0, sizeof( x509_csr ) );
|
||||
|
||||
#if defined(POLARSSL_PEM_PARSE_C)
|
||||
pem_init( &pem );
|
||||
ret = pem_read_buffer( &pem,
|
||||
"-----BEGIN CERTIFICATE REQUEST-----",
|
||||
"-----END CERTIFICATE REQUEST-----",
|
||||
buf, NULL, 0, &use_len );
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
/*
|
||||
* Was PEM encoded
|
||||
*/
|
||||
buflen -= use_len;
|
||||
buf += use_len;
|
||||
|
||||
/*
|
||||
* Steal PEM buffer
|
||||
*/
|
||||
p = pem.buf;
|
||||
pem.buf = NULL;
|
||||
len = pem.buflen;
|
||||
pem_free( &pem );
|
||||
}
|
||||
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
|
||||
{
|
||||
pem_free( &pem );
|
||||
return( ret );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* nope, copy the raw DER data
|
||||
*/
|
||||
p = (unsigned char *) polarssl_malloc( len = buflen );
|
||||
|
||||
if( p == NULL )
|
||||
return( POLARSSL_ERR_X509_MALLOC_FAILED );
|
||||
|
||||
memcpy( p, buf, buflen );
|
||||
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
csr->raw.p = p;
|
||||
csr->raw.len = len;
|
||||
end = p + len;
|
||||
|
||||
/*
|
||||
* CertificationRequest ::= SEQUENCE {
|
||||
* certificationRequestInfo CertificationRequestInfo,
|
||||
* signatureAlgorithm AlgorithmIdentifier,
|
||||
* signature BIT STRING
|
||||
* }
|
||||
*/
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
|
||||
}
|
||||
|
||||
if( len != (size_t) ( end - p ) )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
}
|
||||
|
||||
/*
|
||||
* CertificationRequestInfo ::= SEQUENCE {
|
||||
*/
|
||||
csr->cri.p = p;
|
||||
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
|
||||
}
|
||||
|
||||
end = p + len;
|
||||
csr->cri.len = end - csr->cri.p;
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0) }
|
||||
*/
|
||||
if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
csr->version++;
|
||||
|
||||
if( csr->version != 1 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
|
||||
}
|
||||
|
||||
/*
|
||||
* subject Name
|
||||
*/
|
||||
csr->subject_raw.p = p;
|
||||
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
csr->subject_raw.len = p - csr->subject_raw.p;
|
||||
|
||||
/*
|
||||
* subjectPKInfo SubjectPublicKeyInfo
|
||||
*/
|
||||
if( ( ret = pk_parse_get_pubkey( &p, end, &csr->pk ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* attributes [0] Attributes
|
||||
*/
|
||||
if( ( ret = asn1_get_tag( &p, end, &len,
|
||||
ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
|
||||
}
|
||||
// TODO Parse Attributes / extension requests
|
||||
|
||||
p += len;
|
||||
|
||||
end = csr->raw.p + csr->raw.len;
|
||||
|
||||
/*
|
||||
* signatureAlgorithm AlgorithmIdentifier,
|
||||
* signature BIT STRING
|
||||
*/
|
||||
if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
|
||||
&csr->sig_pk ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
|
||||
}
|
||||
|
||||
if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( p != end )
|
||||
{
|
||||
x509_csr_free( csr );
|
||||
return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
|
||||
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_FS_IO)
|
||||
/*
|
||||
* Load a CSR into the structure
|
||||
*/
|
||||
int x509parse_csrfile( x509_csr *csr, const char *path )
|
||||
{
|
||||
int ret;
|
||||
size_t n;
|
||||
unsigned char *buf;
|
||||
|
||||
if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = x509parse_csr( csr, buf, n );
|
||||
|
||||
memset( buf, 0, n + 1 );
|
||||
polarssl_free( buf );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* POLARSSL_FS_IO */
|
||||
|
||||
#if defined _MSC_VER && !defined snprintf
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif // vsnprintf
|
||||
|
||||
/*
|
||||
* Windows _snprintf and _vsnprintf are not compatible to linux versions.
|
||||
* Result value is not size of buffer needed, but -1 if no fit is possible.
|
||||
*
|
||||
* This fuction tries to 'fix' this by at least suggesting enlarging the
|
||||
* size by 20.
|
||||
*/
|
||||
static int compat_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int res = -1;
|
||||
|
||||
va_start( ap, format );
|
||||
|
||||
res = vsnprintf( str, size, format, ap );
|
||||
|
||||
va_end( ap );
|
||||
|
||||
// No quick fix possible
|
||||
if ( res < 0 )
|
||||
return( (int) size + 20 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define snprintf compat_snprintf
|
||||
#endif
|
||||
|
||||
#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
|
||||
|
||||
#define SAFE_SNPRINTF() \
|
||||
{ \
|
||||
if( ret == -1 ) \
|
||||
return( -1 ); \
|
||||
\
|
||||
if ( (unsigned int) ret > n ) { \
|
||||
p[n - 1] = '\0'; \
|
||||
return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
|
||||
} \
|
||||
\
|
||||
n -= (unsigned int) ret; \
|
||||
p += (unsigned int) ret; \
|
||||
}
|
||||
|
||||
#define BEFORE_COLON 14
|
||||
#define BC "14"
|
||||
/*
|
||||
* Return an informational string about the CSR.
|
||||
*/
|
||||
int x509parse_csr_info( char *buf, size_t size, const char *prefix,
|
||||
const x509_csr *csr )
|
||||
{
|
||||
int ret;
|
||||
size_t n;
|
||||
char *p;
|
||||
const char *desc;
|
||||
char key_size_str[BEFORE_COLON];
|
||||
|
||||
p = buf;
|
||||
n = size;
|
||||
|
||||
ret = snprintf( p, n, "%sCSR version : %d",
|
||||
prefix, csr->version );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n%ssubject name : ", prefix );
|
||||
SAFE_SNPRINTF();
|
||||
ret = x509parse_dn_gets( p, n, &csr->subject );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = snprintf( p, n, "\n%ssigned using : ", prefix );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
|
||||
if( ret != 0 )
|
||||
ret = snprintf( p, n, "???" );
|
||||
else
|
||||
ret = snprintf( p, n, "%s", desc );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
|
||||
pk_get_name( &csr->pk ) ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
|
||||
(int) pk_get_size( &csr->pk ) );
|
||||
SAFE_SNPRINTF();
|
||||
|
||||
return( (int) ( size - n ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Unallocate all CSR data
|
||||
*/
|
||||
void x509_csr_free( x509_csr *csr )
|
||||
{
|
||||
x509_name *name_cur;
|
||||
x509_name *name_prv;
|
||||
|
||||
if( csr == NULL )
|
||||
return;
|
||||
|
||||
pk_free( &csr->pk );
|
||||
|
||||
name_cur = csr->subject.next;
|
||||
while( name_cur != NULL )
|
||||
{
|
||||
name_prv = name_cur;
|
||||
name_cur = name_cur->next;
|
||||
memset( name_prv, 0, sizeof( x509_name ) );
|
||||
polarssl_free( name_prv );
|
||||
}
|
||||
|
||||
if( csr->raw.p != NULL )
|
||||
{
|
||||
memset( csr->raw.p, 0, csr->raw.len );
|
||||
polarssl_free( csr->raw.p );
|
||||
}
|
||||
|
||||
memset( csr, 0, sizeof( x509_csr ) );
|
||||
}
|
||||
|
||||
#endif /* POLARSSL_X509_CSR_PARSE_C */
|
244
library/x509_csr_write.c
Normal file
244
library/x509_csr_write.c
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* X.509 Certificate Signing Request writing
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* References:
|
||||
* - CSRs: PKCS#10 v1.7 aka RFC 2986
|
||||
* - attributes: PKCS#9 v2.0 aka RFC 2985
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_CSR_WRITE_C)
|
||||
|
||||
#include "polarssl/x509_csr.h"
|
||||
#include "polarssl/oid.h"
|
||||
#include "polarssl/asn1write.h"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void x509write_csr_init( x509write_csr *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof(x509write_csr) );
|
||||
}
|
||||
|
||||
void x509write_csr_free( x509write_csr *ctx )
|
||||
{
|
||||
asn1_free_named_data_list( &ctx->subject );
|
||||
asn1_free_named_data_list( &ctx->extensions );
|
||||
|
||||
memset( ctx, 0, sizeof(x509write_csr) );
|
||||
}
|
||||
|
||||
void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
|
||||
{
|
||||
ctx->md_alg = md_alg;
|
||||
}
|
||||
|
||||
void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
|
||||
{
|
||||
ctx->key = key;
|
||||
}
|
||||
|
||||
int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->subject, subject_name );
|
||||
}
|
||||
|
||||
int x509write_csr_set_extension( x509write_csr *ctx,
|
||||
const char *oid, size_t oid_len,
|
||||
const unsigned char *val, size_t val_len )
|
||||
{
|
||||
return x509_set_extension( &ctx->extensions, oid, oid_len,
|
||||
0, val, val_len );
|
||||
}
|
||||
|
||||
int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
|
||||
OID_SIZE( OID_KEY_USAGE ),
|
||||
buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
|
||||
unsigned char ns_cert_type )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
|
||||
OID_SIZE( OID_NS_CERT_TYPE ),
|
||||
buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
const char *sig_oid;
|
||||
size_t sig_oid_len = 0;
|
||||
unsigned char *c, *c2;
|
||||
unsigned char hash[64];
|
||||
unsigned char sig[POLARSSL_MPI_MAX_SIZE];
|
||||
unsigned char tmp_buf[2048];
|
||||
size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
|
||||
size_t len = 0;
|
||||
pk_type_t pk_alg;
|
||||
|
||||
/*
|
||||
* Prepare data to be signed in tmp_buf
|
||||
*/
|
||||
c = tmp_buf + sizeof( tmp_buf );
|
||||
|
||||
ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
|
||||
|
||||
if( len )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
|
||||
OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
|
||||
|
||||
ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
|
||||
tmp_buf, c - tmp_buf ) );
|
||||
c -= pub_len;
|
||||
len += pub_len;
|
||||
|
||||
/*
|
||||
* Subject ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Prepare signature
|
||||
*/
|
||||
md( md_info_from_type( ctx->md_alg ), c, len, hash );
|
||||
|
||||
pk_alg = pk_get_type( ctx->key );
|
||||
if( pk_alg == POLARSSL_PK_ECKEY )
|
||||
pk_alg = POLARSSL_PK_ECDSA;
|
||||
|
||||
if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
|
||||
f_rng, p_rng ) ) != 0 ||
|
||||
( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
|
||||
&sig_oid, &sig_oid_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to output buffer
|
||||
*/
|
||||
c2 = buf + size;
|
||||
ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
|
||||
sig_oid, sig_oid_len, sig, sig_len ) );
|
||||
|
||||
c2 -= len;
|
||||
memcpy( c2, c, len );
|
||||
|
||||
len += sig_and_oid_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
|
||||
#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
unsigned char output_buf[4096];
|
||||
size_t olen = 0;
|
||||
|
||||
if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
|
||||
f_rng, p_rng ) ) < 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
|
||||
output_buf + sizeof(output_buf) - ret,
|
||||
ret, buf, size, &olen ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* POLARSSL_PEM_WRITE_C */
|
||||
|
||||
#endif /* POLARSSL_X509_CSR_WRITE_C */
|
|
@ -1,869 +0,0 @@
|
|||
/*
|
||||
* X509 buffer writing functionality
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* References:
|
||||
* - certificates: RFC 5280, updated by RFC 6818
|
||||
* - CSRs: PKCS#10 v1.7 aka RFC 2986
|
||||
* - attributes: PKCS#9 v2.0 aka RFC 2985
|
||||
*/
|
||||
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#if defined(POLARSSL_X509_WRITE_C)
|
||||
|
||||
#include "polarssl/asn1write.h"
|
||||
#include "polarssl/x509write.h"
|
||||
#include "polarssl/x509.h"
|
||||
#include "polarssl/md.h"
|
||||
#include "polarssl/oid.h"
|
||||
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
#include "polarssl/pem.h"
|
||||
#endif
|
||||
|
||||
#if defined(POLARSSL_MEMORY_C)
|
||||
#include "polarssl/memory.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define polarssl_malloc malloc
|
||||
#define polarssl_free free
|
||||
#endif
|
||||
|
||||
static int x509write_string_to_names( asn1_named_data **head, char *name )
|
||||
{
|
||||
int ret = 0;
|
||||
char *s = name, *c = s;
|
||||
char *end = s + strlen( s );
|
||||
char *oid = NULL;
|
||||
int in_tag = 1;
|
||||
asn1_named_data *cur;
|
||||
|
||||
/* Clear existing chain if present */
|
||||
asn1_free_named_data_list( head );
|
||||
|
||||
while( c <= end )
|
||||
{
|
||||
if( in_tag && *c == '=' )
|
||||
{
|
||||
if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_CN;
|
||||
else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_COUNTRY;
|
||||
else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_ORGANIZATION;
|
||||
else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_AT_LOCALITY;
|
||||
else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
|
||||
oid = OID_PKCS9_EMAIL;
|
||||
else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_ORG_UNIT;
|
||||
else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
|
||||
oid = OID_AT_STATE;
|
||||
else
|
||||
{
|
||||
ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
s = c + 1;
|
||||
in_tag = 0;
|
||||
}
|
||||
|
||||
if( !in_tag && ( *c == ',' || c == end ) )
|
||||
{
|
||||
if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
|
||||
(unsigned char *) s,
|
||||
c - s ) ) == NULL )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
while( c < end && *(c + 1) == ' ' )
|
||||
c++;
|
||||
|
||||
s = c + 1;
|
||||
in_tag = 1;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
void x509write_csr_init( x509write_csr *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof(x509write_csr) );
|
||||
}
|
||||
|
||||
void x509write_csr_free( x509write_csr *ctx )
|
||||
{
|
||||
asn1_free_named_data_list( &ctx->subject );
|
||||
asn1_free_named_data_list( &ctx->extensions );
|
||||
|
||||
memset( ctx, 0, sizeof(x509write_csr) );
|
||||
}
|
||||
|
||||
void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
|
||||
{
|
||||
ctx->md_alg = md_alg;
|
||||
}
|
||||
|
||||
void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
|
||||
{
|
||||
ctx->key = key;
|
||||
}
|
||||
|
||||
int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->subject, subject_name );
|
||||
}
|
||||
|
||||
/* The first byte of the value in the asn1_named_data structure is reserved
|
||||
* to store the critical boolean for us
|
||||
*/
|
||||
static int x509_set_extension( asn1_named_data **head,
|
||||
const char *oid, size_t oid_len,
|
||||
int critical,
|
||||
const unsigned char *val, size_t val_len )
|
||||
{
|
||||
asn1_named_data *cur;
|
||||
|
||||
if( ( cur = asn1_store_named_data( head, oid, oid_len,
|
||||
NULL, val_len + 1 ) ) == NULL )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
|
||||
}
|
||||
|
||||
cur->val.p[0] = critical;
|
||||
memcpy( cur->val.p + 1, val, val_len );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_csr_set_extension( x509write_csr *ctx,
|
||||
const char *oid, size_t oid_len,
|
||||
const unsigned char *val, size_t val_len )
|
||||
{
|
||||
return x509_set_extension( &ctx->extensions, oid, oid_len,
|
||||
0, val, val_len );
|
||||
}
|
||||
|
||||
int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
|
||||
OID_SIZE( OID_KEY_USAGE ),
|
||||
buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
|
||||
unsigned char ns_cert_type )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
|
||||
OID_SIZE( OID_NS_CERT_TYPE ),
|
||||
buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
void x509write_crt_init( x509write_cert *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof(x509write_cert) );
|
||||
|
||||
mpi_init( &ctx->serial );
|
||||
ctx->version = X509_CRT_VERSION_3;
|
||||
}
|
||||
|
||||
void x509write_crt_free( x509write_cert *ctx )
|
||||
{
|
||||
mpi_free( &ctx->serial );
|
||||
|
||||
asn1_free_named_data_list( &ctx->subject );
|
||||
asn1_free_named_data_list( &ctx->issuer );
|
||||
asn1_free_named_data_list( &ctx->extensions );
|
||||
|
||||
memset( ctx, 0, sizeof(x509write_csr) );
|
||||
}
|
||||
|
||||
void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
|
||||
{
|
||||
ctx->md_alg = md_alg;
|
||||
}
|
||||
|
||||
void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
|
||||
{
|
||||
ctx->subject_key = key;
|
||||
}
|
||||
|
||||
void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
|
||||
{
|
||||
ctx->issuer_key = key;
|
||||
}
|
||||
|
||||
int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->subject, subject_name );
|
||||
}
|
||||
|
||||
int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
|
||||
{
|
||||
return x509write_string_to_names( &ctx->issuer, issuer_name );
|
||||
}
|
||||
|
||||
int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
|
||||
char *not_after )
|
||||
{
|
||||
if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
|
||||
strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
|
||||
{
|
||||
return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
|
||||
}
|
||||
strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
|
||||
strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
|
||||
ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
|
||||
ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
return x509_set_extension( &ctx->extensions, oid, oid_len,
|
||||
critical, val, val_len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_basic_constraints( x509write_cert *ctx,
|
||||
int is_ca, int max_pathlen )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[9];
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf) );
|
||||
|
||||
if( is_ca && max_pathlen > 127 )
|
||||
return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
|
||||
|
||||
if( is_ca )
|
||||
{
|
||||
if( max_pathlen >= 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
|
||||
}
|
||||
ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
|
||||
OID_SIZE( OID_BASIC_CONSTRAINTS ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf));
|
||||
ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
|
||||
|
||||
sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
|
||||
c = buf + sizeof(buf) - 20;
|
||||
len = 20;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
|
||||
OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
|
||||
unsigned char *c = buf + sizeof(buf);
|
||||
size_t len = 0;
|
||||
|
||||
memset( buf, 0, sizeof(buf));
|
||||
ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
|
||||
|
||||
sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
|
||||
c = buf + sizeof(buf) - 20;
|
||||
len = 20;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
|
||||
OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
|
||||
0, buf + sizeof(buf) - len, len );
|
||||
}
|
||||
|
||||
int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
|
||||
OID_SIZE( OID_KEY_USAGE ),
|
||||
1, buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
|
||||
unsigned char ns_cert_type )
|
||||
{
|
||||
unsigned char buf[4];
|
||||
unsigned char *c;
|
||||
int ret;
|
||||
|
||||
c = buf + 4;
|
||||
|
||||
if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
||||
return( ret );
|
||||
|
||||
ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
|
||||
OID_SIZE( OID_NS_CERT_TYPE ),
|
||||
0, buf, 4 );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* RelativeDistinguishedName ::=
|
||||
* SET OF AttributeTypeAndValue
|
||||
*
|
||||
* AttributeTypeAndValue ::= SEQUENCE {
|
||||
* type AttributeType,
|
||||
* value AttributeValue }
|
||||
*
|
||||
* AttributeType ::= OBJECT IDENTIFIER
|
||||
*
|
||||
* AttributeValue ::= ANY DEFINED BY AttributeType
|
||||
*/
|
||||
static int x509_write_name( unsigned char **p, unsigned char *start,
|
||||
const char *oid, size_t oid_len,
|
||||
const unsigned char *name, size_t name_len )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
// Write PrintableString for all except OID_PKCS9_EMAIL
|
||||
//
|
||||
if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
|
||||
memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
|
||||
(const char *) name,
|
||||
name_len ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
|
||||
(const char *) name,
|
||||
name_len ) );
|
||||
}
|
||||
|
||||
// Write OID
|
||||
//
|
||||
ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
static int x509_write_names( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *first )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
asn1_named_data *cur = first;
|
||||
|
||||
while( cur != NULL )
|
||||
{
|
||||
ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
|
||||
cur->oid.len,
|
||||
cur->val.p, cur->val.len ) );
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
static int x509_write_sig( unsigned char **p, unsigned char *start,
|
||||
const char *oid, size_t oid_len,
|
||||
unsigned char *sig, size_t size )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
if( *p - start < (int) size + 1 )
|
||||
return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
len = size;
|
||||
(*p) -= len;
|
||||
memcpy( *p, sig, len );
|
||||
|
||||
*--(*p) = 0;
|
||||
len += 1;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
|
||||
|
||||
// Write OID
|
||||
//
|
||||
ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
|
||||
oid_len, 0 ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
static int x509_write_time( unsigned char **p, unsigned char *start,
|
||||
const char *time, size_t size )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
/*
|
||||
* write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
|
||||
*/
|
||||
if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) time + 2,
|
||||
size - 2 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) time,
|
||||
size ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
|
||||
}
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
static int x509_write_extension( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *ext )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
|
||||
ext->val.len - 1 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
|
||||
|
||||
if( ext->val.p[0] != 0 )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
|
||||
ext->oid.len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* }
|
||||
*/
|
||||
static int x509_write_extensions( unsigned char **p, unsigned char *start,
|
||||
asn1_named_data *first )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
asn1_named_data *cur_ext = first;
|
||||
|
||||
while( cur_ext != NULL )
|
||||
{
|
||||
ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
|
||||
cur_ext = cur_ext->next;
|
||||
}
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
const char *sig_oid;
|
||||
size_t sig_oid_len = 0;
|
||||
unsigned char *c, *c2;
|
||||
unsigned char hash[64];
|
||||
unsigned char sig[POLARSSL_MPI_MAX_SIZE];
|
||||
unsigned char tmp_buf[2048];
|
||||
size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
|
||||
size_t len = 0;
|
||||
pk_type_t pk_alg;
|
||||
|
||||
/*
|
||||
* Prepare data to be signed in tmp_buf
|
||||
*/
|
||||
c = tmp_buf + sizeof( tmp_buf );
|
||||
|
||||
ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
|
||||
|
||||
if( len )
|
||||
{
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
|
||||
OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
}
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
|
||||
|
||||
ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
|
||||
tmp_buf, c - tmp_buf ) );
|
||||
c -= pub_len;
|
||||
len += pub_len;
|
||||
|
||||
/*
|
||||
* Subject ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Prepare signature
|
||||
*/
|
||||
md( md_info_from_type( ctx->md_alg ), c, len, hash );
|
||||
|
||||
pk_alg = pk_get_type( ctx->key );
|
||||
if( pk_alg == POLARSSL_PK_ECKEY )
|
||||
pk_alg = POLARSSL_PK_ECDSA;
|
||||
|
||||
if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
|
||||
f_rng, p_rng ) ) != 0 ||
|
||||
( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
|
||||
&sig_oid, &sig_oid_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to output buffer
|
||||
*/
|
||||
c2 = buf + size;
|
||||
ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
|
||||
sig_oid, sig_oid_len, sig, sig_len ) );
|
||||
|
||||
c2 -= len;
|
||||
memcpy( c2, c, len );
|
||||
|
||||
len += sig_and_oid_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
const char *sig_oid;
|
||||
size_t sig_oid_len = 0;
|
||||
unsigned char *c, *c2;
|
||||
unsigned char hash[64];
|
||||
unsigned char sig[POLARSSL_MPI_MAX_SIZE];
|
||||
unsigned char tmp_buf[2048];
|
||||
size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
|
||||
size_t len = 0;
|
||||
pk_type_t pk_alg;
|
||||
|
||||
/*
|
||||
* Prepare data to be signed in tmp_buf
|
||||
*/
|
||||
c = tmp_buf + sizeof( tmp_buf );
|
||||
|
||||
/* Signature algorithm needed in TBS, and later for actual signature */
|
||||
pk_alg = pk_get_type( ctx->issuer_key );
|
||||
if( pk_alg == POLARSSL_PK_ECKEY )
|
||||
pk_alg = POLARSSL_PK_ECDSA;
|
||||
|
||||
if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
|
||||
&sig_oid, &sig_oid_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
|
||||
|
||||
/*
|
||||
* SubjectPublicKeyInfo
|
||||
*/
|
||||
ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
|
||||
tmp_buf, c - tmp_buf ) );
|
||||
c -= pub_len;
|
||||
len += pub_len;
|
||||
|
||||
/*
|
||||
* Subject ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
|
||||
|
||||
/*
|
||||
* Validity ::= SEQUENCE {
|
||||
* notBefore Time,
|
||||
* notAfter Time }
|
||||
*/
|
||||
sub_len = 0;
|
||||
|
||||
ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
|
||||
X509_RFC5280_UTC_TIME_LEN ) );
|
||||
|
||||
ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
|
||||
X509_RFC5280_UTC_TIME_LEN ) );
|
||||
|
||||
len += sub_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Issuer ::= Name
|
||||
*/
|
||||
ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
|
||||
|
||||
/*
|
||||
* Signature ::= AlgorithmIdentifier
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
|
||||
sig_oid, strlen( sig_oid ), 0 ) );
|
||||
|
||||
/*
|
||||
* Serial ::= INTEGER
|
||||
*/
|
||||
ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
|
||||
*/
|
||||
sub_len = 0;
|
||||
ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
|
||||
len += sub_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
/*
|
||||
* Make signature
|
||||
*/
|
||||
md( md_info_from_type( ctx->md_alg ), c, len, hash );
|
||||
|
||||
if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
|
||||
f_rng, p_rng ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to output buffer
|
||||
*/
|
||||
c2 = buf + size;
|
||||
ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
|
||||
sig_oid, sig_oid_len, sig, sig_len ) );
|
||||
|
||||
c2 -= len;
|
||||
memcpy( c2, c, len );
|
||||
|
||||
len += sig_and_oid_len;
|
||||
ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
|
||||
#define PEM_END_CRT "-----END CERTIFICATE-----\n"
|
||||
|
||||
#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
|
||||
#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
|
||||
|
||||
#if defined(POLARSSL_PEM_WRITE_C)
|
||||
int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
unsigned char output_buf[4096];
|
||||
size_t olen = 0;
|
||||
|
||||
if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
|
||||
f_rng, p_rng ) ) < 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
|
||||
output_buf + sizeof(output_buf) - ret,
|
||||
ret, buf, size, &olen ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
unsigned char output_buf[4096];
|
||||
size_t olen = 0;
|
||||
|
||||
if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
|
||||
f_rng, p_rng ) ) < 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
|
||||
output_buf + sizeof(output_buf) - ret,
|
||||
ret, buf, size, &olen ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* POLARSSL_BASE64_C */
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue