?? x509read_c.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0048)http://xyssl.org/code/source/x509read/x509read.c -->
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.3790.2954" name=GENERATOR></HEAD>
<BODY><PRE>/*
* X.509 certificate and private key decoding
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* The ITU-T X.509 standard defines a certificat format for PKI.
*
* http://www.ietf.org/rfc/rfc2459.txt
* http://www.ietf.org/rfc/rfc3279.txt
*
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
*
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
*/
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "xyssl/x509.h"
#include "xyssl/base64.h"
#include "xyssl/des.h"
#include "xyssl/sha1.h"
#include "xyssl/md5.h"
#if !defined(NO_MD4)
#include "xyssl/md4.h"
#endif
#if !defined(NO_MD2)
#include "xyssl/md2.h"
#endif
/*
* ASN.1 DER decoding routines
*/
static int asn1_get_len( unsigned char **p,
unsigned char *end,
int *len )
{
if( ( end - *p ) < 1 )
return( ERR_ASN1_OUT_OF_DATA );
if( ( **p & 0x80 ) == 0 )
*len = *(*p)++;
else
{
switch( **p & 0x7F )
{
case 1:
if( ( end - *p ) < 2 )
return( ERR_ASN1_OUT_OF_DATA );
*len = (*p)[1];
(*p) += 2;
break;
case 2:
if( ( end - *p ) < 3 )
return( ERR_ASN1_OUT_OF_DATA );
*len = ( (*p)[1] << 8 ) | (*p)[2];
(*p) += 3;
break;
default:
return( ERR_ASN1_INVALID_LENGTH );
break;
}
}
if( *len > (int) ( end - *p ) )
return( ERR_ASN1_OUT_OF_DATA );
return( 0 );
}
static int asn1_get_tag( unsigned char **p,
unsigned char *end,
int *len, int tag )
{
if( ( end - *p ) < 1 )
return( ERR_ASN1_OUT_OF_DATA );
if( **p != tag )
return( ERR_ASN1_UNEXPECTED_TAG );
(*p)++;
return( asn1_get_len( p, end, len ) );
}
static int asn1_get_bool( unsigned char **p,
unsigned char *end,
int *val )
{
int ret, len;
if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
return( ret );
if( len != 1 )
return( ERR_ASN1_INVALID_LENGTH );
*val = ( **p != 0 ) ? 1 : 0;
(*p)++;
return( 0 );
}
static int asn1_get_int( unsigned char **p,
unsigned char *end,
int *val )
{
int ret, len;
if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
return( ret );
if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
return( ERR_ASN1_INVALID_LENGTH );
*val = 0;
while( len-- > 0 )
{
*val = ( *val << 8 ) | **p;
(*p)++;
}
return( 0 );
}
static int asn1_get_mpi( unsigned char **p,
unsigned char *end,
mpi *X )
{
int ret, len;
if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
return( ret );
ret = mpi_read_binary( X, *p, len );
*p += len;
return( ret );
}
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
static int x509_get_version( unsigned char **p,
unsigned char *end,
int *ver )
{
int ret, len;
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
{
if( ret == ERR_ASN1_UNEXPECTED_TAG )
return( *ver = 0 );
return( ret );
}
end = *p + len;
if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
return( ERR_X509_CERT_INVALID_VERSION | ret );
if( *p != end )
return( ERR_X509_CERT_INVALID_VERSION |
ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}
/*
* CertificateSerialNumber ::= INTEGER
*/
static int x509_get_serial( unsigned char **p,
unsigned char *end,
x509_buf *serial )
{
int ret;
if( ( end - *p ) < 1 )
return( ERR_X509_CERT_INVALID_SERIAL |
ERR_ASN1_OUT_OF_DATA );
if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
**p != ASN1_INTEGER )
return( ERR_X509_CERT_INVALID_SERIAL |
ERR_ASN1_UNEXPECTED_TAG );
serial->tag = *(*p)++;
if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
return( ERR_X509_CERT_INVALID_SERIAL | ret );
serial->p = *p;
*p += serial->len;
return( 0 );
}
/*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
*/
static int x509_get_alg( unsigned char **p,
unsigned char *end,
x509_buf *alg )
{
int ret, len;
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_ALG | ret );
end = *p + len;
alg->tag = **p;
if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
return( ERR_X509_CERT_INVALID_ALG | ret );
alg->p = *p;
*p += alg->len;
if( *p == end )
return( 0 );
/*
* assume the algorithm parameters must be NULL
*/
if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
return( ERR_X509_CERT_INVALID_ALG | ret );
if( *p != end )
return( ERR_X509_CERT_INVALID_ALG |
ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}
/*
* RelativeDistinguishedName ::=
* SET OF AttributeTypeAndValue
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY DEFINED BY AttributeType
*/
static int x509_get_name( unsigned char **p,
unsigned char *end,
x509_name *cur )
{
int ret, len;
unsigned char *end2;
x509_buf *oid;
x509_buf *val;
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
return( ERR_X509_CERT_INVALID_NAME | ret );
end2 = end;
end = *p + len;
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_NAME | ret );
if( *p + len != end )
return( ERR_X509_CERT_INVALID_NAME |
ERR_ASN1_LENGTH_MISMATCH );
oid = &cur->oid;
oid->tag = **p;
if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
return( ERR_X509_CERT_INVALID_NAME | ret );
oid->p = *p;
*p += oid->len;
if( ( end - *p ) < 1 )
return( ERR_X509_CERT_INVALID_NAME |
ERR_ASN1_OUT_OF_DATA );
if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
**p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
**p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
return( ERR_X509_CERT_INVALID_NAME |
ERR_ASN1_UNEXPECTED_TAG );
val = &cur->val;
val->tag = *(*p)++;
if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
return( ERR_X509_CERT_INVALID_NAME | ret );
val->p = *p;
*p += val->len;
cur->next = NULL;
if( *p != end )
return( ERR_X509_CERT_INVALID_NAME |
ERR_ASN1_LENGTH_MISMATCH );
/*
* recurse until end of SEQUENCE is reached
*/
if( *p == end2 )
return( 0 );
cur->next = (x509_name *) malloc(
sizeof( x509_name ) );
if( cur->next == NULL )
return( 1 );
return( x509_get_name( p, end2, cur->next ) );
}
/*
* Validity ::= SEQUENCE {
* notBefore Time,
* notAfter Time }
*
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
*/
static int x509_get_dates( unsigned char **p,
unsigned char *end,
x509_time *from,
x509_time *to )
{
int ret, len;
char date[64];
if( ( ret = asn1_get_tag( p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
return( ERR_X509_CERT_INVALID_DATE | ret );
end = *p + len;
/*
* TODO: also handle GeneralizedTime
*/
if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
return( ERR_X509_CERT_INVALID_DATE | ret );
memset( date, 0, sizeof( date ) );
memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
len : (int) sizeof( date ) - 1 );
if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
&from->year, &from->mon, &from->day,
&from->hour, &from->min, &from->sec ) < 5 )
return( ERR_X509_CERT_INVALID_DATE );
from->year += 100 * ( from->year < 90 );
from->year += 1900;
*p += len;
if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
return( ERR_X509_CERT_INVALID_DATE | ret );
memset( date, 0, sizeof( date ) );
memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
len : (int) sizeof( date ) - 1 );
if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
&to->year, &to->mon, &to->day,
&to->hour, &to->min, &to->sec ) < 5 )
return( ERR_X509_CERT_INVALID_DATE );
to->year += 100 * ( to->year < 90 );
to->year += 1900;
*p += len;
if( *p != end )
return( ERR_X509_CERT_INVALID_DATE |
ERR_ASN1_LENGTH_MISMATCH );
return( 0 );
}
/*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
*/
static int x509_get_pubkey( unsigned char **p,
unsigned char *end,
x509_buf *pk_alg_oid,
mpi *N, mpi *E )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -