Internally split up x509parse_key()

Split up x509parse_key() into a (PEM) handler function and specific
DER parser functions for the PKCS#1 (x509parse_key_pkcs1_der()) and
unencrypted PKCS#8 (x509parse_key_pkcs8_unencrypted_der()) private
key formats.
(cherry picked from commit 65a1909dc6ff7b93f0a231a5a49d98d968c9bcdc)

Conflicts:
	library/x509parse.c
This commit is contained in:
Paul Bakker 2013-06-24 19:00:59 +02:00
parent 89ecb2d074
commit e2f5040876
2 changed files with 165 additions and 166 deletions

View File

@ -2015,69 +2015,21 @@ int x509parse_public_keyfile( rsa_context *rsa, const char *path )
#endif /* POLARSSL_FS_IO */
/*
* Parse a private RSA key
* Parse a PKCS#1 encoded private RSA key
*/
int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen )
static int x509parse_key_pkcs1_der( rsa_context *rsa,
const unsigned char *key,
size_t keylen )
{
int ret;
size_t len;
unsigned char *p, *end;
unsigned char *p_alt;
x509_buf pk_alg_oid;
#if defined(POLARSSL_PEM_C)
pem_context pem;
pem_init( &pem );
ret = pem_read_buffer( &pem,
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
key, pwd, pwdlen, &len );
if( ret == POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
ret = pem_read_buffer( &pem,
"-----BEGIN PRIVATE KEY-----",
"-----END PRIVATE KEY-----",
key, pwd, pwdlen, &len );
}
if( ret == 0 )
{
/*
* Was PEM encoded
*/
keylen = pem.buflen;
}
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
pem_free( &pem );
return( ret );
}
p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
#else
((void) pwd);
((void) pwdlen);
p = (unsigned char *) key;
#endif
end = p + keylen;
/*
* Note: Depending on the type of private key file one can expect either a
* PrivatKeyInfo object (PKCS#8) or a RSAPrivateKey (PKCS#1) directly.
*
* PrivateKeyInfo ::= SEQUENCE {
* version Version,
* algorithm AlgorithmIdentifier,
* PrivateKey BIT STRING
* }
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
* This function parses the RSAPrivateKey (PKCS#1)
*
* RSAPrivateKey ::= SEQUENCE {
* version Version,
@ -2095,10 +2047,6 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
@ -2106,106 +2054,14 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
if( rsa->ver != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
}
p_alt = p;
if( ( ret = x509_get_alg( &p_alt, end, &pk_alg_oid ) ) != 0 )
{
// Assume that we have the PKCS#1 format if wrong
// tag was encountered
//
if( ret != POLARSSL_ERR_X509_CERT_INVALID_ALG +
POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
}
}
else
{
pk_type_t pk_alg = POLARSSL_PK_NONE;
/*
* only RSA keys handled at this time
*/
if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 )
return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
/*
* Parse the PKCS#8 format
*/
p = p_alt;
if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
if( ( end - p ) < 1 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
POLARSSL_ERR_ASN1_OUT_OF_DATA );
}
end = p + len;
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
end = p + len;
if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
if( rsa->ver != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
}
}
if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
@ -2215,9 +2071,6 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
@ -2226,9 +2079,6 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
if( p != end )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
@ -2236,16 +2086,165 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
{
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
rsa_free( rsa );
return( ret );
}
return( 0 );
}
/*
* Parse an unencrypted PKCS#8 encoded private RSA key
*/
static int x509parse_key_pkcs8_unencrypted_der(
rsa_context *rsa,
const unsigned char *key,
size_t keylen )
{
int ret;
size_t len;
unsigned char *p, *end;
x509_buf pk_alg_oid;
pk_type_t pk_alg = POLARSSL_PK_NONE;
p = (unsigned char *) key;
end = p + keylen;
/*
* This function parses the PrivatKeyInfo object (PKCS#8)
*
* PrivateKeyInfo ::= SEQUENCE {
* version Version,
* algorithm AlgorithmIdentifier,
* PrivateKey BIT STRING
* }
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* The PrivateKey BIT STRING is a PKCS#1 RSAPrivateKey
*/
if( ( ret = asn1_get_tag( &p, end, &len,
ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
{
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
}
end = p + len;
if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
if( rsa->ver != 0 )
return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
if( ( ret = x509_get_alg( &p, end, &pk_alg_oid ) ) != 0 )
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
/*
* only RSA keys handled at this time
*/
if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 )
return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
/*
* Get the OCTET STRING and parse the PKCS#1 format inside
*/
if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
if( ( end - p ) < 1 )
{
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
POLARSSL_ERR_ASN1_OUT_OF_DATA );
}
end = p + len;
if( ( ret = x509parse_key_pkcs1_der( rsa, p, end - p ) ) != 0 )
return( ret );
return( 0 );
}
/*
* Parse a private RSA key
*/
int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen )
{
int ret;
#if defined(POLARSSL_PEM_C)
size_t len;
pem_context pem;
pem_init( &pem );
ret = pem_read_buffer( &pem,
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
key, pwd, pwdlen, &len );
if( ret == 0 )
{
if( ( ret = x509parse_key_pkcs1_der( rsa, pem.buf, pem.buflen ) ) != 0 )
{
rsa_free( rsa );
}
pem_free( &pem );
return( ret );
}
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
pem_free( &pem );
return( ret );
}
ret = pem_read_buffer( &pem,
"-----BEGIN PRIVATE KEY-----",
"-----END PRIVATE KEY-----",
key, NULL, 0, &len );
if( ret == 0 )
{
if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa,
pem.buf, pem.buflen ) ) != 0 )
{
rsa_free( rsa );
}
pem_free( &pem );
return( ret );
}
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
pem_free( &pem );
return( ret );
}
pem_free( &pem );
#endif
#else
((void) pwd);
((void) pwdlen);
#endif /* POLARSSL_PEM_C */
// At this point we only know it's not a PEM formatted key. Could be any
// of the known DER encoded private key formats
//
// We try the different DER format parsers to see if one passes without
// error
//
if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa, key, keylen ) ) != 0 )
{
rsa_free( rsa );
if( ( ret = x509parse_key_pkcs1_der( rsa, key, keylen ) ) != 0 )
{
rsa_free( rsa );
return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
}
}
return( 0 );
}

View File

@ -584,22 +584,22 @@ X509 CRL ASN1 (TBSCertList, no entries)
x509parse_crl:"30463031020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030300d06092a864886f70d01010e050003020001":"CRL version \: 1\nissuer name \: CN=ABCD\nthis update \: 2009-01-01 00\:00\:00\nnext update \: 0000-00-00 00\:00\:00\nRevoked certificates\:\nsigned using \: RSA with SHA-224\n":0
X509 Key ASN1 (Incorrect first tag)
x509parse_key:"":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
x509parse_key:"":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, incorrect version tag)
x509parse_key:"300100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
x509parse_key:"300100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, version tag missing)
x509parse_key:"3000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
x509parse_key:"3000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, invalid version)
x509parse_key:"3003020101":"":POLARSSL_ERR_X509_KEY_INVALID_VERSION
x509parse_key:"3003020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, correct version, incorrect tag)
x509parse_key:"300402010000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
x509parse_key:"300402010000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, values present, length mismatch)
x509parse_key:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
x509parse_key:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT
X509 Key ASN1 (RSAPrivateKey, values present, check_privkey fails)
x509parse_key:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_RSA_KEY_CHECK_FAILED
x509parse_key:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT