mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-11-04 04:32:24 -05:00 
			
		
		
		
	- Added CRL revocation support to x509parse_verify()
- Fixed an off-by-one allocation in ssl_set_hostname() - Added CRL support to SSL/TLS code
This commit is contained in:
		
							parent
							
								
									7d06ad2b52
								
							
						
					
					
						commit
						40ea7de46d
					
				@ -18,6 +18,10 @@ PolarSSL ChangeLog
 | 
			
		||||
     systems (Found by Gernot).
 | 
			
		||||
   * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in
 | 
			
		||||
     padlock and timing code. 
 | 
			
		||||
   * Fixed an off-by-one buffer allocation in ssl_set_hostname().
 | 
			
		||||
   * Added support for Certificate Revocation List (CRL parsing.
 | 
			
		||||
   * Added support for CRL revocation to x509parse_verify() and
 | 
			
		||||
     SSL/TLS code.
 | 
			
		||||
 | 
			
		||||
= Version 0.10.0 released on 2009-01-12
 | 
			
		||||
   * Migrated XySSL to PolarSSL
 | 
			
		||||
 | 
			
		||||
@ -235,6 +235,7 @@ struct _ssl_context
 | 
			
		||||
    rsa_context *rsa_key;               /*!<  own RSA private key     */
 | 
			
		||||
    x509_cert *own_cert;                /*!<  own X.509 certificate   */
 | 
			
		||||
    x509_cert *ca_chain;                /*!<  own trusted CA chain    */
 | 
			
		||||
    x509_crl *ca_crl;                   /*!<  trusted CA CRLs         */
 | 
			
		||||
    x509_cert *peer_cert;               /*!<  peer X.509 cert chain   */
 | 
			
		||||
    char *peer_cn;                      /*!<  expected peer CN        */
 | 
			
		||||
 | 
			
		||||
@ -389,12 +390,13 @@ void ssl_set_ciphers( ssl_context *ssl, int *ciphers );
 | 
			
		||||
 *
 | 
			
		||||
 * \param ssl      SSL context
 | 
			
		||||
 * \param ca_chain trusted CA chain
 | 
			
		||||
 * \param ca_crl   trusted CA CRLs
 | 
			
		||||
 * \param peer_cn  expected peer CommonName (or NULL)
 | 
			
		||||
 *
 | 
			
		||||
 * \note           TODO: add two more parameters: depth and crl
 | 
			
		||||
 */
 | 
			
		||||
void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
 | 
			
		||||
                       char *peer_cn );
 | 
			
		||||
                       x509_crl *ca_crl, char *peer_cn );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief          Set own certificate and private key
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,8 @@
 | 
			
		||||
#define BADCERT_REVOKED                 2
 | 
			
		||||
#define BADCERT_CN_MISMATCH             4
 | 
			
		||||
#define BADCERT_NOT_TRUSTED             8
 | 
			
		||||
#define BADCRL_NOT_TRUSTED             16
 | 
			
		||||
#define BADCRL_EXPIRED                 32
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DER constants
 | 
			
		||||
@ -335,16 +337,17 @@ int x509parse_cert_info( char *buf, size_t size, char *prefix, x509_cert *crt );
 | 
			
		||||
int x509parse_crl_info( char *buf, size_t size, char *prefix, x509_crl *crl );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief          Return 0 if the certificate is still valid,
 | 
			
		||||
 *                 or BADCERT_EXPIRED
 | 
			
		||||
 * \brief          Return 0 if the x509_time is still valid,
 | 
			
		||||
 *                 or 1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int x509parse_expired( x509_cert *crt );
 | 
			
		||||
int x509parse_time_expired( x509_time *time );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief          Verify the certificate signature
 | 
			
		||||
 *
 | 
			
		||||
 * \param crt      a certificate to be verified
 | 
			
		||||
 * \param trust_ca the trusted CA chain
 | 
			
		||||
 * \param ca_crl   the CRL chain for trusted CA's
 | 
			
		||||
 * \param cn       expected Common Name (can be set to
 | 
			
		||||
 *                 NULL if the CN must not be verified)
 | 
			
		||||
 * \param flags    result of the verification
 | 
			
		||||
@ -361,6 +364,7 @@ int x509parse_expired( x509_cert *crt );
 | 
			
		||||
 */
 | 
			
		||||
int x509parse_verify( x509_cert *crt,
 | 
			
		||||
                      x509_cert *trust_ca,
 | 
			
		||||
                      x509_crl *ca_crl,
 | 
			
		||||
                      char *cn, int *flags );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -1332,7 +1332,7 @@ int ssl_parse_certificate( ssl_context *ssl )
 | 
			
		||||
            return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain,
 | 
			
		||||
        ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl,
 | 
			
		||||
                                ssl->peer_cn,  &ssl->verify_result );
 | 
			
		||||
 | 
			
		||||
        if( ret != 0 )
 | 
			
		||||
@ -1702,9 +1702,10 @@ void ssl_set_ciphers( ssl_context *ssl, int *ciphers )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
 | 
			
		||||
                       char *peer_cn )
 | 
			
		||||
                       x509_crl *ca_crl, char *peer_cn )
 | 
			
		||||
{
 | 
			
		||||
    ssl->ca_chain   = ca_chain;
 | 
			
		||||
    ssl->ca_crl     = ca_crl;
 | 
			
		||||
    ssl->peer_cn    = peer_cn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1740,11 +1741,13 @@ int ssl_set_hostname( ssl_context *ssl, char *hostname )
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 | 
			
		||||
 | 
			
		||||
    ssl->hostname_len = strlen( hostname );
 | 
			
		||||
    ssl->hostname = (unsigned char *) malloc( ssl->hostname_len );
 | 
			
		||||
    ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 );
 | 
			
		||||
 | 
			
		||||
    memcpy( ssl->hostname, (unsigned char *) hostname,
 | 
			
		||||
            ssl->hostname_len );
 | 
			
		||||
    
 | 
			
		||||
    ssl->hostname[ssl->hostname_len] = '\0';
 | 
			
		||||
 | 
			
		||||
    return( 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2068,9 +2068,9 @@ int x509parse_crl_info( char *buf, size_t size, char *prefix, x509_crl *crl )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
 | 
			
		||||
 * Return 0 if the x509_time is still valid, or 1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int x509parse_expired( x509_cert *crt )
 | 
			
		||||
int x509parse_time_expired( x509_time *to )
 | 
			
		||||
{
 | 
			
		||||
    struct tm *lt;
 | 
			
		||||
    time_t tt;
 | 
			
		||||
@ -2078,17 +2078,38 @@ int x509parse_expired( x509_cert *crt )
 | 
			
		||||
    tt = time( NULL );
 | 
			
		||||
    lt = localtime( &tt );
 | 
			
		||||
 | 
			
		||||
    if( lt->tm_year  > crt->valid_to.year - 1900 )
 | 
			
		||||
        return( BADCERT_EXPIRED );
 | 
			
		||||
    if( lt->tm_year  > to->year - 1900 )
 | 
			
		||||
        return( 1 );
 | 
			
		||||
 | 
			
		||||
    if( lt->tm_year == crt->valid_to.year - 1900 &&
 | 
			
		||||
        lt->tm_mon   > crt->valid_to.mon  - 1 )
 | 
			
		||||
        return( BADCERT_EXPIRED );
 | 
			
		||||
    if( lt->tm_year == to->year - 1900 &&
 | 
			
		||||
        lt->tm_mon   > to->mon  - 1 )
 | 
			
		||||
        return( 1 );
 | 
			
		||||
 | 
			
		||||
    if( lt->tm_year == crt->valid_to.year - 1900 &&
 | 
			
		||||
        lt->tm_mon  == crt->valid_to.mon  - 1    &&
 | 
			
		||||
        lt->tm_mday  > crt->valid_to.day )
 | 
			
		||||
        return( BADCERT_EXPIRED );
 | 
			
		||||
    if( lt->tm_year == to->year - 1900 &&
 | 
			
		||||
        lt->tm_mon  == to->mon  - 1    &&
 | 
			
		||||
        lt->tm_mday  > to->day )
 | 
			
		||||
        return( 1 );
 | 
			
		||||
 | 
			
		||||
    return( 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return 1 if the certificate is revoked, or 0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int x509parse_revoked( x509_cert *crt, x509_crl *crl )
 | 
			
		||||
{
 | 
			
		||||
    x509_crl_entry *cur = &crl->entry;
 | 
			
		||||
 | 
			
		||||
    while( cur != NULL && cur->serial.len != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        if( memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
 | 
			
		||||
        {
 | 
			
		||||
            if( x509parse_time_expired( &cur->revocation_date ) )
 | 
			
		||||
                return( 1 );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        cur = cur->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return( 0 );
 | 
			
		||||
}
 | 
			
		||||
@ -2125,6 +2146,7 @@ static void x509_hash( unsigned char *in, int len, int alg,
 | 
			
		||||
 */
 | 
			
		||||
int x509parse_verify( x509_cert *crt,
 | 
			
		||||
                      x509_cert *trust_ca,
 | 
			
		||||
                      x509_crl *ca_crl,
 | 
			
		||||
                      char *cn, int *flags )
 | 
			
		||||
{
 | 
			
		||||
    int cn_len;
 | 
			
		||||
@ -2134,7 +2156,10 @@ int x509parse_verify( x509_cert *crt,
 | 
			
		||||
    x509_name *name;
 | 
			
		||||
    unsigned char hash[64];
 | 
			
		||||
 | 
			
		||||
    *flags = x509parse_expired( crt );
 | 
			
		||||
    *flags = 0;
 | 
			
		||||
 | 
			
		||||
    if( x509parse_time_expired( &crt->valid_to ) )
 | 
			
		||||
        *flags = BADCERT_EXPIRED;
 | 
			
		||||
 | 
			
		||||
    if( cn != NULL )
 | 
			
		||||
    {
 | 
			
		||||
@ -2224,6 +2249,61 @@ int x509parse_verify( x509_cert *crt,
 | 
			
		||||
        trust_ca = trust_ca->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * TODO: What happens if no CRL is present?
 | 
			
		||||
     * Suggestion: Revocation state should be unknown if no CRL is present.
 | 
			
		||||
     * For backwards compatibility this is not yet implemented.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Check if the topmost certificate is revoked if the trusted CA is
 | 
			
		||||
     * determined.
 | 
			
		||||
     */
 | 
			
		||||
    while( trust_ca != NULL && ca_crl != NULL && ca_crl->version != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        if( ca_crl->issuer_raw.len != trust_ca->subject_raw.len ||
 | 
			
		||||
            memcmp( ca_crl->issuer_raw.p, trust_ca->subject_raw.p,
 | 
			
		||||
                    ca_crl->issuer_raw.len ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            ca_crl = ca_crl->next;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Check if CRL is correctry signed by the trusted CA
 | 
			
		||||
         */
 | 
			
		||||
        hash_id = ca_crl->sig_oid1.p[8];
 | 
			
		||||
 | 
			
		||||
        x509_hash( ca_crl->tbs.p, ca_crl->tbs.len, hash_id, hash );
 | 
			
		||||
 | 
			
		||||
        if( !rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
 | 
			
		||||
                              0, hash, ca_crl->sig.p ) == 0 )
 | 
			
		||||
        {
 | 
			
		||||
            /*
 | 
			
		||||
             * CRL is not trusted
 | 
			
		||||
             */
 | 
			
		||||
            *flags |= BADCRL_NOT_TRUSTED;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Check for validity of CRL (Do not drop out)
 | 
			
		||||
         */
 | 
			
		||||
        if( x509parse_time_expired( &ca_crl->next_update ) )
 | 
			
		||||
            *flags |= BADCRL_EXPIRED;
 | 
			
		||||
        
 | 
			
		||||
        /*
 | 
			
		||||
         * Check if certificate is revoked
 | 
			
		||||
         */
 | 
			
		||||
        if( x509parse_revoked(crt, ca_crl) )
 | 
			
		||||
        {
 | 
			
		||||
            *flags |= BADCERT_REVOKED;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ca_crl = ca_crl->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( *flags != 0 )
 | 
			
		||||
        return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
 | 
			
		||||
 | 
			
		||||
@ -2406,7 +2486,7 @@ int x509_self_test( int verbose )
 | 
			
		||||
    if( verbose != 0 )
 | 
			
		||||
        printf( "passed\n  X.509 signature verify: ");
 | 
			
		||||
 | 
			
		||||
    ret = x509parse_verify( &clicert, &cacert, "Joe User", &i );
 | 
			
		||||
    ret = x509parse_verify( &clicert, &cacert, NULL, "Joe User", &i );
 | 
			
		||||
    if( ret != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        if( verbose != 0 )
 | 
			
		||||
 | 
			
		||||
@ -158,7 +158,7 @@ int main( void )
 | 
			
		||||
    ssl_set_ciphers( &ssl, ssl_default_ciphers );
 | 
			
		||||
    ssl_set_session( &ssl, 1, 600, &ssn );
 | 
			
		||||
 | 
			
		||||
    ssl_set_ca_chain( &ssl, &cacert, SERVER_NAME );
 | 
			
		||||
    ssl_set_ca_chain( &ssl, &cacert, NULL, SERVER_NAME );
 | 
			
		||||
    ssl_set_own_cert( &ssl, &clicert, &rsa );
 | 
			
		||||
 | 
			
		||||
    ssl_set_hostname( &ssl, SERVER_NAME );
 | 
			
		||||
 | 
			
		||||
@ -286,7 +286,7 @@ accept:
 | 
			
		||||
 | 
			
		||||
    memset( &ssn, 0, sizeof( ssl_session ) );
 | 
			
		||||
 | 
			
		||||
    ssl_set_ca_chain( &ssl, srvcert.next, NULL );
 | 
			
		||||
    ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
 | 
			
		||||
    ssl_set_own_cert( &ssl, &srvcert, &rsa );
 | 
			
		||||
    ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -32,12 +32,14 @@
 | 
			
		||||
#define snprintf _snprintf
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MAX_CLIENT_CERTS    6
 | 
			
		||||
#define MAX_CLIENT_CERTS    8
 | 
			
		||||
 | 
			
		||||
char *client_certificates[MAX_CLIENT_CERTS] =
 | 
			
		||||
{
 | 
			
		||||
    "client1.crt",
 | 
			
		||||
    "client2.crt",
 | 
			
		||||
    "server1.crt",
 | 
			
		||||
    "server2.crt",
 | 
			
		||||
    "cert_sha224.crt",
 | 
			
		||||
    "cert_sha256.crt",
 | 
			
		||||
    "cert_sha384.crt",
 | 
			
		||||
@ -48,6 +50,8 @@ char *client_private_keys[MAX_CLIENT_CERTS] =
 | 
			
		||||
{
 | 
			
		||||
    "client1.key",
 | 
			
		||||
    "client2.key",
 | 
			
		||||
    "server1.key",
 | 
			
		||||
    "server2.key",
 | 
			
		||||
    "cert_sha224.key",
 | 
			
		||||
    "cert_sha256.key",
 | 
			
		||||
    "cert_sha384.key",
 | 
			
		||||
@ -83,6 +87,9 @@ int main( void )
 | 
			
		||||
 | 
			
		||||
    printf( " ok\n" );
 | 
			
		||||
 | 
			
		||||
    x509parse_cert_info( buf, 1024, "CRT: ", &cacert );
 | 
			
		||||
    printf("%s\n", buf );
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * 1.2. Load the CRL
 | 
			
		||||
     */
 | 
			
		||||
@ -134,12 +141,18 @@ int main( void )
 | 
			
		||||
        printf( "  . Verify the client certificate with CA certificate..." );
 | 
			
		||||
        fflush( stdout );
 | 
			
		||||
 | 
			
		||||
        ret = x509parse_verify( &clicert, &cacert, NULL, &flags );
 | 
			
		||||
        ret = x509parse_verify( &clicert, &cacert, &crl, NULL, &flags );
 | 
			
		||||
        if( ret != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED )
 | 
			
		||||
            {
 | 
			
		||||
                if( flags == BADCERT_REVOKED )
 | 
			
		||||
                    printf( " REVOKED " );
 | 
			
		||||
            } else {
 | 
			
		||||
                printf( " failed\n  !  x509parse_verify returned %d\n\n", ret );
 | 
			
		||||
                goto exit;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        printf( " ok\n" );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -225,7 +225,7 @@ static int ssl_test( struct options *opt )
 | 
			
		||||
 | 
			
		||||
        ssl_set_endpoint( &ssl, SSL_IS_SERVER );
 | 
			
		||||
        ssl_set_dh_param( &ssl, dhm_P, dhm_G );
 | 
			
		||||
        ssl_set_ca_chain( &ssl, srvcert.next, NULL );
 | 
			
		||||
        ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
 | 
			
		||||
        ssl_set_own_cert( &ssl, &srvcert, &rsa );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user