/* * check peer cert against CRL */ result_t x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; if (x509parse_crlfile(&crl, crl_file) != 0) { msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); goto end; } if(cert->issuer_raw.len != crl.issuer_raw.len || memcmp(crl.issuer_raw.p, cert->issuer_raw.p, crl.issuer_raw.len) != 0) { msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of " "certificate %s", crl_file, subject); retval = SUCCESS; goto end; } if (0 != x509parse_revoked(cert, &crl)) { msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject); goto end; } retval = SUCCESS; msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); end: x509_crl_free(&crl); return retval; }
void Curl_polarssl_close(struct connectdata *conn, int sockindex) { rsa_free(&conn->ssl[sockindex].rsa); x509_free(&conn->ssl[sockindex].clicert); x509_free(&conn->ssl[sockindex].cacert); x509_crl_free(&conn->ssl[sockindex].crl); ssl_free(&conn->ssl[sockindex].ssl); }
static void Curl_polarssl_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; rsa_free(&BACKEND->rsa); x509_crt_free(&BACKEND->clicert); x509_crt_free(&BACKEND->cacert); x509_crl_free(&BACKEND->crl); ssl_free(&BACKEND->ssl); }
/* * check peer cert against CRL */ result_t x509_verify_crl(const char *crl_file, const char* crl_inline, x509_crt *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; struct gc_arena gc = gc_new(); char *serial; if (!strcmp (crl_file, INLINE_FILE_TAG) && crl_inline) { if (!polar_ok(x509_crl_parse(&crl, crl_inline, strlen(crl_inline)))) { msg (M_WARN, "CRL: cannot parse inline CRL"); goto end; } } else { if (!polar_ok(x509_crl_parse_file(&crl, crl_file))) { msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file); goto end; } } if(cert->issuer_raw.len != crl.issuer_raw.len || memcmp(crl.issuer_raw.p, cert->issuer_raw.p, crl.issuer_raw.len) != 0) { msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of " "certificate %s", crl_file, subject); retval = SUCCESS; goto end; } if (!polar_ok(x509_crt_revoked(cert, &crl))) { serial = backend_x509_get_serial_hex(cert, &gc); msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject, (serial ? serial : "NOT AVAILABLE")); goto end; } retval = SUCCESS; msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); end: gc_free(&gc); x509_crl_free(&crl); return retval; }
/* * check peer cert against CRL */ result_t x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; struct gc_arena gc = gc_new(); char *serial; int polar_retval = x509_crl_parse_file(&crl, crl_file); if (polar_retval != 0) { char errstr[128]; polarssl_strerror(polar_retval, errstr, sizeof(errstr)); msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr); goto end; } if(cert->issuer_raw.len != crl.issuer_raw.len || memcmp(crl.issuer_raw.p, cert->issuer_raw.p, crl.issuer_raw.len) != 0) { msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of " "certificate %s", crl_file, subject); retval = SUCCESS; goto end; } if (0 != x509_crt_revoked(cert, &crl)) { serial = backend_x509_get_serial_hex(cert, &gc); msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject, (serial ? serial : "NOT AVAILABLE")); goto end; } retval = SUCCESS; msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); end: gc_free(&gc); x509_crl_free(&crl); return retval; }
void ngx_ssl_cleanup_ctx(void *data) { ngx_ssl_t *ssl = data; if (ssl->ciphersuites != NULL) { ngx_free(ssl->ciphersuites); } dhm_free(&ssl->dhm_ctx); if (ssl->have_own_cert) { x509_free(&ssl->own_cert); rsa_free(&ssl->own_key); } if (ssl->have_ca_cert) { x509_free(&ssl->ca_cert); } if (ssl->have_ca_crl) { x509_crl_free(&ssl->ca_crl); } }
int main( int argc, char *argv[] ) { int ret = 0; unsigned char buf[1024]; x509_crl crl; int i, j, n; char *p, *q; /* * Set to sane values */ memset( &crl, 0, sizeof( x509_crl ) ); if( argc == 0 ) { usage: printf( USAGE ); goto exit; } opt.filename = DFL_FILENAME; opt.debug_level = DFL_DEBUG_LEVEL; for( i = 1; i < argc; i++ ) { n = strlen( argv[i] ); for( j = 0; j < n; j++ ) { if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) argv[i][j] |= 0x20; } p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } else goto usage; } /* * 1.1. Load the CRL */ printf( "\n . Loading the CRL ..." ); fflush( stdout ); ret = x509parse_crlfile( &crl, opt.filename ); if( ret != 0 ) { printf( " failed\n ! x509parse_crl returned %d\n\n", ret ); x509_crl_free( &crl ); goto exit; } printf( " ok\n" ); /* * 1.2 Print the CRL */ printf( " . CRL information ...\n" ); ret = x509parse_crl_info( (char *) buf, sizeof( buf ) - 1, " ", &crl ); if( ret == -1 ) { printf( " failed\n ! x509parse_crl_info returned %d\n\n", ret ); x509_crl_free( &crl ); goto exit; } printf( "%s\n", buf ); exit: x509_crl_free( &crl ); #ifdef WIN32 printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Parse one CRLs in DER format and append it to the chained list */ int x509_crl_parse_der( x509_crl *chain, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; x509_buf sig_params1, sig_params2; x509_crl *crl = chain; /* * Check for valid input */ if( crl == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); memset( &sig_params1, 0, sizeof( x509_buf ) ); memset( &sig_params2, 0, sizeof( x509_buf ) ); /* * Add new CRL on the end of the chain if needed. */ while( crl->version != 0 && crl->next != NULL ) crl = crl->next; if( crl->version != 0 && crl->next == NULL ) { crl->next = polarssl_malloc( sizeof( x509_crl ) ); if( crl->next == NULL ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_MALLOC_FAILED ); } x509_crl_init( crl->next ); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if( ( p = polarssl_malloc( buflen ) ) == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memcpy( p, buf, buflen ); crl->raw.p = p; crl->raw.len = buflen; end = p + buflen; /* * 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_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_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_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( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } crl->version++; if( crl->version > 2 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); } if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_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_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_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && ret != ( POLARSSL_ERR_X509_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_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 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 || sig_params1.len != sig_params2.len || ( sig_params1.len != 0 && memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_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_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }
int main( int argc, char *argv[] ) { int ret = 0; unsigned char buf[100000]; x509_crl crl; int i; char *p, *q; /* * Set to sane values */ x509_crl_init( &crl ); if( argc == 0 ) { usage: polarssl_printf( USAGE ); goto exit; } opt.filename = DFL_FILENAME; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else goto usage; } /* * 1.1. Load the CRL */ polarssl_printf( "\n . Loading the CRL ..." ); fflush( stdout ); ret = x509_crl_parse_file( &crl, opt.filename ); if( ret != 0 ) { polarssl_printf( " failed\n ! x509_crl_parse_file returned %d\n\n", ret ); x509_crl_free( &crl ); goto exit; } polarssl_printf( " ok\n" ); /* * 1.2 Print the CRL */ polarssl_printf( " . CRL information ...\n" ); ret = x509_crl_info( (char *) buf, sizeof( buf ) - 1, " ", &crl ); if( ret == -1 ) { polarssl_printf( " failed\n ! x509_crl_info returned %d\n\n", ret ); x509_crl_free( &crl ); goto exit; } polarssl_printf( "%s\n", buf ); exit: x509_crl_free( &crl ); #if defined(_WIN32) polarssl_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { int ret = 0, server_fd; unsigned char buf[1024]; entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; x509_crt cacert; x509_crt clicert; x509_crl cacrl; pk_context pkey; int i, j; int flags, verify = 0; char *p, *q; const char *pers = "cert_app"; /* * Set to sane values */ server_fd = 0; x509_crt_init( &cacert ); x509_crt_init( &clicert ); #if defined(POLARSSL_X509_CRL_PARSE_C) x509_crl_init( &cacrl ); #else /* Zeroize structure as CRL parsing is not supported and we have to pass it to the verify function */ memset( &cacrl, 0, sizeof(x509_crl) ); #endif pk_init( &pkey ); if( argc == 0 ) { usage: polarssl_printf( USAGE ); ret = 2; goto exit; } opt.mode = DFL_MODE; opt.filename = DFL_FILENAME; opt.ca_file = DFL_CA_FILE; opt.crl_file = DFL_CRL_FILE; opt.ca_path = DFL_CA_PATH; opt.server_name = DFL_SERVER_NAME; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; opt.permissive = DFL_PERMISSIVE; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; for( j = 0; p + j < q; j++ ) { if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) argv[i][j] |= 0x20; } if( strcmp( p, "mode" ) == 0 ) { if( strcmp( q, "file" ) == 0 ) opt.mode = MODE_FILE; else if( strcmp( q, "ssl" ) == 0 ) opt.mode = MODE_SSL; else goto usage; } else if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "ca_file" ) == 0 ) opt.ca_file = q; else if( strcmp( p, "crl_file" ) == 0 ) opt.crl_file = q; else if( strcmp( p, "ca_path" ) == 0 ) opt.ca_path = q; else if( strcmp( p, "server_name" ) == 0 ) opt.server_name = q; else if( strcmp( p, "server_port" ) == 0 ) { opt.server_port = atoi( q ); if( opt.server_port < 1 || opt.server_port > 65535 ) goto usage; } else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } else if( strcmp( p, "permissive" ) == 0 ) { opt.permissive = atoi( q ); if( opt.permissive < 0 || opt.permissive > 1 ) goto usage; } else goto usage; } /* * 1.1. Load the trusted CA */ polarssl_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); if( strlen( opt.ca_path ) ) { ret = x509_crt_parse_path( &cacert, opt.ca_path ); verify = 1; } else if( strlen( opt.ca_file ) ) { ret = x509_crt_parse_file( &cacert, opt.ca_file ); verify = 1; } if( ret < 0 ) { polarssl_printf( " failed\n ! x509_crt_parse returned -0x%x\n\n", -ret ); goto exit; } polarssl_printf( " ok (%d skipped)\n", ret ); #if defined(POLARSSL_X509_CRL_PARSE_C) if( strlen( opt.crl_file ) ) { if( ( ret = x509_crl_parse_file( &cacrl, opt.crl_file ) ) != 0 ) { polarssl_printf( " failed\n ! x509_crl_parse returned -0x%x\n\n", -ret ); goto exit; } verify = 1; } #endif if( opt.mode == MODE_FILE ) { x509_crt crt; x509_crt *cur = &crt; x509_crt_init( &crt ); /* * 1.1. Load the certificate(s) */ polarssl_printf( "\n . Loading the certificate(s) ..." ); fflush( stdout ); ret = x509_crt_parse_file( &crt, opt.filename ); if( ret < 0 ) { polarssl_printf( " failed\n ! x509_crt_parse_file returned %d\n\n", ret ); x509_crt_free( &crt ); goto exit; } if( opt.permissive == 0 && ret > 0 ) { polarssl_printf( " failed\n ! x509_crt_parse failed to parse %d certificates\n\n", ret ); x509_crt_free( &crt ); goto exit; } polarssl_printf( " ok\n" ); /* * 1.2 Print the certificate(s) */ while( cur != NULL ) { polarssl_printf( " . Peer certificate information ...\n" ); ret = x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", cur ); if( ret == -1 ) { polarssl_printf( " failed\n ! x509_crt_info returned %d\n\n", ret ); x509_crt_free( &crt ); goto exit; } polarssl_printf( "%s\n", buf ); cur = cur->next; } /* * 1.3 Verify the certificate */ if( verify ) { polarssl_printf( " . Verifying X.509 certificate..." ); if( ( ret = x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags, my_verify, NULL ) ) != 0 ) { polarssl_printf( " failed\n" ); if( ( ret & BADCERT_EXPIRED ) != 0 ) polarssl_printf( " ! server certificate has expired\n" ); if( ( ret & BADCERT_REVOKED ) != 0 ) polarssl_printf( " ! server certificate has been revoked\n" ); if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) polarssl_printf( " ! CN mismatch (expected CN=%s)\n", opt.server_name ); if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); polarssl_printf( "\n" ); } else polarssl_printf( " ok\n" ); } x509_crt_free( &crt ); } else if( opt.mode == MODE_SSL ) { /* * 1. Initialize the RNG and the session data */ polarssl_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { polarssl_printf( " failed\n ! ctr_drbg_init returned %d\n", ret ); goto exit; } polarssl_printf( " ok\n" ); /* * 2. Start the connection */ polarssl_printf( " . SSL connection to tcp/%s/%-4d...", opt.server_name, opt.server_port ); fflush( stdout ); if( ( ret = net_connect( &server_fd, opt.server_name, opt.server_port ) ) != 0 ) { polarssl_printf( " failed\n ! net_connect returned %d\n\n", ret ); goto exit; } /* * 3. Setup stuff */ if( ( ret = ssl_init( &ssl ) ) != 0 ) { polarssl_printf( " failed\n ! ssl_init returned %d\n\n", ret ); goto exit; } ssl_set_endpoint( &ssl, SSL_IS_CLIENT ); if( verify ) { ssl_set_authmode( &ssl, SSL_VERIFY_REQUIRED ); ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); ssl_set_verify( &ssl, my_verify, NULL ); } else ssl_set_authmode( &ssl, SSL_VERIFY_NONE ); ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd ); if( ( ret = ssl_set_own_cert( &ssl, &clicert, &pkey ) ) != 0 ) { polarssl_printf( " failed\n ! ssl_set_own_cert returned %d\n\n", ret ); goto exit; } #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) if( ( ret = ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) { polarssl_printf( " failed\n ! ssl_set_hostname returned %d\n\n", ret ); goto exit; } #endif /* * 4. Handshake */ while( ( ret = ssl_handshake( &ssl ) ) != 0 ) { if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) { polarssl_printf( " failed\n ! ssl_handshake returned %d\n\n", ret ); ssl_free( &ssl ); goto exit; } } polarssl_printf( " ok\n" ); /* * 5. Print the certificate */ polarssl_printf( " . Peer certificate information ...\n" ); ret = x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", ssl.session->peer_cert ); if( ret == -1 ) { polarssl_printf( " failed\n ! x509_crt_info returned %d\n\n", ret ); ssl_free( &ssl ); goto exit; } polarssl_printf( "%s\n", buf ); ssl_close_notify( &ssl ); ssl_free( &ssl ); } else goto usage; exit: if( server_fd ) net_close( server_fd ); x509_crt_free( &cacert ); x509_crt_free( &clicert ); #if defined(POLARSSL_X509_CRL_PARSE_C) x509_crl_free( &cacrl ); #endif pk_free( &pkey ); ctr_drbg_free( &ctr_drbg ); entropy_free( &entropy ); #if defined(_WIN32) polarssl_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif if( ret < 0 ) ret = 1; return( ret ); }
char *test_SSL_verify_cert() { x509_crt crt; memset( &crt, 0, sizeof crt ); x509_crt ca_crt; memset( &ca_crt, 0, sizeof ca_crt ); x509_crl crl; memset( &crl, 0, sizeof crl ); int ret = 0; ret =x509_crt_parse_file( &crt, "tests/ca/certs/m2-cert.pem" ); mu_assert(ret == 0, "failed to parse cert m2-cert.pem"); ret =x509_crt_parse_file( &ca_crt, "tests/ca/none.pem" ); mu_assert(ret != 0, "failed to fail on non-existent pem none.pem"); ret =x509_crt_parse_file( &ca_crt, "tests/ca/cacert.pem" ); mu_assert(ret == 0, "failed to parse cert cacert.pem"); ret =x509_crl_parse_file( &crl, "tests/ca/crl.pem" ); mu_assert(ret == 0, "failed to parse cert crl.pem"); /* * Validate the cert. Since these certs are only valid within a certain time period, this test * will fail when the current time is outside this period. To avoid false failures (eg. when * building/testing this version of the software in the distant future), adjust the expected * test outcome accordingly. However, log the failure to stderr so that the maintainer can * detect the expiry of the cert, and generate/commit a new one from time to time. */ int flags = 0; ret =x509_crt_verify( &crt, &ca_crt, NULL, NULL, &flags, NULL, NULL); if ( ret ) { char buf[1024]; buf[0] = 0; polarssl_strerror( ret, buf, sizeof buf ); fprintf( stderr, "*** x509_crt_verify of m2-cert.pem: %d: %s\n", ret, buf ); } int valid_from = x509_time_expired( &crt.valid_from ); int valid_to = x509_time_expired( &crt.valid_to ); int expected = 0; if ( valid_from == BADCERT_EXPIRED && valid_to == BADCERT_EXPIRED ) { /* * This cert hasn't yet become active, or has already expired; expect * X509 cert failure (-0x2700) */ fprintf( stderr, "*** x509_crt_verify WILL FAIL because current data is outside: valid_from '%d/%d/%d %d:%d:%d': %d, valid_to '%d/%d/%d %d:%d:%d': %d\n", crt.valid_from.year, crt.valid_from.mon, crt.valid_from.day, crt.valid_from.hour, crt.valid_from.min, crt.valid_from.sec, valid_from, crt.valid_to .year, crt.valid_to .mon, crt.valid_to .day, crt.valid_to .hour, crt.valid_to .min, crt.valid_to .sec, valid_to ); fprintf( stderr, "*** If this is the currently supported version, generate and commit a new tests/ca/m2-cert.pem with valid dates\n" ); expected = POLARSSL_ERR_X509_CERT_VERIFY_FAILED; } mu_assert(ret == expected, "failed to verify cert m2-cert.pem"); x509_crt_free( &crt ); x509_crt_free( &ca_crt ); x509_crl_free( &crl ); return NULL; }
int main( int argc, char *argv[] ) { int ret, i; x509_crt cacert; x509_crl crl; char buf[10240]; ((void) argc); ((void) argv); x509_crt_init( &cacert ); x509_crl_init( &crl ); /* * 1.1. Load the trusted CA */ printf( "\n . Loading the CA root certificate ..." ); fflush( stdout ); /* * Alternatively, you may load the CA certificates from a .pem or * .crt file by calling x509_crt_parse_file( &cacert, "myca.crt" ). */ ret = x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" ); if( ret != 0 ) { printf( " failed\n ! x509_crt_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crt_info( buf, 1024, "CRT: ", &cacert ); printf("%s\n", buf ); /* * 1.2. Load the CRL */ printf( " . Loading the CRL ..." ); fflush( stdout ); ret = x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" ); if( ret != 0 ) { printf( " failed\n ! x509_crl_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crl_info( buf, 1024, "CRL: ", &crl ); printf("%s\n", buf ); for( i = 0; i < MAX_CLIENT_CERTS; i++ ) { /* * 1.3. Load own certificate */ char name[512]; int flags; x509_crt clicert; pk_context pk; x509_crt_init( &clicert ); pk_init( &pk ); snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]); printf( " . Loading the client certificate %s...", name ); fflush( stdout ); ret = x509_crt_parse_file( &clicert, name ); if( ret != 0 ) { printf( " failed\n ! x509_crt_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 1.4. Verify certificate validity with CA certificate */ printf( " . Verify the client certificate with CA certificate..." ); fflush( stdout ); ret = x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL, NULL ); if( ret != 0 ) { if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED ) { if( flags & BADCERT_CN_MISMATCH ) printf( " CN_MISMATCH " ); if( flags & BADCERT_EXPIRED ) printf( " EXPIRED " ); if( flags & BADCERT_REVOKED ) printf( " REVOKED " ); if( flags & BADCERT_NOT_TRUSTED ) printf( " NOT_TRUSTED " ); if( flags & BADCRL_NOT_TRUSTED ) printf( " CRL_NOT_TRUSTED " ); if( flags & BADCRL_EXPIRED ) printf( " CRL_EXPIRED " ); } else { printf( " failed\n ! x509_crt_verify returned %d\n\n", ret ); goto exit; } } printf( " ok\n" ); /* * 1.5. Load own private key */ snprintf(name, 512, "ssl/test-ca/%s", client_private_keys[i]); printf( " . Loading the client private key %s...", name ); fflush( stdout ); ret = pk_parse_keyfile( &pk, name, NULL ); if( ret != 0 ) { printf( " failed\n ! pk_parse_keyfile returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 1.6. Verify certificate validity with private key */ printf( " . Verify the client certificate with private key..." ); fflush( stdout ); /* EC NOT IMPLEMENTED YET */ if( ! pk_can_do( &clicert.pk, POLARSSL_PK_RSA ) ) { printf( " failed\n ! certificate's key is not RSA\n\n" ); ret = POLARSSL_ERR_X509_FEATURE_UNAVAILABLE; goto exit; } ret = mpi_cmp_mpi(&pk_rsa( pk )->N, &pk_rsa( clicert.pk )->N); if( ret != 0 ) { printf( " failed\n ! mpi_cmp_mpi for N returned %d\n\n", ret ); goto exit; } ret = mpi_cmp_mpi(&pk_rsa( pk )->E, &pk_rsa( clicert.pk )->E); if( ret != 0 ) { printf( " failed\n ! mpi_cmp_mpi for E returned %d\n\n", ret ); goto exit; } ret = rsa_check_privkey( pk_rsa( pk ) ); if( ret != 0 ) { printf( " failed\n ! rsa_check_privkey returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crt_free( &clicert ); pk_free( &pk ); } exit: x509_crt_free( &cacert ); x509_crl_free( &crl ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Parse one or more CRLs and add them to the chained list */ int x509_crl_parse( 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_BAD_INPUT_DATA ); 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; x509_crl_init( 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_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_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_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_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_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_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_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && ret != ( POLARSSL_ERR_X509_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_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_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_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; x509_crl_init( crl ); return( x509_crl_parse( crl, buf, buflen ) ); } return( 0 ); }