view patches/security/20121016/7186286.patch @ 2593:6df81d93af9c

Add 2012/10/16 security updates. 2012-10-11 Andrew John Hughes <gnu.andrew@redhat.com> * Makefile.am: (SECURITY_PATCHES): Add new patches. * patches/ecj/override.patch: Add new cases in P11Key and RMIConnectionImpl introduced by security patches. * patches/ssl.patch: Removed old unneeded patch which breaks with this update. * patches/security/20111018/7092186.patch: Backport of patch added to OpenJDK6 by Oracle as part of the last security update but not included in the bundle delivered ahead of time. * patches/security/20121016/6631398.patch, * patches/security/20121016/7093490.patch, * patches/security/20121016/7143535.patch, * patches/security/20121016/7158801.patch, * patches/security/20121016/7167656.patch, * patches/security/20121016/7169884.patch, * patches/security/20121016/7169888.patch, * patches/security/20121016/7172522.patch, * patches/security/20121016/7176337.patch, * patches/security/20121016/7186286.patch, * patches/security/20121016/7189103.patch, * patches/security/20121016/7189490.patch, * patches/security/20121016/7189567.patch, * patches/security/20121016/7192975.patch, * patches/security/20121016/7195194.patch, * patches/security/20121016/7195917.patch, * patches/security/20121016/7195919.patch, * patches/security/20121016/7198296.patch, * patches/security/20121016/7198606.patch, * patches/security/20121016/hs20/7158800.patch, * patches/security/20121016/hs20/7158804.patch, * patches/security/20121016/original/7158800.patch, * patches/security/20121016/original/7158804.patch: New patches.
author Andrew John Hughes <ahughes@redhat.com>
date Fri, 12 Oct 2012 02:18:24 +0100
parents
children
line wrap: on
line source

# HG changeset patch
# User xuelei
# Date 1343546404 25200
# Node ID a6294da5a21f609b67a0d4d216028dda9f56e689
# Parent  88243aa6e67b6b84ff529ccdfd3b476410f60057
7186286: TLS implementation to better adhere to RFC
Summary: also reviewed by Alexander Fomin <Alexander.Fomin@Oracle.COM>, Andrew Gross<Andrew.Gross@Oracle.COM>, Sean Coffey<Sean.Coffey@Oracle.COM>
Reviewed-by: valeriep, wetmore

diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -650,7 +650,7 @@
     // see JCE spec
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
         int n = P11SecretKeyFactory.convertKey
-                                (token, key, keyAlgorithm).keyLength();
+                                (token, key, keyAlgorithm).length();
         return n;
     }
 }
diff --git a/src/share/classes/sun/security/pkcs11/P11Key.java b/src/share/classes/sun/security/pkcs11/P11Key.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -46,6 +46,7 @@
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
 import sun.security.util.DerValue;
+import sun.security.util.Length;
 
 /**
  * Key implementation classes.
@@ -61,7 +62,7 @@
  * @author  Andreas Sterbenz
  * @since   1.5
  */
-abstract class P11Key implements Key {
+abstract class P11Key implements Key, Length {
 
     private final static String PUBLIC = "public";
     private final static String PRIVATE = "private";
@@ -212,7 +213,11 @@
         return s1;
     }
 
-    int keyLength() {
+    /**
+     * Return bit length of the key.
+     */
+    @Override
+    public int length() { 
         return keyLength;
     }
 
diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -201,7 +201,7 @@
         } else {
             throw new InvalidKeyException("Unknown key type: " + p11Key);
         }
-        int n = (p11Key.keyLength() + 7) >> 3;
+        int n = (p11Key.length() + 7) >> 3;
         outputSize = n;
         buffer = new byte[n];
         maxInputSize = encrypt ? (n - PKCS1_MIN_PADDING_LENGTH) : n;
@@ -458,7 +458,7 @@
 
     // see JCE spec
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
-        int n = P11KeyFactory.convertKey(token, key, algorithm).keyLength();
+        int n = P11KeyFactory.convertKey(token, key, algorithm).length();
         return n;
     }
 }
