- int ret, len, enc;
- unsigned char *s1, *s2;
- unsigned char *p, *end;
-
- s1 = (unsigned char *) strstr( (char *) buf,
- "-----BEGIN RSA PRIVATE KEY-----" );
-
- if( s1 != NULL )
- {
- s2 = (unsigned char *) strstr( (char *) buf,
- "-----END RSA PRIVATE KEY-----" );
-
- if( s2 == NULL || s2 <= s1 )
- return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
-
- s1 += 31;
- if( *s1 == '\r' ) s1++;
- if( *s1 == '\n' ) s1++;
- else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
-
- enc = 0;
-
- if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
- {
- return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
- }
-
- len = 0;
- ret = base64_decode( NULL, &len, s1, s2 - s1 );
-
- if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
- return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
-
- if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
- return( 1 );
-
- if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
- {
- free( buf );
- return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
- }
-
- buflen = len;
-
- if( enc != 0 )
- {
- return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
- }
- }
-
- memset( rsa, 0, sizeof( rsa_context ) );
-
- p = buf;
- end = buf + buflen;
-
- /*
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- if( ( ret = asn1_get_tag( &p, end, &len,
- ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
- {
- if( s1 != NULL )
- free( buf );
-
- 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( s1 != NULL )
- free( buf );
-
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
- }
-
- if( rsa->ver != 0 )
- {
- if( s1 != NULL )
- free( buf );
-
- rsa_free( rsa );
- return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
- }
-
- 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 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
- ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
- {
- if( s1 != NULL )
- free( buf );
-
- rsa_free( rsa );
- return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
- }
-
- rsa->len = mpi_size( &rsa->N );
-
- if( p != end )
- {
- if( s1 != NULL )
- free( buf );
-
- rsa_free( rsa );
- return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
- }
-
- if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
- {
- if( s1 != NULL )
- free( buf );
-
- rsa_free( rsa );
- return( ret );
- }
-
- if( s1 != NULL )
- free( buf );
-
- return( 0 );