diff options
26 files changed, 474 insertions, 377 deletions
diff --git a/JavaLibrary.mk b/JavaLibrary.mk index 64f99d8..a731aee 100644 --- a/JavaLibrary.mk +++ b/JavaLibrary.mk @@ -50,7 +50,7 @@ $(shell cd $(LOCAL_PATH) && ls -d */src/$(1)/{java,resources} 2> /dev/null) endef # The Java files and their associated resources. -core_src_files := $(call all-main-java-files-under,dalvik dom json luni openssl support xml ../external/bouncycastle) +core_src_files := $(call all-main-java-files-under,dalvik dom json luni support xml) core_resource_dirs := $(call all-core-resource-dirs,main) test_resource_dirs := $(call all-core-resource-dirs,test) @@ -151,6 +151,7 @@ LOCAL_NO_STANDARD_LIBRARIES := true # libraries. # TODO: we should have a bogus module that just contains tests.AllTests for speed. LOCAL_JAVA_LIBRARIES := \ + bouncycastle \ core \ core-junit \ core-junitrunner \ @@ -172,7 +173,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-test-java-files-under,support) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := core core-junit core-junitrunner +LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit core-junitrunner LOCAL_DX_FLAGS := --core-library LOCAL_MODULE_TAGS := tests LOCAL_MODULE := core-tests-support @@ -193,7 +194,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-test-java-files-under,support) LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs) LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_JAVA_LIBRARIES := core core-junit core-junitrunner +LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit core-junitrunner LOCAL_DX_FLAGS := --core-library LOCAL_MODULE_TAGS := tests LOCAL_MODULE := core-tests-supportlib diff --git a/luni/src/main/java/java/math/BigInt.java b/luni/src/main/java/java/math/BigInt.java index 70448ee..9f828d0 100644 --- a/luni/src/main/java/java/math/BigInt.java +++ b/luni/src/main/java/java/math/BigInt.java @@ -17,7 +17,6 @@ package java.math; import java.util.Random; -import org.openssl.NativeBN; /* * In contrast to BigIntegers this class doesn't fake two's complement representation. diff --git a/openssl/src/main/java/org/openssl/NativeBN.java b/luni/src/main/java/java/math/NativeBN.java index 7653cba..1fc228b 100644 --- a/openssl/src/main/java/org/openssl/NativeBN.java +++ b/luni/src/main/java/java/math/NativeBN.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package org.openssl; +package java.math; -public class NativeBN { +final class NativeBN { public static native int ERR_get_error(); // unsigned long ERR_get_error(void); diff --git a/luni/src/main/java/java/security/Provider.java b/luni/src/main/java/java/security/Provider.java index 81137ad..d1d9c4d 100644 --- a/luni/src/main/java/java/security/Provider.java +++ b/luni/src/main/java/java/security/Provider.java @@ -549,8 +549,7 @@ public abstract class Provider extends Properties { if (sm != null) { sm.checkSecurityAccess("putProviderProperty." + name); } - if ("Provider".equals(s.getType())) { // Provider service type cannot be - // added + if ("Provider".equals(s.getType())) { // Provider service type cannot be added return; } servicesChanged(); @@ -562,8 +561,8 @@ public abstract class Provider extends Properties { if (aliasTable == null) { aliasTable = new TwoKeyHashMap<String, String, Service>(256); } - for (Iterator<String> it = s.getAliases(); it.hasNext();) { - aliasTable.put(s.type, Util.toUpperCase(it.next()), s); + for (String alias : s.getAliases()) { + aliasTable.put(s.type, Util.toUpperCase(alias), s); } } serviceInfoToProperties(s); @@ -599,14 +598,16 @@ public abstract class Provider extends Properties { serviceTable.remove(s.type, Util.toUpperCase(s.algorithm)); } if (aliasTable != null && s.aliases != null) { - for (Iterator<String> it = s.getAliases(); it.hasNext();) { - aliasTable.remove(s.type, Util.toUpperCase(it.next())); + for (String alias: s.getAliases()) { + aliasTable.remove(s.type, Util.toUpperCase(alias)); } } serviceInfoFromProperties(s); } - // Add Service information to the provider's properties. + /** + * Add Service information to the provider's properties. + */ private void serviceInfoToProperties(Provider.Service s) { super.put(s.type + "." + s.algorithm, s.className); if (s.aliases != null) { @@ -615,8 +616,7 @@ public abstract class Provider extends Properties { } } if (s.attributes != null) { - for (Iterator<Map.Entry<String, String>> i = s.attributes.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, String> entry = i.next(); + for (Map.Entry<String, String> entry : s.attributes.entrySet()) { super.put(s.type + "." + s.algorithm + " " + entry.getKey(), entry.getValue()); } @@ -627,7 +627,9 @@ public abstract class Provider extends Properties { } } - // Remove Service information from the provider's properties. + /** + * Remove Service information from the provider's properties. + */ private void serviceInfoFromProperties(Provider.Service s) { super.remove(s.type + "." + s.algorithm); if (s.aliases != null) { @@ -636,8 +638,7 @@ public abstract class Provider extends Properties { } } if (s.attributes != null) { - for (Iterator<Map.Entry<String, String>> i = s.attributes.entrySet().iterator(); i.hasNext();) { - Map.Entry<String, String> entry = i.next(); + for (Map.Entry<String, String> entry : s.attributes.entrySet()) { super.remove(s.type + "." + s.algorithm + " " + entry.getKey()); } } @@ -692,7 +693,8 @@ public abstract class Provider extends Properties { serviceName = k.substring(0, j); algorithm = k.substring(j + 1); if (propertyServiceTable != null) { - Provider.Service ser = propertyServiceTable.remove(serviceName, Util.toUpperCase(algorithm)); + Provider.Service ser = propertyServiceTable.remove(serviceName, + Util.toUpperCase(algorithm)); if (ser != null && propertyAliasTable != null && ser.aliases != null) { for (Iterator<String> it = ser.aliases.iterator(); it.hasNext();) { @@ -701,8 +703,9 @@ public abstract class Provider extends Properties { } } } - } else { // <crypto_service>.<algorithm_or_type> - // <attribute_name>=<attrValue> + } else { + // <crypto_service>.<algorithm_or_type> + // <attribute_name>=<attrValue> attribute = k.substring(i + 1); serviceName = k.substring(0, j); algorithm = k.substring(j + 1, i); @@ -737,11 +740,13 @@ public abstract class Provider extends Properties { } String key = (String) _key; String value = (String) _value; - if (key.startsWith("Provider")) { // Provider service type is reserved + if (key.startsWith("Provider")) { + // Provider service type is reserved continue; } int i; - if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> + if (key.startsWith("Alg.Alias.")) { + // Alg.Alias.<crypto_service>.<aliasName>=<standardName> String aliasName; String service_alias = key.substring(10); i = service_alias.indexOf('.'); @@ -811,8 +816,9 @@ public abstract class Provider extends Properties { propertyServiceTable.put(serviceName, alg, s); } - } else { // <crypto_service>.<algorithm_or_type> - // <attribute_name>=<attrValue> + } else { + // <crypto_service>.<algorithm_or_type> + // <attribute_name>=<attrValue> serviceName = key.substring(0, j); algorithm = key.substring(j + 1, i); String attribute = key.substring(i + 1); @@ -854,9 +860,11 @@ public abstract class Provider extends Properties { lastServicesSet = null; } - // These attributes should be placed in each Provider object: - // Provider.id name, Provider.id version, Provider.id info, - // Provider.id className + /** + * These attributes should be placed in each Provider object: + * Provider.id name, Provider.id version, Provider.id info, + * Provider.id className + */ @SuppressWarnings("nls") private void putProviderInfo() { super.put("Provider.id name", null != name ? name : "null"); @@ -865,11 +873,13 @@ public abstract class Provider extends Properties { super.put("Provider.id className", this.getClass().getName()); } - // Searches for the property with the specified key in the provider - // properties. Key is not case-sensitive. - // - // @param prop - // @return the property value with the specified key value. + /** + * Searches for the property with the specified key in the + * provider properties. Key is not case-sensitive. + * + * @param prop + * @return the property value with the specified key value. + */ private String getPropertyIgnoreCase(String key) { String res = getProperty(key); if (res != null) { @@ -1042,11 +1052,11 @@ public abstract class Provider extends Properties { return attributes.get(name); } - Iterator<String> getAliases() { - if(aliases == null){ + List<String> getAliases() { + if (aliases == null){ aliases = new ArrayList<String>(0); } - return aliases.iterator(); + return aliases; } /** @@ -1080,7 +1090,9 @@ public abstract class Provider extends Properties { implementation = Class.forName(className, true, cl); } catch (Exception e) { - return new NoSuchAlgorithmException(type + " " + algorithm + " implementation not found: " + e); + return new NoSuchAlgorithmException( + type + " " + algorithm + + " implementation not found: " + e); } lastClassName = className; return null; @@ -1094,7 +1106,8 @@ public abstract class Provider extends Properties { try { return implementation.newInstance(); } catch (Exception e) { - throw new NoSuchAlgorithmException(type + " " + algorithm + " implementation not found", e); + throw new NoSuchAlgorithmException( + type + " " + algorithm + " implementation not found", e); } } if (!supportsParameter(constructorParameter)) { @@ -1113,7 +1126,8 @@ public abstract class Provider extends Properties { return implementation.getConstructor(parameterTypes) .newInstance(initargs); } catch (Exception e) { - throw new NoSuchAlgorithmException(type + " " + algorithm + " implementation not found", e); + throw new NoSuchAlgorithmException(type + " " + algorithm + + " implementation not found", e); } } @@ -1150,7 +1164,8 @@ public abstract class Provider extends Properties { } } - private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException { + private void readObject(java.io.ObjectInputStream in) + throws NotActiveException, IOException, ClassNotFoundException { in.defaultReadObject(); versionString = String.valueOf(version); providerNumber = -1; diff --git a/luni/src/main/java/java/security/Security.java b/luni/src/main/java/java/security/Security.java index 6c94e79..af8e916 100644 --- a/luni/src/main/java/java/security/Security.java +++ b/luni/src/main/java/java/security/Security.java @@ -17,25 +17,24 @@ package java.security; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -// BEGIN android-added -import java.util.logging.Level; -import java.util.logging.Logger; -// END android-added -import java.util.Enumeration; import java.net.URL; +import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.Map.Entry; - +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.harmony.security.Util; import org.apache.harmony.security.fortress.Engine; import org.apache.harmony.security.fortress.PolicyUtils; @@ -131,10 +130,11 @@ public final class Security { // Register default providers private static void registerDefaultProviders() { - secprops.put("security.provider.1", "org.apache.harmony.security.provider.cert.DRLCertFactory"); - secprops.put("security.provider.2", "org.apache.harmony.security.provider.crypto.CryptoProvider"); - secprops.put("security.provider.3", "org.apache.harmony.xnet.provider.jsse.JSSEProvider"); - secprops.put("security.provider.4", "org.bouncycastle.jce.provider.BouncyCastleProvider"); + secprops.put("security.provider.1", "org.apache.harmony.xnet.provider.jsse.OpenSSLProvider"); + secprops.put("security.provider.2", "org.bouncycastle.jce.provider.BouncyCastleProvider"); + secprops.put("security.provider.3", "org.apache.harmony.security.provider.cert.DRLCertFactory"); + secprops.put("security.provider.4", "org.apache.harmony.security.provider.crypto.CryptoProvider"); + secprops.put("security.provider.5", "org.apache.harmony.xnet.provider.jsse.JSSEProvider"); } /** @@ -526,7 +526,7 @@ public final class Security { } // Access to Security.getAliases() - public Iterator<String> getAliases(Provider.Service s) { + public List<String> getAliases(Provider.Service s) { return s.getAliases(); } diff --git a/luni/src/main/java/java/security/security.properties b/luni/src/main/java/java/security/security.properties index cc16be7..9d333b5 100644 --- a/luni/src/main/java/java/security/security.properties +++ b/luni/src/main/java/java/security/security.properties @@ -21,12 +21,14 @@ # Providers # See also: J2SE doc. "How to Implement a Provider for the JavaTM Cryptography Architecture" # +# Android's provider of OpenSSL backed implementations +security.provider.1=libcore.openssl.OpenSSLProvider +# Android's stripped down BouncyCastle provider +security.provider.2=org.bouncycastle.jce.provider.BouncyCastleProvider # Harmony providers -security.provider.1=org.apache.harmony.security.provider.cert.DRLCertFactory -security.provider.2=org.apache.harmony.security.provider.crypto.CryptoProvider -security.provider.3=org.apache.harmony.xnet.provider.jsse.JSSEProvider -# Other Open Source providers -security.provider.4=org.bouncycastle.jce.provider.BouncyCastleProvider +security.provider.3=org.apache.harmony.security.provider.cert.DRLCertFactory +security.provider.4=org.apache.harmony.security.provider.crypto.CryptoProvider +security.provider.5=org.apache.harmony.xnet.provider.jsse.JSSEProvider # # Class to instantiate as a default Configuration implementation @@ -85,9 +87,9 @@ jgss.spi.manager= # javax/net/ssl/SSLSocketFactory.html#getDefault() # javax/net/ssl/SSLServerSocketFactory.html#getDefault() -# BEGIN android-removed +# BEGIN android-changed ssl.SocketFactory.provider=org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl -# END android-removed +# END android-changed # BEGIN android-added # Use the definition above to get the new, OpenSSL-based SSL implementation, diff --git a/luni/src/main/java/java/util/jar/JarVerifier.java b/luni/src/main/java/java/util/jar/JarVerifier.java index 2324992..88373a3 100644 --- a/luni/src/main/java/java/util/jar/JarVerifier.java +++ b/luni/src/main/java/java/util/jar/JarVerifier.java @@ -37,10 +37,6 @@ import org.apache.harmony.security.utils.JarUtils; import org.apache.harmony.luni.util.Util; -// BEGIN android-added -import org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK; -// END android-added - /** * Non-public class used by {@link JarFile} and {@link JarInputStream} to manage * the verification of signed JARs. {@code JarFile} and {@code JarInputStream} @@ -217,10 +213,8 @@ class JarVerifier { byte[] hashBytes = hash.getBytes(Charsets.ISO_8859_1); try { - // BEGIN android-changed - return new VerifierEntry(name, OpenSSLMessageDigestJDK.getInstance(algorithm), - hashBytes, certificatesArray); - // END android-changed + return new VerifierEntry(name, MessageDigest + .getInstance(algorithm), hashBytes, certificatesArray); } catch (NoSuchAlgorithmException e) { // ignored } @@ -407,9 +401,7 @@ class JarVerifier { MessageDigest md; try { - // BEGIN android-changed - md = OpenSSLMessageDigestJDK.getInstance(algorithm); - // END android-changed + md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { continue; } diff --git a/luni/src/main/java/org/apache/harmony/security/fortress/SecurityAccess.java b/luni/src/main/java/org/apache/harmony/security/fortress/SecurityAccess.java index 6dd679f..be3e0cc 100644 --- a/luni/src/main/java/org/apache/harmony/security/fortress/SecurityAccess.java +++ b/luni/src/main/java/org/apache/harmony/security/fortress/SecurityAccess.java @@ -22,8 +22,8 @@ package org.apache.harmony.security.fortress; -import java.util.Iterator; import java.security.Provider; +import java.util.List; /** * @@ -42,7 +42,7 @@ public interface SecurityAccess { * @param s * @return */ - public Iterator<String> getAliases(Provider.Service s); + public List<String> getAliases(Provider.Service s); /** * Access to Provider.getService(String type) diff --git a/luni/src/main/java/org/apache/harmony/security/fortress/Services.java b/luni/src/main/java/org/apache/harmony/security/fortress/Services.java index 94c5667..7730fa6 100644 --- a/luni/src/main/java/org/apache/harmony/security/fortress/Services.java +++ b/luni/src/main/java/org/apache/harmony/security/fortress/Services.java @@ -49,7 +49,8 @@ public class Services { // BEGIN android-changed // set the initial size to 600 so we don't grow to 1024 by default because // initialization adds a few entries more than the growth threshold. - private static final Map<String, Provider.Service> services = new HashMap<String, Provider.Service>(600); + private static final Map<String, Provider.Service> services + = new HashMap<String, Provider.Service>(600); // END android-changed // Need refresh flag @@ -93,8 +94,8 @@ public class Services { initServiceInfo(p); } catch (ClassNotFoundException e) { // ignore Exceptions } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } + } catch (InstantiationException e) { + } } Engine.door.renumProviders(); } @@ -166,23 +167,17 @@ public class Services { * @param p */ public static void initServiceInfo(Provider p) { - Provider.Service serv; - String key; - String type; - String alias; StringBuilder sb = new StringBuilder(128); - for (Iterator<Provider.Service> it1 = p.getServices().iterator(); it1.hasNext();) { - serv = it1.next(); - type = serv.getType(); + for (Provider.Service serv : p.getServices()) { + String type = serv.getType(); sb.delete(0, sb.length()); - key = sb.append(type).append(".").append( + String key = sb.append(type).append(".").append( Util.toUpperCase(serv.getAlgorithm())).toString(); if (!services.containsKey(key)) { services.put(key, serv); } - for (Iterator<String> it2 = Engine.door.getAliases(serv); it2.hasNext();) { - alias = it2.next(); + for (String alias : Engine.door.getAliases(serv)) { sb.delete(0, sb.length()); key = sb.append(type).append(".").append(Util.toUpperCase(alias)) .toString(); @@ -200,8 +195,8 @@ public class Services { */ public static void updateServiceInfo() { services.clear(); - for (Iterator<Provider> it = providers.iterator(); it.hasNext();) { - initServiceInfo(it.next()); + for (Provider p : providers) { + initServiceInfo(p); } needRefresh = false; } @@ -227,19 +222,6 @@ public class Services { } /** - * Prints Services content - */ - // FIXME remove debug function - public static void printServices() { - refresh(); - Set<String> s = services.keySet(); - for (Iterator<String> i = s.iterator(); i.hasNext();) { - String key = i.next(); - System.out.println(key + "=" + services.get(key)); - } - } - - /** * Set flag needRefresh * */ @@ -257,4 +239,4 @@ public class Services { updateServiceInfo(); } } -}
\ No newline at end of file +} diff --git a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java index aeddd41..5870f60 100644 --- a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java +++ b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java @@ -38,23 +38,18 @@ import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Set; - import javax.security.auth.x500.X500Principal; - import org.apache.harmony.security.utils.AlgNameMapper; import org.apache.harmony.security.x509.Certificate; import org.apache.harmony.security.x509.Extension; import org.apache.harmony.security.x509.Extensions; import org.apache.harmony.security.x509.TBSCertificate; - -// BEGIN android-added -import java.security.interfaces.RSAPublicKey; import org.apache.harmony.xnet.provider.jsse.NativeCrypto; -// END android-added /** * This class is an implementation of X509Certificate. It wraps diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java index 02f37dc..9013eba 100644 --- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java +++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java @@ -36,20 +36,14 @@ import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; - import javax.security.auth.x500.X500Principal; - import org.apache.harmony.security.asn1.BerInputStream; import org.apache.harmony.security.pkcs7.ContentInfo; import org.apache.harmony.security.pkcs7.SignedData; import org.apache.harmony.security.pkcs7.SignerInfo; import org.apache.harmony.security.provider.cert.X509CertImpl; import org.apache.harmony.security.x501.AttributeTypeAndValue; - -// BEGIN android-added -import org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK; import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature; -// END android-added public class JarUtils { @@ -176,12 +170,7 @@ public class JarUtils { } } if (existingDigest != null) { - // BEGIN android-removed - // MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm()); - // END android-removed - // BEGIN android-added - MessageDigest md = OpenSSLMessageDigestJDK.getInstance(sigInfo.getDigestAlgorithm()); - // END android-added + MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm()); byte[] computedDigest = md.digest(sfBytes); if (!Arrays.equals(existingDigest, computedDigest)) { throw new SecurityException("Incorrect MD"); diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java index 0309838..a35fbac 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java @@ -154,7 +154,7 @@ abstract class AbstractSessionContext implements SSLSessionContext { } } - /** + /** * Called when a session is removed. Used by ClientSessionContext * to update its host-and-port based cache. */ diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java index cb7d6c9..35cac53 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java @@ -118,18 +118,6 @@ public final class JSSEProvider extends Provider { put("SSLContext.Default", DefaultSSLContextImpl.class.getName()); put("SSLContext.SSL", SSLContextImpl.class.getName()); put("Alg.Alias.SSLContext.SSLv3", "SSL"); - put("MessageDigest.SHA-1", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1"); - put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); - put("Alg.Alias.MessageDigest.SHA", "SHA-1"); - put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1"); - put("MessageDigest.SHA-224", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA224"); - put("Alg.Alias.MessageDigest.SHA224", "SHA-224"); - put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.4", "SHA-224"); - put("MessageDigest.SHA-256", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA256"); - put("Alg.Alias.MessageDigest.SHA256", "SHA-256"); - put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256"); - put("MessageDigest.MD5", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5"); - put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5"); // END android-added return null; } diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java index 7e6723e..63275f0 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java @@ -28,11 +28,9 @@ import java.util.List; import java.util.Map; /** - * Provides the Java side of our JNI glue for OpenSSL. Currently only - * hashing and verifying are covered. Is expected to grow over - * time. Also needs to move into libcore/openssl at some point. + * Provides the Java side of our JNI glue for OpenSSL. */ -public class NativeCrypto { +public final class NativeCrypto { // --- OpenSSL library initialization -------------------------------------- static { @@ -258,9 +256,9 @@ public class NativeCrypto { public static final String[] KEY_TYPES = new String[] { "RSA", "DSA", "DH_RSA" , "DH_DSA" }; - public static native void SSL_use_certificate(int ssl, byte[] pemEncodedCertificate); + public static native void SSL_use_certificate(int ssl, byte[][] asn1DerEncodedCertificate); - public static native void SSL_use_PrivateKey(int ssl, byte[] pemEncodedPrivateKey); + public static native void SSL_use_PrivateKey(int ssl, byte[] pkcs8EncodedPrivateKey); public static native void SSL_check_private_key(int ssl); @@ -302,8 +300,8 @@ public class NativeCrypto { optionsToSet &= ~SSL_OP_NO_TLSv1; optionsToClear |= SSL_OP_NO_TLSv1; } else { - throw new IllegalArgumentException("protocol " + protocol + - " is not supported"); + throw new IllegalArgumentException("protocol " + protocol + + " is not supported"); } } @@ -322,8 +320,8 @@ public class NativeCrypto { } if ((!protocol.equals(SUPPORTED_PROTOCOL_SSLV3)) && (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) { - throw new IllegalArgumentException("protocol " + protocol + - " is not supported"); + throw new IllegalArgumentException("protocol " + protocol + + " is not supported"); } } return protocols; diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigest.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigest.java deleted file mode 100644 index 0fd5879..0000000 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.harmony.xnet.provider.jsse; - -import org.bouncycastle.crypto.ExtendedDigest; - -import java.security.NoSuchAlgorithmException; - -/** - * Implements the BouncyCastle Digest interface using OpenSSL's EVP API. - */ -public class OpenSSLMessageDigest implements ExtendedDigest { - - /** - * Holds the name of the hashing algorithm, e.g. "SHA-1"; - */ - private String algorithm; - - /** - * Holds a pointer to the native message digest context. - */ - private int ctx; - - /** - * Holds a dummy buffer for writing single bytes to the digest. - */ - private byte[] singleByte = new byte[1]; - - /** - * Creates a new OpenSSLMessageDigest instance for the given algorithm - * name. - * - * @param algorithm The name of the algorithm, e.g. "SHA1". - * - * @return The new OpenSSLMessageDigest instance. - * - * @throws RuntimeException In case of problems. - */ - public static OpenSSLMessageDigest getInstance(String algorithm) { - return new OpenSSLMessageDigest(algorithm); - } - - /** - * Creates a new OpenSSLMessageDigest instance for the given algorithm - * name. - * - * @param algorithm The name of the algorithm, e.g. "SHA1". - */ - private OpenSSLMessageDigest(String algorithm) { - this.algorithm = algorithm; - - // We don't support MD2 anymore. This needs to also check for aliases - // and OIDs. - if ("MD2".equalsIgnoreCase(algorithm) || "1.2.840.113549.2.2" - .equals(algorithm)) { - throw new RuntimeException(algorithm + " not supported"); - } - - ctx = NativeCrypto.EVP_new(); - try { - NativeCrypto.EVP_DigestInit(ctx, algorithm.replace("-", "").toLowerCase()); - } catch (Exception ex) { - throw new RuntimeException(ex.getMessage() + " (" + algorithm + ")"); - } - } - - public int doFinal(byte[] out, int outOff) { - int i = NativeCrypto.EVP_DigestFinal(ctx, out, outOff); - reset(); - return i; - } - - public String getAlgorithmName() { - return algorithm; - } - - public int getDigestSize() { - return NativeCrypto.EVP_DigestSize(ctx); - } - - public int getByteLength() { - return NativeCrypto.EVP_DigestBlockSize(ctx); - } - - public void reset() { - NativeCrypto.EVP_DigestInit(ctx, algorithm.replace("-", "").toLowerCase()); - } - - public void update(byte in) { - singleByte[0] = in; - NativeCrypto.EVP_DigestUpdate(ctx, singleByte, 0, 1); - } - - public void update(byte[] in, int inOff, int len) { - NativeCrypto.EVP_DigestUpdate(ctx, in, inOff, len); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - NativeCrypto.EVP_free(ctx); - } - -} diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java new file mode 100644 index 0000000..01681f1 --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.xnet.provider.jsse; + +import java.security.Provider; + +public final class OpenSSLProvider extends Provider { + + public OpenSSLProvider() { + super("AndroidOpenSSL", 1.0, "Android's OpenSSL-backed security provider"); + + put("MessageDigest.SHA-1", + "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1"); + put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); + put("Alg.Alias.MessageDigest.SHA", "SHA-1"); + put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1"); + + put("MessageDigest.SHA-256", + "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA256"); + put("Alg.Alias.MessageDigest.SHA256", "SHA-256"); + put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256"); + + put("MessageDigest.SHA-384", + "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA384"); + put("Alg.Alias.MessageDigest.SHA384", "SHA-384"); + put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384"); + + put("MessageDigest.SHA-512", + "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA512"); + put("Alg.Alias.MessageDigest.SHA512", "SHA-512"); + put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512"); + + put("MessageDigest.MD5", + "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5"); + put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5"); + + // TODO Flush out implementation of OpenSSLSignature so it can be registered here + } +} diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java index c651213..5ea288f 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java @@ -16,6 +16,8 @@ package org.apache.harmony.xnet.provider.jsse; +import java.util.HashMap; +import java.util.Map; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; @@ -28,14 +30,57 @@ import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; /** - * Implements the JDK MessageDigest interface using OpenSSL's EVP API. + * Implements the subset of the JDK Signature interface needed for + * signature verification using OpenSSL. */ public class OpenSSLSignature extends Signature { + private static Map<String,Class<? extends OpenSSLSignature>> jdkToOpenSsl + = new HashMap<String,Class<? extends OpenSSLSignature>>(); + + static { + // TODO Finish OpenSSLSignature implementation and move + // registration information to the OpenSSLProvider + jdkToOpenSsl.put("MD5WithRSAEncryption", MD5RSA.class); + jdkToOpenSsl.put("MD5WithRSA", MD5RSA.class); + jdkToOpenSsl.put("MD5/RSA", MD5RSA.class); + jdkToOpenSsl.put("1.2.840.113549.1.1.4", MD5RSA.class); + jdkToOpenSsl.put("1.2.840.113549.2.5with1.2.840.113549.1.1.1", MD5RSA.class); + + jdkToOpenSsl.put("SHA1WithRSAEncryption", SHA1RSA.class); + jdkToOpenSsl.put("SHA1WithRSA", SHA1RSA.class); + jdkToOpenSsl.put("SHA1/RSA", SHA1RSA.class); + jdkToOpenSsl.put("SHA-1/RSA", SHA1RSA.class); + jdkToOpenSsl.put("1.2.840.113549.1.1.5", SHA1RSA.class); + jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.113549.1.1.1", SHA1RSA.class); + jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.113549.1.1.5", SHA1RSA.class); + jdkToOpenSsl.put("1.3.14.3.2.29", SHA1RSA.class); + + jdkToOpenSsl.put("SHA256WithRSAEncryption", SHA256RSA.class); + jdkToOpenSsl.put("SHA256WithRSA", SHA256RSA.class); + jdkToOpenSsl.put("1.2.840.113549.1.1.11", SHA256RSA.class); + + jdkToOpenSsl.put("SHA384WithRSAEncryption", SHA384RSA.class); + jdkToOpenSsl.put("SHA384WithRSA", SHA384RSA.class); + jdkToOpenSsl.put("1.2.840.113549.1.1.12", SHA384RSA.class); + + jdkToOpenSsl.put("SHA512WithRSAEncryption", SHA512RSA.class); + jdkToOpenSsl.put("SHA512WithRSA", SHA512RSA.class); + jdkToOpenSsl.put("1.2.840.113549.1.1.13", SHA512RSA.class); + + jdkToOpenSsl.put("SHA1withDSA", SHA1DSA.class); + jdkToOpenSsl.put("SHA/DSA", SHA1DSA.class); + jdkToOpenSsl.put("DSA", SHA1DSA.class); + jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.10040.4.1", SHA1DSA.class); + jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.10040.4.3", SHA1DSA.class); + jdkToOpenSsl.put("DSAWithSHA1", SHA1DSA.class); + jdkToOpenSsl.put("1.2.840.10040.4.3", SHA1DSA.class); + } + /** * Holds a pointer to the native message digest context. */ - private int ctx; + private final int ctx; /** * Holds a pointer to the native DSA key. @@ -50,63 +95,53 @@ public class OpenSSLSignature extends Signature { /** * Holds the OpenSSL name of the algorithm (lower case, no dashes). */ - private String evpAlgorithm; + private final String evpAlgorithm; /** * Holds a dummy buffer for writing single bytes to the digest. */ - private byte[] singleByte = new byte[1]; + private final byte[] singleByte = new byte[1]; /** * Creates a new OpenSSLSignature instance for the given algorithm name. * - * @param algorithm The name of the algorithm, e.g. "SHA1". + * @param algorithm The name of the algorithm, e.g. "SHA1WithRSA". * * @return The new OpenSSLSignature instance. * * @throws RuntimeException In case of problems. */ public static OpenSSLSignature getInstance(String algorithm) throws NoSuchAlgorithmException { - //log("OpenSSLSignature", "getInstance() invoked with " + algorithm); - return new OpenSSLSignature(algorithm); + // System.out.println("getInstance() invoked with " + algorithm); + + Class <? extends OpenSSLSignature> clazz = jdkToOpenSsl.get(algorithm); + if (clazz == null) { + throw new NoSuchAlgorithmException(algorithm); + } + try { + return clazz.newInstance(); + } catch (InstantiationException e) { + throw new NoSuchAlgorithmException(algorithm, e); + } catch (IllegalAccessException e) { + throw new NoSuchAlgorithmException(algorithm, e); + } } /** * Creates a new OpenSSLSignature instance for the given algorithm name. * - * @param algorithm The name of the algorithm, e.g. "SHA1". + * @param algorithm OpenSSL name of the algorithm, e.g. "RSA-SHA1". */ private OpenSSLSignature(String algorithm) throws NoSuchAlgorithmException { super(algorithm); - int i = algorithm.indexOf("with"); - if (i == -1) { + // We don't support MD2 + if ("RSA-MD2".equals(algorithm)) { throw new NoSuchAlgorithmException(algorithm); } - // We don't support MD2 anymore. This needs to also check for aliases - // and OIDs. - if ("MD2withRSA".equalsIgnoreCase(algorithm) || - "MD2withRSAEncryption".equalsIgnoreCase(algorithm) || - "1.2.840.113549.1.1.2".equalsIgnoreCase(algorithm) || - "MD2/RSA".equalsIgnoreCase(algorithm)) { - throw new NoSuchAlgorithmException("MD2withRSA"); - } - - // For the special combination of DSA and SHA1, we need to pass the - // algorithm name as a pair consisting of crypto algorithm and hash - // algorithm. For all other (RSA) cases, passing the hash algorithm - // alone is not only sufficient, but actually necessary. OpenSSL - // doesn't accept something like RSA-SHA1. - if ("1.3.14.3.2.26with1.2.840.10040.4.1".equals(algorithm) - || "SHA1withDSA".equals(algorithm) - || "SHAwithDSA".equals(algorithm)) { - evpAlgorithm = "DSA-SHA"; - } else { - evpAlgorithm = algorithm.substring(0, i).replace("-", "").toUpperCase(); - } - - ctx = NativeCrypto.EVP_new(); + this.evpAlgorithm = algorithm; + this.ctx = NativeCrypto.EVP_new(); } @Override @@ -136,7 +171,8 @@ public class OpenSSLSignature extends Signature { @Override protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { - //log("OpenSSLSignature", "engineInitVerify() invoked with " + publicKey.getClass().getCanonicalName()); + // System.out.println("engineInitVerify() invoked with " + // + publicKey.getClass().getCanonicalName()); if (publicKey instanceof DSAPublicKey) { try { @@ -212,4 +248,36 @@ public class OpenSSLSignature extends Signature { NativeCrypto.EVP_free(ctx); } } + + public static final class MD5RSA extends OpenSSLSignature { + public MD5RSA() throws NoSuchAlgorithmException { + super("RSA-MD5"); + } + } + public static final class SHA1RSA extends OpenSSLSignature { + public SHA1RSA() throws NoSuchAlgorithmException { + super("RSA-SHA1"); + } + } + public static final class SHA256RSA extends OpenSSLSignature { + public SHA256RSA() throws NoSuchAlgorithmException { + super("RSA-SHA256"); + } + } + public static final class SHA384RSA extends OpenSSLSignature { + public SHA384RSA() throws NoSuchAlgorithmException { + super("RSA-SHA384"); + } + } + public static final class SHA512RSA extends OpenSSLSignature { + public SHA512RSA() throws NoSuchAlgorithmException { + super("RSA-SHA512"); + } + } + public static final class SHA1DSA extends OpenSSLSignature { + public SHA1DSA() throws NoSuchAlgorithmException { + super("DSA-SHA1"); + } + } } + diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java index ed8861c..17ac99a 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java @@ -21,7 +21,6 @@ import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; - import org.apache.harmony.xnet.provider.jsse.SSLParameters; public class OpenSSLSocketFactoryImpl extends javax.net.ssl.SSLSocketFactory { diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java index b23f50e..0435717 100644 --- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java +++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java @@ -16,16 +16,15 @@ package org.apache.harmony.xnet.provider.jsse; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.security.PrivateKey; import java.security.SecureRandom; +import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -37,7 +36,6 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import org.apache.harmony.security.provider.cert.X509CertImpl; -import org.bouncycastle.openssl.PEMWriter; /** * Implementation of the class OpenSSLSocketImpl @@ -449,21 +447,18 @@ public class OpenSSLSocketImpl } PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); - ByteArrayOutputStream privateKeyOS = new ByteArrayOutputStream(); - PEMWriter privateKeyPEMWriter = new PEMWriter(new OutputStreamWriter(privateKeyOS)); - privateKeyPEMWriter.writeObject(privateKey); - privateKeyPEMWriter.close(); - byte[] privateKeyBytes = privateKeyOS.toByteArray(); + byte[] privateKeyBytes = privateKey.getEncoded(); NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); - ByteArrayOutputStream certificateOS = new ByteArrayOutputStream(); - PEMWriter certificateWriter = new PEMWriter(new OutputStreamWriter(certificateOS)); - for (X509Certificate certificate : certificates) { - certificateWriter.writeObject(certificate); + byte[][] certificateBytes = new byte[certificates.length][]; + for (int i = 0; i < certificates.length; i++) { + try { + certificateBytes[i] = certificates[i].getEncoded(); + } catch (CertificateEncodingException e) { + throw new IOException("Problem encoding certificate " + certificates[i], e); + } } - certificateWriter.close(); - byte[] certificateBytes = certificateOS.toByteArray(); // TODO SSL_use_certificate only looks at the first certificate in the chain. // It would be better to use a custom version of SSL_CTX_use_certificate_chain_file // to set the whole chain. Note there is no SSL_ equivalent of this SSL_CTX_ function. diff --git a/openssl/src/main/native/NativeBN.cpp b/luni/src/main/native/NativeBN.cpp index 3d129c8..ac9cd90 100644 --- a/openssl/src/main/native/NativeBN.cpp +++ b/luni/src/main/native/NativeBN.cpp @@ -546,6 +546,6 @@ static JNINativeMethod gMethods[] = { { "sign", "(I)I", (void*)NativeBN_sign }, { "twosComp2bn", "([BII)Z", (void*)NativeBN_twosComp2bn }, }; -int register_org_openssl_NativeBN(JNIEnv* env) { - return jniRegisterNativeMethods(env, "org/openssl/NativeBN", gMethods, NELEM(gMethods)); +int register_java_math_NativeBN(JNIEnv* env) { + return jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods)); } diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/NativeCrypto.cpp index 96ef89c..2a1b431 100644 --- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp +++ b/luni/src/main/native/NativeCrypto.cpp @@ -89,6 +89,13 @@ struct EVP_PKEY_Delete { }; typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; +struct PKCS8_PRIV_KEY_INFO_Delete { + void operator()(PKCS8_PRIV_KEY_INFO* p) const { + PKCS8_PRIV_KEY_INFO_free(p); + } +}; +typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO; + struct RSA_Delete { void operator()(RSA* p) const { RSA_free(p); @@ -600,7 +607,7 @@ static void NativeCrypto_EVP_DigestInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, js return; } - const EVP_MD *digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); + const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); if (digest == NULL) { jniThrowRuntimeException(env, "Hash algorithm not found"); @@ -682,7 +689,7 @@ static void NativeCrypto_EVP_VerifyInit(JNIEnv* env, jclass, EVP_MD_CTX* ctx, js return; } - const EVP_MD *digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); + const EVP_MD* digest = EVP_get_digestbynid(OBJ_txt2nid(algorithmChars.c_str())); if (digest == NULL) { jniThrowRuntimeException(env, "Hash algorithm not found"); @@ -785,7 +792,7 @@ static int rsaVerify(unsigned char* msg, unsigned int msgLen, unsigned char* sig } EVP_PKEY_set1_RSA(pkey.get(), rsa); - const EVP_MD *type = EVP_get_digestbyname(algorithm); + const EVP_MD* type = EVP_get_digestbyname(algorithm); if (type == NULL) { return -1; } @@ -1676,20 +1683,6 @@ static jint NativeCrypto_SSL_new(JNIEnv* env, jclass, jint ssl_ctx_address) return (jint)ssl.release(); } -/** - * Gets the bytes from a jbyteArray and stores them in a freshly-allocated BIO memory buffer. - */ -static BIO* jbyteArrayToMemBuf(JNIEnv* env, jbyteArray byteArray) { - ScopedByteArrayRO buf(env, byteArray); - Unique_BIO bio(BIO_new(BIO_s_mem())); - if (bio.get() == NULL) { - jniThrowRuntimeException(env, "BIO_new failed"); - return NULL; - } - BIO_write(bio.get(), buf.get(), buf.size()); - return bio.release(); -} - static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jint ssl_address, jbyteArray privatekey) { @@ -1701,17 +1694,29 @@ static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, if (privatekey == NULL) { jniThrowNullPointerException(env, "privatekey == null"); - JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => privatekey error", ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => privatekey == null", ssl); + return; + } + + ScopedByteArrayRO buf(env, privatekey); + const unsigned char* tmp = (const unsigned char*) buf.get(); + Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size())); + if (pkcs8.get() == NULL) { + LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, + "Error parsing private key from DER to PKCS8"); + SSL_clear(ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl); return; } - Unique_BIO privatekeybio(jbyteArrayToMemBuf(env, privatekey)); - Unique_EVP_PKEY privatekeyevp(PEM_read_bio_PrivateKey(privatekeybio.get(), NULL, 0, NULL)); + Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get())); if (privatekeyevp.get() == NULL) { LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); - throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing the private key"); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, + "Error creating private key from PKCS8"); SSL_clear(ssl); - JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => privatekeyevp error", ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from PKCS8 to key", ssl); return; } @@ -1720,7 +1725,7 @@ static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, privatekeyevp.release(); } else { LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); - throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting the private key"); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key"); SSL_clear(ssl); JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error", ssl); return; @@ -1730,7 +1735,7 @@ static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, } static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass, - jint ssl_address, jbyteArray certificates) + jint ssl_address, jobjectArray certificates) { SSL* ssl = to_SSL(env, ssl_address, true); JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate certificates=%p", ssl, certificates); @@ -1739,30 +1744,49 @@ static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass, } if (certificates == NULL) { - jniThrowNullPointerException(env, "privatekey == null"); - JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates error", ssl); + jniThrowNullPointerException(env, "certificates == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates == null", ssl); return; } - Unique_BIO certificatesbio(jbyteArrayToMemBuf(env, certificates)); - Unique_X509 certificatesx509(PEM_read_bio_X509(certificatesbio.get(), NULL, 0, NULL)); - - if (certificatesx509.get() == NULL) { - LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); - throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing the certificates"); - SSL_clear(ssl); - JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificatesx509 error", ssl); + int length = env->GetArrayLength(certificates); + if (length == 0) { + jniThrowException(env, "java/lang/IllegalArgumentException", "certificates.length == 0"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates.length == 0", ssl); return; } - int ret = SSL_use_certificate(ssl, certificatesx509.get()); + Unique_X509 certificatesX509[length]; + for (int i = 0; i < length; i++) { + ScopedLocalRef<jbyteArray> certificate(env, + reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(certificates, i))); + if (certificate.get() == NULL) { + jniThrowNullPointerException(env, "certificates element == null"); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates element null", ssl); + return; + } + + ScopedByteArrayRO buf(env, certificate.get()); + const unsigned char* tmp = (const unsigned char*) buf.get(); + certificatesX509[i].reset(d2i_X509(NULL, &tmp, buf.size())); + + if (certificatesX509[i].get() == NULL) { + LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate"); + SSL_clear(ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificates parsing error", ssl); + return; + } + } + + int ret = SSL_use_certificate(ssl, certificatesX509[0].get()); if (ret == 1) { - certificatesx509.release(); + certificatesX509[0].release(); } else { LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); - throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting the certificates"); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate"); SSL_clear(ssl); - JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => error", ssl); + JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => SSL_use_certificate error", ssl); return; } @@ -1778,7 +1802,7 @@ static void NativeCrypto_SSL_check_private_key(JNIEnv* env, jclass, jint ssl_add } int ret = SSL_check_private_key(ssl); if (ret != 1) { - throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking the private key"); + throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error checking private key"); SSL_clear(ssl); JNI_TRACE("ssl=%p NativeCrypto_SSL_check_private_key => error", ssl); return; @@ -2878,7 +2902,7 @@ static JNINativeMethod sNativeCryptoMethods[] = { { "SSL_CTX_free", "(I)V", (void*)NativeCrypto_SSL_CTX_free }, { "SSL_new", "(I)I", (void*)NativeCrypto_SSL_new}, { "SSL_use_PrivateKey", "(I[B)V", (void*)NativeCrypto_SSL_use_PrivateKey}, - { "SSL_use_certificate", "(I[B)V", (void*)NativeCrypto_SSL_use_certificate}, + { "SSL_use_certificate", "(I[[B)V", (void*)NativeCrypto_SSL_use_certificate}, { "SSL_check_private_key","(I)V", (void*)NativeCrypto_SSL_check_private_key}, { "SSL_get_mode", "(I)J", (void*)NativeCrypto_SSL_get_mode }, { "SSL_set_mode", "(IJ)J", (void*)NativeCrypto_SSL_set_mode }, diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp index 0e94531..01cf1c2 100644 --- a/luni/src/main/native/Register.cpp +++ b/luni/src/main/native/Register.cpp @@ -39,6 +39,7 @@ extern int register_java_lang_Math(JNIEnv* env); extern int register_java_lang_ProcessManager(JNIEnv* env); extern int register_java_lang_StrictMath(JNIEnv* env); extern int register_java_lang_System(JNIEnv* env); +extern int register_java_math_NativeBN(JNIEnv* env); extern int register_java_net_InetAddress(JNIEnv* env); extern int register_java_net_NetworkInterface(JNIEnv* env); extern int register_java_util_regex_Matcher(JNIEnv* env); @@ -60,7 +61,6 @@ extern int register_org_apache_harmony_luni_util_fltparse(JNIEnv* env); extern int register_org_apache_harmony_text_NativeBidi(JNIEnv* env); extern int register_org_apache_harmony_xml_ExpatParser(JNIEnv* env); extern int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env); -extern int register_org_openssl_NativeBN(JNIEnv* env); // DalvikVM calls this on startup, so we can statically register all our native methods. extern "C" int registerCoreLibrariesJni(JNIEnv* env) { @@ -87,6 +87,7 @@ extern "C" int registerCoreLibrariesJni(JNIEnv* env) { register_java_lang_ProcessManager(env) != -1 && register_java_lang_StrictMath(env) != -1 && register_java_lang_System(env) != -1 && + register_java_math_NativeBN(env) != -1 && register_java_net_InetAddress(env) != -1 && register_java_net_NetworkInterface(env) != -1 && register_java_util_regex_Matcher(env) != -1 && @@ -106,7 +107,6 @@ extern "C" int registerCoreLibrariesJni(JNIEnv* env) { register_org_apache_harmony_luni_util_fltparse(env) != -1 && register_org_apache_harmony_text_NativeBidi(env) != -1 && register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(env) != -1 && - register_org_openssl_NativeBN(env) != -1 && // Initialize the Android classes last, as they have dependencies on the "corer" core classes. android::register_dalvik_system_TouchDex(env) != -1 && register_org_apache_harmony_dalvik_NativeTestTarget(env) != -1 && diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk index d204d56..73ceedb 100644 --- a/luni/src/main/native/sub.mk +++ b/luni/src/main/native/sub.mk @@ -6,10 +6,12 @@ LOCAL_SRC_FILES := \ ErrorCode.cpp \ ICU.cpp \ JniConstants.cpp \ + NativeBN.cpp \ NativeBidi.cpp \ NativeBreakIterator.cpp \ NativeCollation.cpp \ NativeConverter.cpp \ + NativeCrypto.cpp \ NativeDecimalFormat.cpp \ NativeIDN.cpp \ NativeNormalizer.cpp \ @@ -46,7 +48,6 @@ LOCAL_SRC_FILES := \ org_apache_harmony_luni_util_NumberConvert.cpp \ org_apache_harmony_luni_util_fltparse.cpp \ org_apache_harmony_xml_ExpatParser.cpp \ - org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp \ valueOf.cpp diff --git a/luni/src/test/java/org/bouncycastle/crypto/digests/DigestTest.java b/luni/src/test/java/org/bouncycastle/crypto/digests/DigestTest.java new file mode 100644 index 0000000..7ad6254 --- /dev/null +++ b/luni/src/test/java/org/bouncycastle/crypto/digests/DigestTest.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bouncycastle.crypto.digests; + +import junit.framework.TestCase; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.ExtendedDigest; + +/** + * Implements unit tests for our JNI wrapper around OpenSSL. We use the + * existing Bouncy Castle implementation as our test oracle. + */ +public class DigestTest extends TestCase { + + /** + * Processes the two given message digests for the same data and checks + * the results. Requirement is that the results must be equal, the digest + * implementations must have the same properties, and the new implementation + * must be faster than the old one. + * + * @param oldDigest The old digest implementation, provided by Bouncy Castle + * @param newDigest The new digest implementation, provided by OpenSSL + */ + public void doTestMessageDigest(Digest oldDigest, Digest newDigest) { + final int ITERATIONS = 10; + + byte[] data = new byte[1024]; + + byte[] oldHash = new byte[oldDigest.getDigestSize()]; + byte[] newHash = new byte[newDigest.getDigestSize()]; + + assertEquals("Hash names must be equal", + oldDigest.getAlgorithmName(), newDigest.getAlgorithmName()); + assertEquals("Hash sizes must be equal", + oldHash.length, newHash.length); + assertEquals("Hash block sizes must be equal", + ((ExtendedDigest)oldDigest).getByteLength(), + ((ExtendedDigest)newDigest).getByteLength()); + for (int i = 0; i < data.length; i++) { + data[i] = (byte)i; + } + + long oldTime = 0; + long newTime = 0; + + for (int j = 0; j < ITERATIONS; j++) { + long t0 = System.currentTimeMillis(); + for (int i = 0; i < 4; i++) { + oldDigest.update(data, 0, data.length); + } + int oldLength = oldDigest.doFinal(oldHash, 0); + long t1 = System.currentTimeMillis(); + + oldTime = oldTime + (t1 - t0); + + long t2 = System.currentTimeMillis(); + for (int i = 0; i < 4; i++) { + newDigest.update(data, 0, data.length); + } + int newLength = newDigest.doFinal(newHash, 0); + long t3 = System.currentTimeMillis(); + + newTime = newTime + (t3 - t2); + + assertEquals("Hash sizes must be equal", oldLength, newLength); + + for (int i = 0; i < oldLength; i++) { + assertEquals("Hashes[" + i + "] must be equal", oldHash[i], newHash[i]); + } + } + + System.out.println("Time for " + ITERATIONS + " x old hash processing: " + oldTime + " ms"); + System.out.println("Time for " + ITERATIONS + " x new hash processing: " + newTime + " ms"); + + assertTrue("New hash should be faster", newTime < oldTime); + } + + /** + * Tests the MD5 implementation. + */ + public void testMD5() { + Digest oldDigest = new MD5Digest(); + Digest newDigest = new OpenSSLDigest.MD5(); + doTestMessageDigest(oldDigest, newDigest); + } + + /** + * Tests the SHA-1 implementation. + */ + public void testSHA1() { + Digest oldDigest = new SHA1Digest(); + Digest newDigest = new OpenSSLDigest.SHA1(); + doTestMessageDigest(oldDigest, newDigest); + } + + /** + * Tests the SHA-256 implementation. + */ + public void testSHA256() { + Digest oldDigest = new SHA256Digest(); + Digest newDigest = new OpenSSLDigest.SHA256(); + doTestMessageDigest(oldDigest, newDigest); + } + + /** + * Tests the SHA-384 implementation. + */ + public void testSHA384() { + Digest oldDigest = new SHA384Digest(); + Digest newDigest = new OpenSSLDigest.SHA384(); + doTestMessageDigest(oldDigest, newDigest); + } + + /** + * Tests the SHA-512 implementation. + */ + public void testSHA512() { + Digest oldDigest = new SHA512Digest(); + Digest newDigest = new OpenSSLDigest.SHA512(); + doTestMessageDigest(oldDigest, newDigest); + } +} diff --git a/openssl/src/main/native/sub.mk b/openssl/src/main/native/sub.mk deleted file mode 100644 index ce4d4d4..0000000 --- a/openssl/src/main/native/sub.mk +++ /dev/null @@ -1,18 +0,0 @@ -# This file is included by the top-level libcore Makefile. -# It's not a normal makefile, so we don't include CLEAR_VARS -# or BUILD_*_LIBRARY. - -LOCAL_SRC_FILES := \ - NativeBN.cpp - -LOCAL_C_INCLUDES += \ - external/openssl/include - -# Any shared/static libs that are listed here must also -# be listed in libs/nativehelper/Makefile. -# TODO: fix this requirement - -LOCAL_SHARED_LIBRARIES += \ - libcrypto - -LOCAL_STATIC_LIBRARIES += diff --git a/support/src/test/java/java/security/StandardNames.java b/support/src/test/java/java/security/StandardNames.java index 316b46e..ec34eda 100644 --- a/support/src/test/java/java/security/StandardNames.java +++ b/support/src/test/java/java/security/StandardNames.java @@ -263,7 +263,7 @@ public final class StandardNames extends Assert { unprovide("KeyManagerFactory", "SunX509"); provide("KeyManagerFactory", "X509"); - // different names SHA vs SHA-1 + // different names: BouncyCastle actually uses the Standard name of SHA-1 vs SHA unprovide("MessageDigest", "SHA"); provide("MessageDigest", "SHA-1"); @@ -287,10 +287,6 @@ public final class StandardNames extends Assert { // TODO remove one, probably Harmony's provide("CertificateFactory", "X509"); - // The Harmony JSSEProvider registers an OpenSSL based MessageDigest SHA-224 - // TODO remove it since the RI does not provide this variant - provide("MessageDigest", "SHA-224"); - // Harmony JSSEProvider is missing these // TODO add them unprovide("SSLContext", "SSLv3"); |