📄 x509read_c.htm
字号:
{
int ret, len;
unsigned char *end2;
if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
return( ret );
/*
* only RSA public keys handled at this time
*/
if( pk_alg_oid->len != 9 ||
memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
return( ERR_X509_CERT_UNKNOWN_PK_ALG );
if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
return( ERR_X509_CERT_INVALID_PUBKEY | ret );
if( ( end - *p ) < 1 )
return( ERR_X509_CERT_INVALID_PUBKEY |
ERR_ASN1_OUT_OF_DATA );
end2 = *p + len;
if( *(*p)++ != 0 )
return( ERR_X509_CERT_INVALID_PUBKEY );
/*
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER -- e
* }
*/
if( ( ret = asn1_get_tag( p, end2, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_PUBKEY | ret );
if( *p + len != end2 )
return( ERR_X509_CERT_INVALID_PUBKEY |
ERR_ASN1_LENGTH_MISMATCH );
if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
return( ERR_X509_CERT_INVALID_PUBKEY | ret );
if( *p != end )
return( ERR_X509_CERT_INVALID_PUBKEY |
ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}
static int x509_get_sig( unsigned char **p,
unsigned char *end,
x509_buf *sig )
{
int ret, len;
sig->tag = **p;
if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
return( ERR_X509_CERT_INVALID_SIGNATURE | ret );
if( --len < 1 || *(*p)++ != 0 )
return( ERR_X509_CERT_INVALID_SIGNATURE );
sig->len = len;
sig->p = *p;
*p += len;
return( 0 );
}
/*
* X.509 v2/v3 unique identifier (not parsed)
*/
static int x509_get_uid( unsigned char **p,
unsigned char *end,
x509_buf *uid, int n )
{
int ret;
if( *p == end )
return( 0 );
uid->tag = **p;
if( ( ret = asn1_get_tag( p, end, &uid->len,
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
{
if( ret == ERR_ASN1_UNEXPECTED_TAG )
return( 0 );
return( ret );
}
uid->p = *p;
*p += uid->len;
return( 0 );
}
/*
* X.509 v3 extensions (only BasicConstraints are parsed)
*/
static int x509_get_ext( unsigned char **p,
unsigned char *end,
x509_buf *ext,
int *ca_istrue,
int *max_pathlen )
{
int ret, len;
int is_critical = 1;
int is_cacert = 0;
unsigned char *end2;
if( *p == end )
return( 0 );
ext->tag = **p;
if( ( ret = asn1_get_tag( p, end, &ext->len,
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
{
if( ret == ERR_ASN1_UNEXPECTED_TAG )
return( 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( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( end != *p + len )
return( ERR_X509_CERT_INVALID_EXTENSIONS |
ERR_ASN1_LENGTH_MISMATCH );
while( *p < end )
{
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
{
*p += len;
continue;
}
*p += 5;
if( ( ret = asn1_get_bool( p, end, &is_critical ) ) != 0 &&
( ret != ERR_ASN1_UNEXPECTED_TAG ) )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_OCTET_STRING ) ) != 0 )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
/*
* BasicConstraints ::= SEQUENCE {
* cA BOOLEAN DEFAULT FALSE,
* pathLenConstraint INTEGER (0..MAX) OPTIONAL }
*/
end2 = *p + len;
if( ( ret = asn1_get_tag( p, end2, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( *p == end2 )
continue;
if( ( ret = asn1_get_bool( p, end2, &is_cacert ) ) != 0 )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( *p == end2 )
continue;
if( ( ret = asn1_get_int( p, end2, max_pathlen ) ) != 0 )
return( ERR_X509_CERT_INVALID_EXTENSIONS | ret );
if( *p != end2 )
return( ERR_X509_CERT_INVALID_EXTENSIONS |
ERR_ASN1_LENGTH_MISMATCH );
max_pathlen++;
}
if( *p != end )
return( ERR_X509_CERT_INVALID_EXTENSIONS |
ERR_ASN1_LENGTH_MISMATCH );
*ca_istrue = is_critical & is_cacert;
return( 0 );
}
/*
* Parse one or more certificates and add them to the chain
*/
int x509_add_certs( x509_cert *chain, unsigned char *buf, int buflen )
{
int ret, len;
unsigned char *s1, *s2;
unsigned char *p, *end;
x509_cert *crt;
crt = chain;
while( crt->version != 0 )
crt = crt->next;
/*
* check if the certificate is encoded in base64
*/
s1 = (unsigned char *) strstr( (char *) buf,
"-----BEGIN CERTIFICATE-----" );
if( s1 != NULL )
{
s2 = (unsigned char *) strstr( (char *) buf,
"-----END CERTIFICATE-----" );
if( s2 == NULL || s2 <= s1 )
return( ERR_X509_CERT_INVALID_PEM );
s1 += 27;
if( *s1 == '\r' ) s1++;
if( *s1 == '\n' ) s1++;
else return( ERR_X509_CERT_INVALID_PEM );
/*
* get the DER data length and decode the buffer
*/
len = 0;
ret = base64_decode( NULL, &len, s1, s2 - s1 );
if( ret == ERR_BASE64_INVALID_CHARACTER )
return( ERR_X509_CERT_INVALID_PEM | ret );
if( ( p = (unsigned char *) malloc( len ) ) == NULL )
return( 1 );
if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
{
free( p );
return( ERR_X509_CERT_INVALID_PEM | ret );
}
/*
* update the buffer size and offset
*/
s2 += 25;
if( *s2 == '\r' ) s2++;
if( *s2 == '\n' ) s2++;
else return( ERR_X509_CERT_INVALID_PEM );
buflen -= s2 - buf;
buf = s2;
}
else
{
/*
* nope, copy the raw DER data
*/
p = (unsigned char *) malloc( len = buflen );
if( p == NULL )
return( 1 );
memcpy( p, buf, buflen );
buflen = 0;
}
crt->raw.p = p;
crt->raw.len = len;
end = p + len;
/*
* Certificate ::= SEQUENCE {
* tbsCertificate TBSCertificate,
* signatureAlgorithm AlgorithmIdentifier,
* signatureValue BIT STRING }
*/
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT );
}
if( len != (int) ( end - p ) )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT |
ERR_ASN1_LENGTH_MISMATCH );
}
/*
* TBSCertificate ::= SEQUENCE {
*/
crt->tbs.p = p;
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT | ret );
}
end = p + len;
crt->tbs.len = end - crt->tbs.p;
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*
* CertificateSerialNumber ::= INTEGER
*
* signature AlgorithmIdentifier
*/
if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
{
x509_free_cert( crt );
return( ret );
}
crt->version++;
if( crt->version > 3 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_UNKNOWN_VERSION );
}
if( crt->sig_oid1.len != 9 ||
memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_UNKNOWN_SIG_ALG );
}
if( crt->sig_oid1.p[8] < 2 ||
crt->sig_oid1.p[8] > 5 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_UNKNOWN_SIG_ALG );
}
/*
* issuer Name
*/
crt->issuer_raw.p = p;
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT | ret );
}
if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
{
x509_free_cert( crt );
return( ret );
}
crt->issuer_raw.len = p - crt->issuer_raw.p;
/*
* Validity ::= SEQUENCE {
* notBefore Time,
* notAfter Time }
*
*/
if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
&crt->valid_to ) ) != 0 )
{
x509_free_cert( crt );
return( ret );
}
/*
* subject Name
*/
crt->subject_raw.p = p;
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT | ret );
}
if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
{
x509_free_cert( crt );
return( ret );
}
crt->subject_raw.len = p - crt->subject_raw.p;
/*
* SubjectPublicKeyInfo ::= SEQUENCE
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
*/
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
x509_free_cert( crt );
return( ERR_X509_CERT_INVALID_FORMAT | ret );
}
if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
&crt->rsa.N, &crt->rsa.E ) ) != 0 )
{
x509_free_cert( crt );
return( ret );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -