Merge "Add tests for alg name aliases"
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index c1d73df..8df02c9 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -87,14 +87,33 @@
static {
for (String[] element : knownAlgMappings) {
- String algUC = element[1].toUpperCase(Locale.US);
- alg2OidMap.put(algUC, element[0]);
- oid2AlgMap.put(element[0], algUC);
- // map upper case alg name to its original name
- algAliasesMap.put(algUC, element[1]);
+ addMapping(element[0], element[1]);
}
}
+ /**
+ * Adds a mapping to the internal table. Will overwrite any entry already
+ * present. Visible for testing.
+ */
+ public static void addMapping(String oid, String name) {
+ String nameUC = name.toUpperCase(Locale.ROOT);
+ alg2OidMap.put(nameUC, oid);
+ oid2AlgMap.put(oid, nameUC);
+ // map upper case alg name to its original name
+ algAliasesMap.put(nameUC, name);
+ }
+
+ /**
+ * Removes a mapping from the internal table. Visible for testing.
+ */
+ public static void removeMapping(String oid, String name) {
+ String nameUC = name.toUpperCase(Locale.ROOT);
+ alg2OidMap.remove(nameUC);
+ oid2AlgMap.remove(oid);
+ // map upper case alg name to its original name
+ algAliasesMap.remove(nameUC);
+ }
+
// No instances
private AlgNameMapper() {
}
@@ -126,7 +145,7 @@
checkCacheVersion();
// alg2OidMap map contains upper case keys
- String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
+ String result = alg2OidMap.get(algName.toUpperCase(Locale.ROOT));
if (result != null) {
return result;
}
@@ -144,7 +163,7 @@
* Returns algName for OID
*
* @param oid OID to be mapped
- * @return algorithm name
+ * @return algorithm name or {@code null} if not found.
*/
public static String map2AlgName(String oid) {
checkCacheVersion();
@@ -172,7 +191,7 @@
* @return algorithm name
*/
public static String getStandardName(String algName) {
- return algAliasesMap.get(algName.toUpperCase(Locale.US));
+ return algAliasesMap.get(algName.toUpperCase(Locale.ROOT));
}
// Searches given provider for mappings like
@@ -185,11 +204,11 @@
for (String service : serviceName) {
String keyPrfix2find = "Alg.Alias." + service + ".";
for (Entry<Object, Object> me : entrySet) {
- String key = (String)me.getKey();
+ String key = (String) me.getKey();
if (key.startsWith(keyPrfix2find)) {
String alias = key.substring(keyPrfix2find.length());
- String alg = (String)me.getValue();
- String algUC = alg.toUpperCase(Locale.US);
+ String alg = (String) me.getValue();
+ String algUC = alg.toUpperCase(Locale.ROOT);
if (isOID(alias)) {
if (alias.startsWith("OID.")) {
alias = alias.substring(4);
@@ -207,9 +226,9 @@
// map upper case alg name to its original name
algAliasesMap.put(algUC, alg);
}
- // Do not override known standard names
- } else if (!algAliasesMap.containsKey(alias.toUpperCase(Locale.US))) {
- algAliasesMap.put(alias.toUpperCase(Locale.US), alg);
+ // Do not override known standard names
+ } else if (!algAliasesMap.containsKey(alias.toUpperCase(Locale.ROOT))) {
+ algAliasesMap.put(alias.toUpperCase(Locale.ROOT), alg);
}
}
}
diff --git a/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java b/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java
new file mode 100644
index 0000000..3e9183a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/cert/FakeOidProvider.java
@@ -0,0 +1,69 @@
+package libcore.java.security.cert;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+
+public class FakeOidProvider extends Provider {
+ /**
+ * Used for testing some effects of algorithm OID mapping. We have to be
+ * slightly careful of the OID we pick here: the first number has to be 0,
+ * 1, or 2, and the second number has to be less than 39.
+ */
+ public static final String SIGALG_OID = "1.2.34359737229.1.1.5";
+
+ /**
+ * Used for testing some effects of algorithm OID mapping.
+ */
+ public static final String SIGALG_OID_NAME = "FAKEwithFAKE";
+
+ public static final String PROVIDER_NAME = "FakeOidProvider";
+
+ protected FakeOidProvider() {
+ super(PROVIDER_NAME, 1.0, "Fake OID Provider for Tests");
+
+ put("Signature." + SIGALG_OID, FakeOidSignature.class.getName());
+ }
+
+ public static class FakeOidSignature extends SignatureSpi {
+ @Override
+ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+ }
+
+ @Override
+ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+ }
+
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ }
+
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+ }
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ return null;
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ return true;
+ }
+
+ @Override
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ }
+
+ @Override
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
+ return null;
+ }
+ }
+}
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
index c35f8e6..5ddbed3 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
@@ -16,6 +16,8 @@
package libcore.java.security.cert;
+import org.apache.harmony.security.utils.AlgNameMapper;
+
import tests.support.resource.Support_Resources;
import java.io.BufferedInputStream;
@@ -294,6 +296,8 @@
generateCertificates_PKCS7_PEM_TrailingData(f);
generateCertificates_PKCS7_DER_TrailingData(f);
test_Serialization(f);
+ test_UnknownUnmappedKeyOID(f);
+ test_UnknownMappedKeyOID(f);
} catch (Throwable e) {
out.append("Error encountered checking " + p.getName() + "\n");
e.printStackTrace(out);
@@ -1174,7 +1178,7 @@
Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
f.generateCertificates(bais);
if (StandardNames.IS_RI) {
- fail("RI fails on this test.");
+ return;
}
} catch (CertificateParsingException e) {
if (StandardNames.IS_RI) {
@@ -1204,7 +1208,7 @@
Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
f.generateCertificates(bais);
if (StandardNames.IS_RI) {
- fail("RI fails on this test.");
+ return;
}
} catch (CertificateParsingException e) {
if (StandardNames.IS_RI) {
@@ -1249,12 +1253,7 @@
Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>)
f.generateCertificates(bais);
- // RI is broken
- if (StandardNames.IS_RI) {
- assertEquals(0, bais.available());
- } else {
- assertEquals(4096, bais.available());
- }
+ assertEquals(4096, bais.available());
}
private void test_Serialization(CertificateFactory f) throws Exception {
@@ -1284,6 +1283,89 @@
}
}
+ private void test_UnknownUnmappedKeyOID(CertificateFactory f) throws Exception {
+ byte[] certBytes = generateFakeOidCertificate();
+
+ {
+ X509Certificate cert = (X509Certificate) f
+ .generateCertificate(new ByteArrayInputStream(certBytes));
+ assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgOID());
+ assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgName());
+ }
+ }
+
+ private void test_UnknownMappedKeyOID(CertificateFactory f) throws Exception {
+ AlgNameMapper.addMapping(FakeOidProvider.SIGALG_OID, FakeOidProvider.SIGALG_OID_NAME);
+
+ Security.addProvider(new FakeOidProvider());
+ try {
+ byte[] certBytes = generateFakeOidCertificate();
+
+ // Make sure the certificate is outputting something.
+ X509Certificate cert = (X509Certificate) f
+ .generateCertificate(new ByteArrayInputStream(certBytes));
+ assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgOID());
+ if ("AndroidOpenSSL".equals(f.getProvider().getName())) {
+ // AndroidOpenSSL provider has a connection to AlgNameMapper, so
+ // we expect it to get our special name.
+ assertEquals(FakeOidProvider.SIGALG_OID_NAME, cert.getSigAlgName());
+ } else {
+ assertNotNull(cert.getSigAlgName());
+ }
+
+ cert.verify(cert.getPublicKey());
+ } finally {
+ AlgNameMapper
+ .removeMapping(FakeOidProvider.SIGALG_OID, FakeOidProvider.SIGALG_OID_NAME);
+ Security.removeProvider(FakeOidProvider.PROVIDER_NAME);
+ }
+ }
+
+ private byte[] generateFakeOidCertificate() throws IOException {
+ byte[] certBytes;
+
+ // Read in the original cert.
+ {
+ InputStream is = null;
+ try {
+ is = Support_Resources.getStream(CERT_RSA);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[2048];
+ int numRead;
+ while ((numRead = is.read(buffer, 0, buffer.length)) != -1) {
+ baos.write(buffer, 0, numRead);
+ }
+ certBytes = baos.toByteArray();
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+
+ // Fix the OID for the certificate.
+ {
+ int numFixed = 0;
+ for (int i = 0; i < certBytes.length - 5; i++) {
+ if (certBytes[i] == (byte) 0x2A && certBytes[i + 1] == (byte) 0x86
+ && certBytes[i + 2] == (byte) 0x48 && certBytes[i + 3] == (byte) 0x86
+ && certBytes[i + 4] == (byte) 0xF7) {
+ certBytes[i + 1] = (byte) 0xFF;
+ certBytes[i + 2] = (byte) 0xFF;
+ certBytes[i + 3] = (byte) 0xFF;
+ i += 4;
+ numFixed++;
+ }
+ }
+ assertEquals(3, numFixed);
+ }
+ return certBytes;
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();