⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x509read_c.htm

📁 阅读x.509文件的代码
💻 HTM
📖 第 1 页 / 共 4 页
字号:
#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 + -