📄 x509read_c.htm
字号:
#if defined _MSC_VER && !defined snprintf
#define snprintf _snprintf
#endif
/*
* Store the name in printable form into buf; no more
* than (end - buf) characters will be written
*/
int x509_dn_gets( char *buf, char *end, x509_name *dn )
{
int i;
unsigned char c;
x509_name *name;
char s[128], *p;
memset( s, 0, sizeof( s ) );
name = dn;
p = buf;
while( name != NULL )
{
if( name != dn )
p += snprintf( p, end - p, ", " );
if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
{
switch( name->oid.p[2] )
{
case X520_COMMON_NAME:
p += snprintf( p, end - p, "CN=" ); break;
case X520_COUNTRY:
p += snprintf( p, end - p, "C=" ); break;
case X520_LOCALITY:
p += snprintf( p, end - p, "L=" ); break;
case X520_STATE:
p += snprintf( p, end - p, "ST=" ); break;
case X520_ORGANIZATION:
p += snprintf( p, end - p, "O=" ); break;
case X520_ORG_UNIT:
p += snprintf( p, end - p, "OU=" ); break;
default:
p += snprintf( p, end - p, "0x%02X=",
name->oid.p[2] );
break;
}
}
else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
{
switch( name->oid.p[8] )
{
case PKCS9_EMAIL:
p += snprintf( p, end - p, "emailAddress=" ); break;
default:
p += snprintf( p, end - p, "0x%02X=",
name->oid.p[8] );
break;
}
}
else
p += snprintf( p, end - p, "\?\?=" );
for( i = 0; i < name->val.len; i++ )
{
if( i >= (int) 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';
p += snprintf( p, end - p, "%s", s );
name = name->next;
}
return( p - buf );
}
/*
* Return an informational string about the
* certificate, or NULL if memory allocation failed
*/
char *x509_cert_info( x509_cert *crt )
{
int i, n;
char *buf, *p, *end;
if( ( buf = (char *) malloc( 4096 ) ) == NULL )
return( NULL );
memset( buf, 0, 4096 );
p = buf;
end = buf + 4096 - 1;
p += snprintf( p, end - p, "Cert. version : %d\n", crt->version );
p += snprintf( p, end - p, "Serial Number : " );
n = ( crt->serial.len <= 32 )
? crt->serial.len : 32;
for( i = 1; i < n; i++ )
p += snprintf( p, end - p, "%02X%s",
crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
p += snprintf( p, end - p, "\nIssuer name : " );
p += x509_dn_gets( p, end, &crt->issuer );
p += snprintf( p, end - p, "\nSubject name : " );
p += x509_dn_gets( p, end, &crt->subject );
p += snprintf( p, end - p, "\nIssued on : " \
"%04d-%02d-%02d %02d:%02d:%02d",
crt->valid_from.year, crt->valid_from.mon,
crt->valid_from.day, crt->valid_from.hour,
crt->valid_from.min, crt->valid_from.sec );
p += snprintf( p, end - p, "\nExpires on : " \
"%04d-%02d-%02d %02d:%02d:%02d",
crt->valid_to.year, crt->valid_to.mon,
crt->valid_to.day, crt->valid_to.hour,
crt->valid_to.min, crt->valid_to.sec );
p += snprintf( p, end - p, "\nSigned using : RSA+" );
switch( crt->sig_oid1.p[8] )
{
case RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
case RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
case RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
case RSA_SHA1: p += snprintf( p, end - p, "SHA1" ); break;
default: p += snprintf( p, end - p, "???" ); break;
}
p += snprintf( p, end - p, "\nRSA key size : %u bits\n",
crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
return( buf );
}
/*
* Return 0 if the certificate is still valid, or BADCERT_HAS_EXPIRED
*/
int x509_is_cert_expired( x509_cert *crt )
{
struct tm *lt;
time_t tt;
tt = time( NULL );
lt = localtime( &tt );
if( lt->tm_year > crt->valid_to.year - 1900 )
return( BADCERT_HAS_EXPIRED );
if( lt->tm_year == crt->valid_to.year - 1900 &&
lt->tm_mon > crt->valid_to.mon - 1 )
return( BADCERT_HAS_EXPIRED );
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_HAS_EXPIRED );
return( 0 );
}
static void x509_hash( unsigned char *in, int len, int alg,
unsigned char *out )
{
switch( alg )
{
#if !defined(NO_MD2)
case RSA_MD2 : md2( in, len, out ); break;
#endif
#if !defined(NO_MD4)
case RSA_MD4 : md4( in, len, out ); break;
#endif
case RSA_MD5 : md5( in, len, out ); break;
case RSA_SHA1 : sha1( in, len, out ); break;
default:
memset( out, '\xFF', len );
break;
}
}
/*
* Verify the certificate validity
*/
int x509_verify_cert( x509_cert *crt, x509_cert *trust_ca,
char *cn, int *flags )
{
int alg_id;
int pathlen;
x509_cert *cur;
x509_name *name;
unsigned char hash[20];
*flags = x509_is_cert_expired( crt );
if( cn != NULL )
{
name = &crt->subject;
while( name != NULL )
{
if( memcmp( name->oid.p, "\x55\x04\x03", 3 ) == 0 &&
memcmp( name->val.p, cn, strlen( cn ) ) == 0 )
break;
name = name->next;
}
if( name == NULL )
*flags |= BADCERT_CN_MISMATCH;
}
*flags |= BADCERT_NOT_TRUSTED;
/*
* Iterate upwards in the given cert chain,
* ignoring any upper cert with CA != TRUE.
*/
cur = crt->next;
pathlen = 1;
while( cur->version != 0 )
{
if( cur->ca_istrue == 0 ||
crt->issuer_raw.len != cur->subject_raw.len ||
memcmp( crt->issuer_raw.p, cur->subject_raw.p,
crt->issuer_raw.len ) != 0 )
{
cur = cur->next;
continue;
}
alg_id = crt->sig_oid1.p[8];
x509_hash( crt->tbs.p, crt->tbs.len, alg_id, hash );
if( rsa_pkcs1_verify( &cur->rsa, alg_id, hash, 0,
crt->sig.p, crt->sig.len ) != 0 )
return( ERR_X509_SIG_VERIFY_FAILED );
pathlen++;
crt = cur;
cur = crt->next;
}
/*
* Atempt to validate topmost cert with our CA chain.
*/
while( trust_ca->version != 0 )
{
if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
crt->issuer_raw.len ) != 0 )
{
trust_ca = trust_ca->next;
continue;
}
if( trust_ca->max_pathlen > 0 &&
trust_ca->max_pathlen < pathlen )
return( ERR_X509_SIG_VERIFY_FAILED );
alg_id = crt->sig_oid1.p[8];
x509_hash( crt->tbs.p, crt->tbs.len, alg_id, hash );
if( rsa_pkcs1_verify( &trust_ca->rsa, alg_id, hash, 0,
crt->sig.p, crt->sig.len ) != 0 )
return( ERR_X509_SIG_VERIFY_FAILED );
break;
}
if( trust_ca->version == 0 )
return( ERR_X509_SIG_VERIFY_FAILED );
*flags &= ~BADCERT_NOT_TRUSTED;
return( 0 );
}
/*
* Unallocate all certificate data
*/
void x509_free_cert( x509_cert *crt )
{
x509_cert *cert_cur = crt;
x509_cert *cert_prv;
x509_name *name_cur;
x509_name *name_prv;
if( crt == NULL )
return;
do
{
rsa_free( &cert_cur->rsa );
name_cur = cert_cur->issuer.next;
while( name_cur != NULL )
{
name_prv = name_cur;
name_cur = name_cur->next;
free( name_prv );
}
name_cur = cert_cur->subject.next;
while( name_cur != NULL )
{
name_prv = name_cur;
name_cur = name_cur->next;
free( name_prv );
}
if( cert_cur->raw.p != NULL )
free( cert_cur->raw.p );
cert_cur = cert_cur->next;
}
while( cert_cur != NULL );
cert_cur = crt;
do
{
cert_prv = cert_cur;
cert_cur = cert_cur->next;
if( cert_prv != crt )
free( cert_prv );
}
while( cert_cur != NULL );
}
static const char _x509_read_src[] = "_x509read_src";
#if defined(SELF_TEST)
#include "xyssl/certs.h"
/*
* Checkup routine
*/
int x509_self_test( int verbose )
{
int ret, flags;
x509_cert cacert;
x509_cert clicert;
rsa_context rsa;
if( verbose != 0 )
printf( " X.509 certificate load: " );
memset( &clicert, 0, sizeof( x509_cert ) );
ret = x509_add_certs( &clicert, (unsigned char *) test_cli_crt,
strlen( test_cli_crt ) );
if( ret != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( ret );
}
memset( &cacert, 0, sizeof( x509_cert ) );
ret = x509_add_certs( &cacert, (unsigned char *) test_ca_crt,
strlen( test_ca_crt ) );
if( ret != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( ret );
}
if( verbose != 0 )
printf( "passed\n X.509 private key load: " );
ret = x509_parse_key( &rsa,
(unsigned char *) test_ca_key, strlen( test_ca_key ),
(unsigned char *) test_ca_pwd, strlen( test_ca_pwd ) );
if( ret != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( ret );
}
if( verbose != 0 )
printf( "passed\n X.509 signature verify: ");
ret = x509_verify_cert( &clicert, &cacert, "Joe User", &flags );
if( ret != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( ret );
}
if( verbose != 0 )
printf( "passed\n\n" );
x509_free_cert( &cacert );
x509_free_cert( &clicert );
rsa_free( &rsa );
return( 0 );
}
#else
int x509_self_test( int verbose )
{
return( 0 );
}
#endif
</PRE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -