/* * Parse a private key */ int pk_parse_key( pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret; const pk_info_t *pk_info; #if defined(POLARSSL_PEM_PARSE_C) size_t len; pem_context pem; pem_init( &pem ); #if defined(POLARSSL_RSA_C) ret = pem_read_buffer( &pem, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", key, pwd, pwdlen, &len ); if( ret == 0 ) { if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), pem.buf, pem.buflen ) ) != 0 ) { pk_free( pk ); } pem_free( &pem ); return( ret ); } else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* POLARSSL_RSA_C */ #if defined(POLARSSL_ECP_C) ret = pem_read_buffer( &pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", key, pwd, pwdlen, &len ); if( ret == 0 ) { if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), pem.buf, pem.buflen ) ) != 0 ) { pk_free( pk ); } pem_free( &pem ); return( ret ); } else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* POLARSSL_ECP_C */ ret = pem_read_buffer( &pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", key, NULL, 0, &len ); if( ret == 0 ) { if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, pem.buf, pem.buflen ) ) != 0 ) { pk_free( pk ); } pem_free( &pem ); return( ret ); } else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) ret = pem_read_buffer( &pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----", key, NULL, 0, &len ); if( ret == 0 ) { if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, pem.buf, pem.buflen, pwd, pwdlen ) ) != 0 ) { pk_free( pk ); } pem_free( &pem ); return( ret ); } else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */ #else ((void) pwd); ((void) pwdlen); #endif /* POLARSSL_PEM_PARSE_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 defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, pwd, pwdlen ) ) == 0 ) { return( 0 ); } pk_free( pk ); if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH ) { return( ret ); } #endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */ if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) return( 0 ); pk_free( pk ); #if defined(POLARSSL_RSA_C) if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } pk_free( pk ); #endif /* POLARSSL_RSA_C */ #if defined(POLARSSL_ECP_C) if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } pk_free( pk ); #endif /* POLARSSL_ECP_C */ return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); }
/* * Parse an encrypted PKCS#8 encoded private key */ static int pk_parse_key_pkcs8_encrypted_der( pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret, decrypted = 0; size_t len; unsigned char buf[2048]; unsigned char *p, *end; asn1_buf pbe_alg_oid, pbe_params; #if defined(POLARSSL_PKCS12_C) cipher_type_t cipher_alg; md_type_t md_alg; #endif memset( buf, 0, sizeof( buf ) ); p = (unsigned char *) key; end = p + keylen; if( pwdlen == 0 ) return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); /* * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) * * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData * } * * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * * EncryptedData ::= OCTET STRING * * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } end = p + len; if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( len > sizeof( buf ) ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); /* * Decrypt EncryptedData with appropriate PDE */ #if defined(POLARSSL_PKCS12_C) if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) { if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT, cipher_alg, md_alg, pwd, pwdlen, p, len, buf ) ) != 0 ) { if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH ) return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); return( ret ); } decrypted = 1; } else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) ) { if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params, PKCS12_PBE_DECRYPT, pwd, pwdlen, p, len, buf ) ) != 0 ) { return( ret ); } // Best guess for password mismatch when using RC4. If first tag is // not ASN1_CONSTRUCTED | ASN1_SEQUENCE // if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); decrypted = 1; } else #endif /* POLARSSL_PKCS12_C */ #if defined(POLARSSL_PKCS5_C) if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) ) { if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen, p, len, buf ) ) != 0 ) { if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH ) return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); return( ret ); } decrypted = 1; } else #endif /* POLARSSL_PKCS5_C */ { ((void) pwd); } if( decrypted == 0 ) return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); }