8062731: Cipher object can be created without calling Cipher.getInstance
authorvaleriep
Thu, 26 Jan 2017 22:56:02 +0000
changeset 43326 bbbdabc3f81b
parent 43324 10c580b0c3f4
child 43327 889efa087768
8062731: Cipher object can be created without calling Cipher.getInstance Summary: Fixed the check in JCE so that only trusted providers can extend Cipher class Reviewed-by: wetmore
jdk/src/java.base/share/classes/javax/crypto/JceSecurityManager.java
--- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurityManager.java	Thu Jan 26 21:21:16 2017 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurityManager.java	Thu Jan 26 22:56:02 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package javax.crypto;
 
+import java.lang.reflect.Module;
 import java.security.*;
 import java.net.*;
 import java.util.*;
@@ -227,38 +228,55 @@
         return (CryptoPermission)enum_.nextElement();
     }
 
-    // See  bug 4341369 & 4334690 for more info.
+    // Only used by javax.crypto.Cipher constructor to disallow Cipher
+    // objects being constructed by untrusted code (See bug 4341369 &
+    // 4334690 for more info).
     boolean isCallerTrusted(Provider provider) {
-        if (ProviderVerifier.isTrustedCryptoProvider(provider)) {
-            // fast path
-            return true;
-        }
-
         // Get the caller and its codebase.
         Class<?>[] context = getClassContext();
-        URL callerCodeBase = null;
-        int i;
-        for (i=0; i<context.length; i++) {
-            callerCodeBase = JceSecurity.getCodeBase(context[i]);
-            if (callerCodeBase != null) {
-                break;
+        if (context.length >= 3) {
+            // context[0]: class javax.crypto.JceSecurityManager
+            // context[1]: class javax.crypto.Cipher (or other JCE API class)
+            // context[2]: this is what we are gonna check
+            Class<?> caller = context[2];
+            URL callerCodeBase = JceSecurity.getCodeBase(caller);
+            if (callerCodeBase == null) {
+                return true;
+            }
+            // The caller has been verified.
+            if (TrustedCallersCache.contains(caller)) {
+                return true;
             }
-        }
-        // The caller is in the JCE framework.
-        if (i == context.length) {
+
+            // Check the association between caller and provider
+            Class<?> pCls = provider.getClass();
+            Module pMod = pCls.getModule();
+            // If they are in the same named module or share
+            // the same codebase, then they are associated
+            boolean sameOrigin = (pMod.isNamed()?
+                caller.getModule().equals(pMod) :
+                callerCodeBase.equals(JceSecurity.getCodeBase(pCls)));
+            if (sameOrigin) {
+                // The caller is from trusted provider
+                if (ProviderVerifier.isTrustedCryptoProvider(provider)) {
+                    TrustedCallersCache.addElement(caller);
+                    return true;
+                }
+            } else {
+                // Don't include the provider in the subsequent
+                // JceSecurity.verifyProvider(...) call
+                provider = null;
+            }
+
+            // Check whether the caller is a trusted provider.
+            try {
+                JceSecurity.verifyProvider(callerCodeBase, provider);
+            } catch (Exception e2) {
+                return false;
+            }
+            TrustedCallersCache.addElement(caller);
             return true;
         }
-        //The caller has been verified.
-        if (TrustedCallersCache.contains(context[i])) {
-            return true;
-        }
-        // Check whether the caller is a trusted provider.
-        try {
-            JceSecurity.verifyProvider(callerCodeBase, provider);
-        } catch (Exception e2) {
-            return false;
-        }
-        TrustedCallersCache.addElement(context[i]);
-        return true;
+        return false;
     }
 }