diff --git a/src/share/classes/sun/security/pkcs11/P11Signature.java b/src/share/classes/sun/security/pkcs11/P11Signature.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -274,7 +274,7 @@
                 if (keyAlgorithm.equals("DSA")) {
                     signature = new byte[40];
                 } else {
-                    signature = new byte[(p11Key.keyLength() + 7) >> 3];
+                    signature = new byte[(p11Key.length() + 7) >> 3];
                 }
                 if (type == T_UPDATE) {
                     token.p11.C_VerifyFinal(session.id(), signature);
@@ -359,7 +359,7 @@
         if (keyAlgorithm.equals("RSA") && publicKey != p11Key) {
             int keyLen;
             if (publicKey instanceof P11Key) {
-                keyLen = ((P11Key) publicKey).keyLength();
+                keyLen = ((P11Key) publicKey).length();
             } else {
                 keyLen = ((RSAKey) publicKey).getModulus().bitLength();
             }
@@ -620,7 +620,7 @@
 
     private byte[] pkcs1Pad(byte[] data) {
         try {
-            int len = (p11Key.keyLength() + 7) >> 3;
+            int len = (p11Key.length() + 7) >> 3;
             RSAPadding padding = RSAPadding.getInstance
                                         (RSAPadding.PAD_BLOCKTYPE_1, len);
             byte[] padded = padding.pad(data);
diff --git a/src/share/classes/sun/security/ssl/HandshakeInStream.java b/src/share/classes/sun/security/ssl/HandshakeInStream.java
--- openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -190,6 +190,7 @@
 
     byte[] getBytes8() throws IOException {
         int len = getInt8();
+        verifyLength(len);
         byte b[] = new byte[len];
 
         read(b, 0, len);
@@ -198,6 +199,7 @@
 
     byte[] getBytes16() throws IOException {
         int len = getInt16();
+        verifyLength(len);
         byte b[] = new byte[len];
 
         read(b, 0, len);
@@ -206,10 +208,19 @@
 
     byte[] getBytes24() throws IOException {
         int len = getInt24();
+        verifyLength(len);
         byte b[] = new byte[len];
 
         read(b, 0, len);
         return b;
     }
 
+    // Is a length greater than available bytes in the record?
+    private void verifyLength(int len) throws SSLException {
+        if (len > available()) {
+            throw new SSLException(
+                        "Not enough data to fill declared vector size");
+        }
+    }
+
 }
diff --git a/src/share/classes/sun/security/ssl/Handshaker.java b/src/share/classes/sun/security/ssl/Handshaker.java
--- openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -776,9 +776,9 @@
             if (debug != null && Debug.isOn("handshake")) {
                 System.out.println("RSA master secret generation error:");
                 e.printStackTrace(System.out);
-                System.out.println("Generating new random premaster secret");
             }
-            preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+            preMasterSecret =
+                    RSAClientKeyExchange.generateDummySecret(protocolVersion);
             // recursive call with new premaster secret
             return calculateMasterSecret(preMasterSecret, null);
         }
@@ -821,9 +821,9 @@
             System.out.println("RSA PreMasterSecret version error: expected"
                 + protocolVersion + " or " + requestedVersion + ", decrypted: "
                 + premasterVersion);
-            System.out.println("Generating new random premaster secret");
         }
-        preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
+        preMasterSecret =
+                RSAClientKeyExchange.generateDummySecret(protocolVersion);
         // recursive call with new premaster secret
         return calculateMasterSecret(preMasterSecret, null);
     }
diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
--- openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -36,6 +36,7 @@
 import javax.net.ssl.*;
 
 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.util.KeyLength;
 
 /**
  * This is the client key exchange message (CLIENT --> SERVER) used with
@@ -85,7 +86,8 @@
      * it, using its RSA private key.  Result is the same size as the
      * server's public key, and uses PKCS #1 block format 02.
      */
-    RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
+    RSAClientKeyExchange(ProtocolVersion protocolVersion,
+            ProtocolVersion maxVersion,
             SecureRandom generator, PublicKey publicKey) throws IOException {
         if (publicKey.getAlgorithm().equals("RSA") == false) {
             throw new SSLKeyException("Public key not of type RSA");
@@ -120,7 +122,8 @@
      * Server gets the PKCS #1 (block format 02) data, decrypts
      * it with its private key.
      */
-    RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
+    RSAClientKeyExchange(ProtocolVersion currentVersion,
+            ProtocolVersion maxVersion, HandshakeInStream input,
             int messageSize, PrivateKey privateKey) throws IOException {
 
         if (privateKey.getAlgorithm().equals("RSA") == false) {
@@ -143,28 +146,119 @@
             cipher.init(Cipher.UNWRAP_MODE, privateKey);
             preMaster = (SecretKey)cipher.unwrap(encrypted,
                                 "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
+
+            // polish the premaster secret
+            preMaster = polishPreMasterSecretKey(
+                                currentVersion, maxVersion, preMaster, null);
         } catch (Exception e) {
-            /*
-             * Bogus decrypted ClientKeyExchange? If so, conjure a
-             * a random preMaster secret that will fail later during
-             * Finished message processing. This is a countermeasure against
-             * the "interactive RSA PKCS#1 encryption envelop attack" reported
-             * in June 1998. Preserving the executation path will
-             * mitigate timing attacks and force consistent error handling
-             * that will prevent an attacking client from differentiating
-             * different kinds of decrypted ClientKeyExchange bogosities.
-             */
-            if (debug != null && Debug.isOn("handshake")) {
-                System.out.println("Error decrypting premaster secret:");
-                e.printStackTrace(System.out);
-                System.out.println("Generating random secret");
+            // polish the premaster secret
+            preMaster = polishPreMasterSecretKey(
+                                currentVersion, maxVersion, preMaster, e);
+        }
+    }
+
+    /**
+     * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
+     * treating incorrectly formatted message blocks and/or mismatched
+     * version numbers in a manner indistinguishable from correctly
+     * formatted RSA blocks.
+     *
+     * RFC 5246 describes the approach as :
+     *
+     *  1. Generate a string R of 46 random bytes
+     *
+     *  2. Decrypt the message to recover the plaintext M
+     *
+     *  3. If the PKCS#1 padding is not correct, or the length of message
+     *     M is not exactly 48 bytes:
+     *        pre_master_secret = ClientHello.client_version || R
+     *     else If ClientHello.client_version <= TLS 1.0, and version
+     *     number check is explicitly disabled:
+     *        pre_master_secret = M
+     *     else:
+     *        pre_master_secret = ClientHello.client_version || M[2..47]
+     *
+     * Note that although TLS 1.2 is not supported in this release, we still
+     * want to make use of the above approach to provide better protection.
+     */
+    private SecretKey polishPreMasterSecretKey(
+            ProtocolVersion currentVersion, ProtocolVersion clientHelloVersion,
+            SecretKey secretKey, Exception failoverException) {
+
+        if (failoverException == null && secretKey != null) {
+            // check the length
+            byte[] encoded = secretKey.getEncoded();
+            if (encoded == null) {      // unable to get the encoded key
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "unable to get the plaintext of the premaster secret");
+                }
+
+                int keySize = KeyLength.getKeySize(secretKey);
+                if (keySize > 0 && keySize != 384) {       // 384 = 48 * 8
+                    if (debug != null && Debug.isOn("handshake")) {
+                        System.out.println(
+                            "incorrect length of premaster secret: " +
+                            (keySize/8));
+                    }
+
+                    return generateDummySecret(currentVersion);
+                }
+
+                // The key size is exactly 48 bytes or not accessible.
+                //
+                // Conservatively, pass the checking to master secret
+                // calculation.
+                return secretKey;
+            } else if (encoded.length == 48) {
+                // check the version
+                if (clientHelloVersion.major == encoded[0] &&
+                    clientHelloVersion.minor == encoded[1]) {
+
+                    return secretKey;
+                } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
+                           currentVersion.major == encoded[0] &&
+                           currentVersion.minor == encoded[1]) {
+                    /*
+                     * For compatibility, we maintain the behavior that the
+                     * version in pre_master_secret can be the negotiated
+                     * version for TLS v1.0 and SSL v3.0.
+                     */
+                    return secretKey;
+                }
+
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println("Mismatching Protocol Versions, " +
+                        "ClientHello.client_version is " + clientHelloVersion +
+                        ", while PreMasterSecret.client_version is " +
+                        ProtocolVersion.valueOf(encoded[0], encoded[1]));
+                }
+                return generateDummySecret(currentVersion);
+            } else {
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println(
+                        "incorrect length of premaster secret: " +
+                        encoded.length);
+                }
+                return generateDummySecret(currentVersion);
             }
-            preMaster = generateDummySecret(currentVersion);
         }
+
+        if (debug != null && Debug.isOn("handshake") &&
+                        failoverException != null) {
+            System.out.println("Error decrypting premaster secret:");
+            failoverException.printStackTrace(System.out);
+        }
+
+        return generateDummySecret(currentVersion);
     }
 
     // generate a premaster secret with the specified version number
     static SecretKey generateDummySecret(ProtocolVersion version) {
+        if (debug != null && Debug.isOn("handshake")) {
+            System.out.println("Generating a random fake premaster secret");
+        }
+
         try {
             KeyGenerator kg =
                     JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java
--- openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -190,8 +190,9 @@
                      * temporary one used for non-export or signing-only
                      * certificates/keys.
                      */
-                    RSAClientKeyExchange pms = new RSAClientKeyExchange
-                        (protocolVersion, input, message_len, privateKey);
+                    RSAClientKeyExchange pms = new RSAClientKeyExchange(
+                            protocolVersion, clientRequestedVersion,
+                            input, message_len, privateKey);
                     preMasterSecret = this.clientKeyExchange(pms);
                     break;
                 case K_KRB5:
diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java
new file mode 100644
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/security/util/KeyLength.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.security.Key;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.DSAKey;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHKey;
+
+/**
+ * A utility class to get key length
+ */
+public final class KeyLength {
+
+    /**
+     * Returns the key size of the given key object in bits.
+     *
+     * @param key the key object, cannot be null
+     * @return the key size of the given key object in bits, or -1 if the
+     *       key size is not accessible
+     */
+    final public static int getKeySize(Key key) {
+        int size = -1;
+
+        if (key instanceof Length) {
+            try {
+                Length ruler = (Length)key;
+                size = ruler.length();
+            } catch (UnsupportedOperationException usoe) {
+                // ignore the exception
+            }
+
+            if (size >= 0) {
+                return size;
+            }
+        }
+
+        // try to parse the length from key specification
+        if (key instanceof SecretKey) {
+            SecretKey sk = (SecretKey)key;
+            String format = sk.getFormat();
+            if ("RAW".equals(format) && sk.getEncoded() != null) {
+                size = (sk.getEncoded().length * 8);
+            }   // Otherwise, it may be a unextractable key of PKCS#11, or
+                // a key we are not able to handle.
+        } else if (key instanceof RSAKey) {
+            RSAKey pubk = (RSAKey)key;
+            size = pubk.getModulus().bitLength();
+        } else if (key instanceof ECKey) {
+            ECKey pubk = (ECKey)key;
+            size = pubk.getParams().getOrder().bitLength();
+        } else if (key instanceof DSAKey) {
+            DSAKey pubk = (DSAKey)key;
+            size = pubk.getParams().getP().bitLength();
+        } else if (key instanceof DHKey) {
+            DHKey pubk = (DHKey)key;
+            size = pubk.getParams().getP().bitLength();
+        }   // Otherwise, it may be a unextractable key of PKCS#11, or
+            // a key we are not able to handle.
+
+        return size;
+    }
+}
+
diff --git a/src/share/classes/sun/security/util/Length.java b/src/share/classes/sun/security/util/Length.java
new file mode 100644
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/security/util/Length.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+/**
+ * The Length interface defines the length of an object
+ */
+public interface Length {
+
+    /**
+     * Gets the length of this object
+     * <p>
+     * Note that if a class of java.security.Key implements this interfaces,
+     * the length should be measured in bits.
+     *
+     * @return the length of this object
+     * @throws UnsupportedOperationException if the operation is not supported
+     */
+    public int length();
+}