changeset 2969:9389cc43b7b8

Add 2013/02/19 security patches. 2013-02-15 Andrew John Hughes <gnu.andrew@redhat.com> * Makefile.am: (SECURITY_PATCHES): Add latest security patches. * patches/security/20130219/8006446.patch, * patches/security/20130219/8006777.patch, * patches/security/20130219/8007688.patch: New patches for next security update.
author Andrew John Hughes <gnu.andrew@redhat.com>
date Wed, 06 Mar 2013 19:22:19 +0000
parents ed710bbd6305
children 076acbb953a5
files ChangeLog Makefile.am patches/security/20130219/8006446.patch patches/security/20130219/8006777.patch patches/security/20130219/8007688.patch
diffstat 5 files changed, 1574 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Feb 20 13:11:53 2013 +1100
+++ b/ChangeLog	Wed Mar 06 19:22:19 2013 +0000
@@ -1,3 +1,12 @@
+2013-02-15  Andrew John Hughes  <gnu.andrew@redhat.com>
+
+	* Makefile.am:
+	(SECURITY_PATCHES): Add latest security patches.
+	* patches/security/20130219/8006446.patch,
+	* patches/security/20130219/8006777.patch,
+	* patches/security/20130219/8007688.patch:
+	New patches for next security update.
+
 2013-02-20  Andrew John Hughes  <gnu.andrew@redhat.com>
 
 	* NEWS:
--- a/Makefile.am	Wed Feb 20 13:11:53 2013 +1100
+++ b/Makefile.am	Wed Mar 06 19:22:19 2013 +0000
@@ -273,7 +273,10 @@
 	patches/security/20130201/8001242.patch \
 	patches/security/20130201/8001972.patch \
 	patches/security/20130201/8002325.patch \
-	patches/security/20130201/8001235.patch
+	patches/security/20130201/8001235.patch \
+	patches/security/20130219/8006446.patch \
+	patches/security/20130219/8006777.patch \
+	patches/security/20130219/8007688.patch
 
 if !WITH_ALT_HSBUILD
 SECURITY_PATCHES += \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20130219/8006446.patch	Wed Mar 06 19:22:19 2013 +0000
@@ -0,0 +1,395 @@
+diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java	2011-11-14 22:11:44.000000000 +0000
++++ openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java	2013-02-15 03:40:40.511587149 +0000
+@@ -36,6 +36,7 @@
+ 
+ import javax.management.ObjectName;
+ import javax.management.loading.PrivateClassLoader;
++import sun.reflect.misc.ReflectUtil;
+ 
+ /**
+  * This class keeps the list of Class Loaders registered in the MBean Server.
+@@ -192,6 +193,7 @@
+                             final ClassLoader without,
+                             final ClassLoader stop)
+             throws ClassNotFoundException {
++        ReflectUtil.checkPackageAccess(className);
+         final int size = list.length;
+         for(int i=0; i<size; i++) {
+             try {
+diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java	2011-11-14 22:11:44.000000000 +0000
++++ openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java	2013-02-15 03:40:40.511587149 +0000
+@@ -57,6 +57,7 @@
+ import javax.management.RuntimeOperationsException;
+ import javax.management.MBeanServer;
+ import javax.management.MBeanServerDelegate;
++import javax.management.MBeanServerPermission;
+ import javax.management.loading.ClassLoaderRepository;
+ 
+ import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
+@@ -1413,6 +1414,8 @@
+         // Default is true.
+         final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY;
+ 
++        checkNewMBeanServerPermission();
++
+         // This constructor happens to disregard the value of the interceptors
+         // flag - that is, it always uses the default value - false.
+         // This is admitedly a bug, but we chose not to fix it for now
+@@ -1499,4 +1502,11 @@
+         }
+     }
+ 
++    private static void checkNewMBeanServerPermission() {
++        SecurityManager sm = System.getSecurityManager();
++        if (sm != null) {
++            Permission perm = new MBeanServerPermission("newMBeanServer");
++            sm.checkPermission(perm);
++        }
++    }
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java	2011-11-14 22:11:44.000000000 +0000
++++ openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java	2013-02-15 03:40:40.511587149 +0000
+@@ -32,11 +32,13 @@
+ import java.io.ObjectInputStream;
+ import java.lang.reflect.Constructor;
+ import java.lang.reflect.InvocationTargetException;
++import java.security.Permission;
+ import java.util.Map;
+ import java.util.logging.Level;
+ 
+ import javax.management.InstanceNotFoundException;
+ import javax.management.MBeanException;
++import javax.management.MBeanPermission;
+ import javax.management.NotCompliantMBeanException;
+ import javax.management.ObjectName;
+ import javax.management.OperationsException;
+@@ -44,7 +46,7 @@
+ import javax.management.RuntimeErrorException;
+ import javax.management.RuntimeMBeanException;
+ import javax.management.RuntimeOperationsException;
+-
++import sun.reflect.misc.ConstructorUtil;
+ import sun.reflect.misc.ReflectUtil;
+ 
+ /**
+@@ -56,7 +58,6 @@
+  * @since 1.5
+  */
+ public class MBeanInstantiator {
+-
+     private final ModifiableClassLoaderRepository clr;
+     //    private MetaData meta = null;
+ 
+@@ -88,6 +89,7 @@
+                              "Exception occurred during object instantiation");
+         }
+ 
++        ReflectUtil.checkPackageAccess(className);
+         try {
+             if (clr == null) throw new ClassNotFoundException(className);
+             theClass = clr.loadClass(className);
+@@ -162,6 +164,7 @@
+                     continue;
+                 }
+ 
++                ReflectUtil.checkPackageAccess(signature[i]);
+                 // Ok we do not have a primitive type ! We need to build
+                 // the signature of the method
+                 //
+@@ -205,6 +208,9 @@
+      */
+     public Object instantiate(Class theClass)
+         throws ReflectionException, MBeanException {
++
++        checkMBeanPermission(theClass, null, null, "instantiate");
++
+         Object moi = null;
+ 
+ 
+@@ -260,6 +266,9 @@
+     public Object instantiate(Class theClass, Object params[],
+                               String signature[], ClassLoader loader)
+         throws ReflectionException, MBeanException {
++
++        checkMBeanPermission(theClass, null, null, "instantiate");
++
+         // Instantiate the new object
+ 
+         // ------------------------------
+@@ -408,6 +417,8 @@
+             throw new  RuntimeOperationsException(new
+              IllegalArgumentException(), "Null className passed in parameter");
+         }
++
++        ReflectUtil.checkPackageAccess(className);
+         Class theClass = null;
+         if (loaderName == null) {
+             // Load the class using the agent class loader
+@@ -620,13 +631,13 @@
+      **/
+     static Class loadClass(String className, ClassLoader loader)
+         throws ReflectionException {
+-
+         Class theClass = null;
+         if (className == null) {
+             throw new RuntimeOperationsException(new
+                 IllegalArgumentException("The class name cannot be null"),
+                               "Exception occurred during object instantiation");
+         }
++	ReflectUtil.checkPackageAccess(className);
+         try {
+             if (loader == null)
+                 loader = MBeanInstantiator.class.getClassLoader();
+@@ -677,6 +688,7 @@
+                 // We need to load the class through the class
+                 // loader of the target object.
+                 //
++                ReflectUtil.checkPackageAccess(signature[i]);
+                 tab[i] = Class.forName(signature[i], false, aLoader);
+             }
+         } catch (ClassNotFoundException e) {
+@@ -702,7 +714,7 @@
+ 
+     private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) {
+         try {
+-            return c.getConstructor(params);
++            return ConstructorUtil.getConstructor(c, params);
+         } catch (Exception e) {
+             return null;
+         }
+@@ -716,4 +728,18 @@
+                                        char.class, boolean.class})
+             primitiveClasses.put(c.getName(), c);
+     }
++
++    private static void checkMBeanPermission(Class<?> clazz,
++                                             String member,
++                                             ObjectName objectName,
++                                             String actions) {
++        SecurityManager sm = System.getSecurityManager();
++        if (clazz != null && sm != null) {
++            Permission perm = new MBeanPermission(clazz.getName(),
++                                                  member,
++                                                  objectName,
++                                                  actions);
++            sm.checkPermission(perm);
++        }
++    }
+ }
+diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java
+--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java	2011-11-14 22:11:44.000000000 +0000
++++ openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java	2013-02-15 03:40:40.511587149 +0000
+@@ -38,6 +38,7 @@
+ import javax.management.NotCompliantMBeanException;
+ import javax.management.ObjectName;
+ import javax.management.ReflectionException;
++import sun.reflect.misc.ReflectUtil;
+ 
+ /**
+  * Base class for MBeans.  There is one instance of this class for
+@@ -131,6 +132,7 @@
+                 " is not an instance of " + mbeanInterface.getName();
+             throw new NotCompliantMBeanException(msg);
+         }
++        ReflectUtil.checkPackageAccess(mbeanInterface);
+         this.resource = resource;
+         MBeanIntrospector<M> introspector = getMBeanIntrospector();
+         this.perInterface = introspector.getPerInterface(mbeanInterface);
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/management/LockDataConverter.java openjdk/jdk/src/share/classes/sun/management/LockDataConverter.java
+--- openjdk.orig/jdk/src/share/classes/sun/management/LockDataConverter.java	2011-11-14 22:12:00.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/management/LockDataConverter.java	2013-02-15 03:40:40.511587149 +0000
+@@ -27,6 +27,8 @@
+ 
+ import java.lang.management.LockInfo;
+ import java.lang.management.ThreadInfo;
++import java.security.AccessController;
++import java.security.PrivilegedAction;
+ import javax.management.Attribute;
+ import javax.management.StandardMBean;
+ import javax.management.openmbean.CompositeData;
+@@ -40,13 +42,13 @@
+     private LockInfo      lockInfo;
+     private LockInfo[]    lockedSyncs;
+ 
+-    LockDataConverter() {
++    private LockDataConverter() {
+         super(LockDataConverterMXBean.class, true);
+         this.lockInfo = null;
+         this.lockedSyncs = null;
+     }
+ 
+-    LockDataConverter(ThreadInfo ti) {
++    private LockDataConverter(ThreadInfo ti) {
+         super(LockDataConverterMXBean.class, true);
+         this.lockInfo = ti.getLockInfo();
+         this.lockedSyncs = ti.getLockedSynchronizers();
+@@ -104,8 +106,24 @@
+     }
+ 
+     static CompositeData toLockInfoCompositeData(LockInfo l) {
+-        LockDataConverter ldc = new LockDataConverter();
++        LockDataConverter ldc = newLockDataConverter();
+         ldc.setLockInfo(l);
+         return ldc.toLockInfoCompositeData();
+     }
++
++   static LockDataConverter newLockDataConverter() {
++        return AccessController.doPrivileged(new PrivilegedAction<LockDataConverter>() {
++               public LockDataConverter run() {
++                   return new LockDataConverter();
++               }
++        });
++   }
++
++   static LockDataConverter newLockDataConverter(final ThreadInfo ti) {
++        LockDataConverter result = newLockDataConverter();
++        result.lockInfo = ti.getLockInfo();
++        result.lockedSyncs = ti.getLockedSynchronizers();
++        return result;
++   }
+ }
++
+diff -Nru openjdk.orig/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java openjdk/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java
+--- openjdk.orig/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java	2011-11-14 22:12:01.000000000 +0000
++++ openjdk/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java	2013-02-15 03:40:40.511587149 +0000
+@@ -85,7 +85,7 @@
+         }
+ 
+         // Convert MonitorInfo[] and LockInfo[] to CompositeData[]
+-        LockDataConverter converter = new LockDataConverter(threadInfo);
++        LockDataConverter converter = LockDataConverter.newLockDataConverter(threadInfo);
+         CompositeData lockInfoData = converter.toLockInfoCompositeData();
+         CompositeData[] lockedSyncsData = converter.toLockedSynchronizersCompositeData();
+ 
+@@ -315,7 +315,7 @@
+ 
+     // 6.0 new attributes
+     public LockInfo lockInfo() {
+-        LockDataConverter converter = new LockDataConverter();
++        LockDataConverter converter = LockDataConverter.newLockDataConverter();
+         CompositeData lockInfoData = (CompositeData) cdata.get(LOCK_INFO);
+         return converter.toLockInfo(lockInfoData);
+     }
+@@ -336,7 +336,7 @@
+     }
+ 
+     public LockInfo[] lockedSynchronizers() {
+-        LockDataConverter converter = new LockDataConverter();
++        LockDataConverter converter = LockDataConverter.newLockDataConverter();
+         CompositeData[] lockedSyncsData =
+             (CompositeData[]) cdata.get(LOCKED_SYNCS);
+ 
+diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security openjdk/jdk/src/share/lib/security/java.security
+--- openjdk.orig/jdk/src/share/lib/security/java.security	2013-02-15 03:39:56.922892783 +0000
++++ openjdk/jdk/src/share/lib/security/java.security	2013-02-15 03:40:40.511587149 +0000
+@@ -131,8 +131,7 @@
+                com.sun.xml.internal.,\
+                com.sun.imageio.,\
+                com.sun.istack.internal.,\
+-               com.sun.jmx.defaults.,\
+-               com.sun.jmx.remote.util.
++               com.sun.jmx.
+ 
+ #
+ # List of comma-separated packages that start with or equal this string
+@@ -148,8 +147,7 @@
+                    com.sun.xml.internal.,\
+                    com.sun.imageio.,\
+                    com.sun.istack.internal.,\
+-                   com.sun.jmx.defaults.,\
+-                   com.sun.jmx.remote.util.
++                   com.sun.jmx.
+ 
+ #
+ # Determines whether this properties file can be appended to
+diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security-solaris openjdk/jdk/src/share/lib/security/java.security-solaris
+--- openjdk.orig/jdk/src/share/lib/security/java.security-solaris	2013-02-15 03:39:56.902892466 +0000
++++ openjdk/jdk/src/share/lib/security/java.security-solaris	2013-02-15 03:41:36.996489851 +0000
+@@ -131,6 +131,8 @@
+ package.access=sun.,\
+                com.sun.xml.internal.,\
+                com.sun.imageio.
++               com.sun.istack.internal.,\
++               com.sun.jmx.
+ 
+ #
+ # List of comma-separated packages that start with or equal this string
+@@ -145,6 +147,8 @@
+ package.definition=sun.,\
+                    com.sun.xml.internal.,\
+                    com.sun.imageio.
++                   com.sun.istack.internal.,\
++                   com.sun.jmx.
+ 
+ #
+ # Determines whether this properties file can be appended to
+diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security-windows openjdk/jdk/src/share/lib/security/java.security-windows
+--- openjdk.orig/jdk/src/share/lib/security/java.security-windows	2013-02-15 03:39:56.902892466 +0000
++++ openjdk/jdk/src/share/lib/security/java.security-windows	2013-02-15 03:42:05.304943135 +0000
+@@ -131,6 +131,8 @@
+ package.access=sun.,\
+                com.sun.xml.internal.,\
+                com.sun.imageio.
++               com.sun.istack.internal.,\
++               com.sun.jmx.
+ 
+ #
+ # List of comma-separated packages that start with or equal this string
+@@ -145,6 +147,8 @@
+ package.definition=sun.,\
+                    com.sun.xml.internal.,\
+                    com.sun.imageio.
++                   com.sun.istack.internal.,\
++                   com.sun.jmx.
+ 
+ #
+ # Determines whether this properties file can be appended to
+diff -Nru openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java
+--- openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java	2011-11-14 22:12:28.000000000 +0000
++++ openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java	2013-02-15 03:40:40.511587149 +0000
+@@ -119,9 +119,6 @@
+             System.out.println("Create SimpleStandard MBean");
+             SimpleStandard s = new SimpleStandard("monitorRole");
+             mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard"));
+-            // Set Security Manager
+-            //
+-            System.setSecurityManager(new SecurityManager());
+             // Create Properties containing the username/password entries
+             //
+             Properties props = new Properties();
+@@ -132,6 +129,9 @@
+             HashMap env = new HashMap();
+             env.put("jmx.remote.authenticator",
+                     new JMXPluggableAuthenticator(props));
++            // Set Security Manager
++            //
++            System.setSecurityManager(new SecurityManager());
+             // Create an RMI connector server
+             //
+             System.out.println("Create an RMI connector server");
+diff -Nru openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java
+--- openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java	2011-11-14 22:12:28.000000000 +0000
++++ openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java	2013-02-15 03:40:40.511587149 +0000
+@@ -120,9 +120,6 @@
+             System.out.println("Create SimpleStandard MBean");
+             SimpleStandard s = new SimpleStandard("delegate");
+             mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard"));
+-            // Set Security Manager
+-            //
+-            System.setSecurityManager(new SecurityManager());
+             // Create Properties containing the username/password entries
+             //
+             Properties props = new Properties();
+@@ -133,6 +130,9 @@
+             HashMap env = new HashMap();
+             env.put("jmx.remote.authenticator",
+                     new JMXPluggableAuthenticator(props));
++            // Set Security Manager
++            //
++            System.setSecurityManager(new SecurityManager());
+             // Create an RMI connector server
+             //
+             System.out.println("Create an RMI connector server");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20130219/8006777.patch	Wed Mar 06 19:22:19 2013 +0000
@@ -0,0 +1,1036 @@
+# HG changeset patch
+# User coffeys
+# Date 1360882104 0
+# Node ID 85b3b034fdecdc94f082efa8d74e014366502deb
+# Parent  617e68a3948824283f15c36fcd8cf264c1dd0a99
+8006777: Improve TLS handling of invalid messages
+Reviewed-by: wetmore
+
+diff --git a/src/share/classes/sun/security/ssl/CipherBox.java b/src/share/classes/sun/security/ssl/CipherBox.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/CipherBox.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherBox.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2013, 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
+@@ -244,7 +244,8 @@ final class CipherBox {
+      * Decrypts a block of data, returning the size of the
+      * resulting block if padding was required.
+      */
+-    int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
++    int decrypt(byte[] buf, int offset, int len,
++            int tagLen) throws BadPaddingException {
+         if (cipher == null) {
+             return len;
+         }
+@@ -268,8 +269,8 @@ final class CipherBox {
+                 } catch (IOException e) { }
+             }
+             if (blockSize != 0) {
+-                newLen = removePadding(buf, offset, newLen,
+-                             blockSize, protocolVersion);
++                newLen = removePadding(
++                    buf, offset, newLen, tagLen, blockSize, protocolVersion); 
+             }
+             return newLen;
+         } catch (ShortBufferException e) {
+@@ -285,7 +286,7 @@ final class CipherBox {
+      * limit and new limit may be different, given we may
+      * have stripped off some padding bytes.
+      */
+-    int decrypt(ByteBuffer bb) throws BadPaddingException {
++    int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
+ 
+         int len = bb.remaining();
+ 
+@@ -309,7 +310,6 @@ final class CipherBox {
+             }
+ 
+             if (debug != null && Debug.isOn("plaintext")) {
+-                bb.position(pos);
+                 try {
+                     HexDumpEncoder hd = new HexDumpEncoder();
+ 
+@@ -317,7 +317,8 @@ final class CipherBox {
+                         "Padded plaintext after DECRYPTION:  len = "
+                         + newLen);
+ 
+-                    hd.encodeBuffer(bb, System.out);
++                    hd.encodeBuffer(
++                        (ByteBuffer)bb.duplicate().position(pos), System.out);
+                 } catch (IOException e) { }
+             }
+ 
+@@ -326,7 +327,8 @@ final class CipherBox {
+              */
+             if (blockSize != 0) {
+                 bb.position(pos);
+-                newLen = removePadding(bb, blockSize, protocolVersion);
++                newLen = removePadding(
++                    bb, tagLen, blockSize, protocolVersion);
+             }
+             return newLen;
+         } catch (ShortBufferException e) {
+@@ -400,6 +402,65 @@ final class CipherBox {
+         return newlen;
+     }
+ 
++    /*
++     * A constant-time check of the padding.
++     *
++     * NOTE that we are checking both the padding and the padLen bytes here.
++     *
++     * The caller MUST ensure that the len parameter is a positive number.
++     */
++    private static int[] checkPadding(
++            byte[] buf, int offset, int len, byte pad) {
++
++        if (len <= 0) {
++            throw new RuntimeException("padding len must be positive");
++        }
++
++        // An array of hits is used to prevent Hotspot optimization for
++        // the purpose of a constant-time check
++        int[] results = {0, 0};    // {missed #, matched #}
++        for (int i = 0; i <= 256;) {
++            for (int j = 0; j < len && i <= 256; j++, i++) {     // j <= i
++                if (buf[offset + j] != pad) {
++                    results[0]++;       // mismatched padding data
++                } else {
++                    results[1]++;       // matched padding data
++                }
++            }
++        }
++
++        return results;
++    }
++
++    /*
++     * A constant-time check of the padding.
++     *
++     * NOTE that we are checking both the padding and the padLen bytes here.
++     *
++     * The caller MUST ensure that the bb parameter has remaining.
++     */
++    private static int[] checkPadding(ByteBuffer bb, byte pad) {
++
++        if (!bb.hasRemaining()) {
++            throw new RuntimeException("hasRemaining() must be positive");
++        }
++
++        // An array of hits is used to prevent Hotspot optimization for
++        // the purpose of a constant-time check.
++        int[] results = {0, 0};    // {missed #, matched #}
++        bb.mark();
++        for (int i = 0; i <= 256; bb.reset()) {
++            for (; bb.hasRemaining() && i <= 256; i++) {
++                if (bb.get() != pad) {
++                    results[0]++;       // mismatched padding data
++                } else {
++                    results[1]++;       // matched padding data
++                }
++            }
++        }
++
++        return results;
++    }
+ 
+     /*
+      * Typical TLS padding format for a 64 bit block cipher is as follows:
+@@ -412,86 +473,95 @@ final class CipherBox {
+      * as it makes the data a multiple of the block size
+      */
+     private static int removePadding(byte[] buf, int offset, int len,
+-            int blockSize, ProtocolVersion protocolVersion)
+-            throws BadPaddingException {
++            int tagLen, int blockSize,
++            ProtocolVersion protocolVersion) throws BadPaddingException {
++
+         // last byte is length byte (i.e. actual padding length - 1)
+         int padOffset = offset + len - 1;
+-        int pad = buf[padOffset] & 0x0ff;
++        int padLen = buf[padOffset] & 0xFF;
+ 
+-        int newlen = len - (pad + 1);
+-        if (newlen < 0) {
+-            throw new BadPaddingException("Padding length invalid: " + pad);
++        int newLen = len - (padLen + 1);
++        if ((newLen - tagLen) < 0) {
++            // If the buffer is not long enough to contain the padding plus
++            // a MAC tag, do a dummy constant-time padding check.
++            //
++            // Note that it is a dummy check, so we won't care about what is
++            // the actual padding data.
++            checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
++
++            throw new BadPaddingException("Invalid Padding length: " + padLen);
+         }
+ 
++        // The padding data should be filled with the padding length value.
++        int[] results = checkPadding(buf, offset + newLen,
++                        padLen + 1, (byte)(padLen & 0xFF));
+         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+-            for (int i = 1; i <= pad; i++) {
+-                int val = buf[padOffset - i] & 0xff;
+-                if (val != pad) {
+-                    throw new BadPaddingException
+-                                        ("Invalid TLS padding: " + val);
+-                }
++            if (results[0] != 0) {          // padding data has invalid bytes
++                throw new BadPaddingException("Invalid TLS padding data");
+             }
+         } else { // SSLv3
+             // SSLv3 requires 0 <= length byte < block size
+             // some implementations do 1 <= length byte <= block size,
+             // so accept that as well
+             // v3 does not require any particular value for the other bytes
+-            if (pad > blockSize) {
+-                throw new BadPaddingException("Invalid SSLv3 padding: " + pad);
++            if (padLen > blockSize) {
++                throw new BadPaddingException("Invalid SSLv3 padding");
+             }
+         }
+-        return newlen;
++        return newLen;
+     }
+ 
+     /*
+      * Position/limit is equal the removed padding.
+      */
+     private static int removePadding(ByteBuffer bb,
+-            int blockSize, ProtocolVersion protocolVersion)
+-            throws BadPaddingException {
++            int tagLen, int blockSize,
++            ProtocolVersion protocolVersion) throws BadPaddingException {
+ 
+         int len = bb.remaining();
+         int offset = bb.position();
+ 
+         // last byte is length byte (i.e. actual padding length - 1)
+         int padOffset = offset + len - 1;
+-        int pad = bb.get(padOffset) & 0x0ff;
++        int padLen = bb.get(padOffset) & 0xFF;
+ 
+-        int newlen = len - (pad + 1);
+-        if (newlen < 0) {
+-            throw new BadPaddingException("Padding length invalid: " + pad);
++        int newLen = len - (padLen + 1);
++        if ((newLen - tagLen) < 0) {
++            // If the buffer is not long enough to contain the padding plus
++            // a MAC tag, do a dummy constant-time padding check.
++            //
++            // Note that it is a dummy check, so we won't care about what is
++            // the actual padding data.
++            checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
++
++            throw new BadPaddingException("Invalid Padding length: " + padLen);
+         }
+ 
+-        /*
+-         * We could zero the padding area, but not much useful
+-         * information there.
+-         */
++        // The padding data should be filled with the padding length value.
++        int[] results = checkPadding(
++                (ByteBuffer)bb.duplicate().position(offset + newLen),
++                (byte)(padLen & 0xFF));
+         if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+-            bb.put(padOffset, (byte)0);         // zero the padding.
+-            for (int i = 1; i <= pad; i++) {
+-                int val = bb.get(padOffset - i) & 0xff;
+-                if (val != pad) {
+-                    throw new BadPaddingException
+-                                        ("Invalid TLS padding: " + val);
+-                }
++            if (results[0] != 0) {          // padding data has invalid bytes
++                throw new BadPaddingException("Invalid TLS padding data");
+             }
+         } else { // SSLv3
+             // SSLv3 requires 0 <= length byte < block size
+             // some implementations do 1 <= length byte <= block size,
+             // so accept that as well
+             // v3 does not require any particular value for the other bytes
+-            if (pad > blockSize) {
+-                throw new BadPaddingException("Invalid SSLv3 padding: " + pad);
++           if (padLen > blockSize) {
++                throw new BadPaddingException("Invalid SSLv3 padding");
+             }
+         }
+ 
+         /*
+          * Reset buffer limit to remove padding.
+          */
+-        bb.position(offset + newlen);
+-        bb.limit(offset + newlen);
++        bb.position(offset + newLen);
++        bb.limit(offset + newLen);
+ 
+-        return newlen;
++        return newLen;
+     }
+ 
+     /*
+@@ -502,4 +572,40 @@ final class CipherBox {
+     boolean isCBCMode() {
+         return isCBCMode;
+     }
++
++    /**
++     * Is the cipher null?
++     *
++     * @return true if the cipher is null, false otherwise.
++     */
++    boolean isNullCipher() {
++        return cipher == null;
++    }
++
++    /**
++     * Sanity check the length of a fragment before decryption.
++     *
++     * In CBC mode, check that the fragment length is one or multiple times
++     * of the block size of the cipher suite, and is at least one (one is the
++     * smallest size of padding in CBC mode) bigger than the tag size of the
++     * MAC algorithm.
++     *
++     * In non-CBC mode, check that the fragment length is not less than the
++     * tag size of the MAC algorithm.
++     *
++     * @return true if the length of a fragment matches above requirements
++     */
++    boolean sanityCheck(int tagLen, int fragmentLen) {
++        if (!isCBCMode) {
++            return fragmentLen >= tagLen;
++        }
++
++        if ((fragmentLen % blockSize) == 0) {
++            int minimal = tagLen + 1;
++            minimal = (minimal >= blockSize) ? minimal : blockSize;
++            return (fragmentLen >= minimal);
++        }
++
++        return false;
++    }
+ }
+diff --git a/src/share/classes/sun/security/ssl/CipherSuite.java b/src/share/classes/sun/security/ssl/CipherSuite.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2002, 2013, 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
+@@ -451,9 +451,18 @@ final class CipherSuite implements Compa
+         // size of the MAC value (and MAC key) in bytes
+         final int size;
+ 
+-        MacAlg(String name, int size) {
++        // block size of the underlying hash algorithm
++        final int hashBlockSize;
++
++        // minimal padding size of the underlying hash algorithm
++        final int minimalPaddingSize;
++
++        MacAlg(String name, int size,
++                int hashBlockSize, int minimalPaddingSize) {
+             this.name = name;
+             this.size = size;
++            this.hashBlockSize = hashBlockSize;
++            this.minimalPaddingSize = minimalPaddingSize;
+         }
+ 
+         /**
+@@ -497,9 +506,9 @@ final class CipherSuite implements Compa
+                         new BulkCipher(CIPHER_AES,     32, 16, true);
+ 
+     // MACs
+-    final static MacAlg M_NULL = new MacAlg("NULL", 0);
+-    final static MacAlg M_MD5  = new MacAlg("MD5", 16);
+-    final static MacAlg M_SHA  = new MacAlg("SHA", 20);
++    final static MacAlg M_NULL    = new MacAlg("NULL",     0,   0,   0);
++    final static MacAlg M_MD5     = new MacAlg("MD5",     16,  64,   9);
++    final static MacAlg M_SHA     = new MacAlg("SHA",     20,  64,   9);
+ 
+     static {
+         idMap = new HashMap<Integer,CipherSuite>();
+diff --git a/src/share/classes/sun/security/ssl/EngineInputRecord.java b/src/share/classes/sun/security/ssl/EngineInputRecord.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2013, 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
+@@ -177,71 +177,6 @@ final class EngineInputRecord extends In
+     }
+ 
+     /*
+-     * Verifies and removes the MAC value.  Returns true if
+-     * the MAC checks out OK.
+-     *
+-     * On entry:
+-     *     position = beginning of app/MAC data
+-     *     limit = end of MAC data.
+-     *
+-     * On return:
+-     *     position = beginning of app data
+-     *     limit = end of app data
+-     */
+-    boolean checkMAC(MAC signer, ByteBuffer bb) {
+-        if (internalData) {
+-            return checkMAC(signer);
+-        }
+-
+-        int len = signer.MAClen();
+-        if (len == 0) { // no mac
+-            return true;
+-        }
+-
+-        /*
+-         * Grab the original limit
+-         */
+-        int lim = bb.limit();
+-
+-        /*
+-         * Delineate the area to apply a MAC on.
+-         */
+-        int macData = lim - len;
+-        bb.limit(macData);
+-
+-        byte[] mac = signer.compute(contentType(), bb);
+-
+-        if (len != mac.length) {
+-            throw new RuntimeException("Internal MAC error");
+-        }
+-
+-        /*
+-         * Delineate the MAC values, position was already set
+-         * by doing the compute above.
+-         *
+-         * We could zero the MAC area, but not much useful information
+-         * there anyway.
+-         */
+-        bb.position(macData);
+-        bb.limit(lim);
+-
+-        try {
+-            for (int i = 0; i < len; i++) {
+-                if (bb.get() != mac[i]) {  // No BB.equals(byte []); !
+-                    return false;
+-                }
+-            }
+-            return true;
+-        } finally {
+-            /*
+-             * Position to the data.
+-             */
+-            bb.rewind();
+-            bb.limit(macData);
+-        }
+-    }
+-
+-    /*
+      * Pass the data down if it's internally cached, otherwise
+      * do it here.
+      *
+@@ -250,18 +185,161 @@ final class EngineInputRecord extends In
+      * If external data(app), return a new ByteBuffer with data to
+      * process.
+      */
+-    ByteBuffer decrypt(CipherBox box, ByteBuffer bb)
+-            throws BadPaddingException {
++    ByteBuffer decrypt(MAC signer,
++            CipherBox box, ByteBuffer bb) throws BadPaddingException {
+ 
+         if (internalData) {
+-            decrypt(box);
++            decrypt(signer, box);   // MAC is checked during decryption
+             return tmpBB;
+         }
+ 
+-        box.decrypt(bb);
+-        bb.rewind();
++        BadPaddingException reservedBPE = null;
++        int tagLen = signer.MAClen();
++        int cipheredLength = bb.remaining();
++
++        if (!box.isNullCipher()) {
++            // sanity check length of the ciphertext
++            if (!box.sanityCheck(tagLen, cipheredLength)) {
++                throw new BadPaddingException(
++                    "ciphertext sanity check failed");
++            }
++
++            try {
++                // Note that the CipherBox.decrypt() does not change
++                // the capacity of the buffer.
++                box.decrypt(bb, tagLen);
++            } catch (BadPaddingException bpe) {
++                // RFC 2246 states that decryption_failed should be used
++                // for this purpose. However, that allows certain attacks,
++                // so we just send bad record MAC. We also need to make
++                // sure to always check the MAC to avoid a timing attack
++                // for the same issue. See paper by Vaudenay et al and the
++                // update in RFC 4346/5246.
++                //
++                // Failover to message authentication code checking.
++                reservedBPE = bpe;
++            } finally {
++                bb.rewind();
++            }
++        }
++
++        if (tagLen != 0) {
++            int macOffset = bb.limit() - tagLen;
++
++            // Note that although it is not necessary, we run the same MAC
++            // computation and comparison on the payload for both stream
++            // cipher and CBC block cipher.
++            if (bb.remaining() < tagLen) {
++                // negative data length, something is wrong
++                if (reservedBPE == null) {
++                    reservedBPE = new BadPaddingException("bad record");
++                }
++
++                // set offset of the dummy MAC
++                macOffset = cipheredLength - tagLen;
++                bb.limit(cipheredLength);
++            }
++
++            // Run MAC computation and comparison on the payload.
++            if (checkMacTags(contentType(), bb, signer, false)) {
++                if (reservedBPE == null) {
++                    reservedBPE = new BadPaddingException("bad record MAC");
++                }
++            }
++
++            // Run MAC computation and comparison on the remainder.
++            //
++            // It is only necessary for CBC block cipher.  It is used to get a
++            // constant time of MAC computation and comparison on each record.
++            if (box.isCBCMode()) {
++                int remainingLen = calculateRemainingLen(
++                                        signer, cipheredLength, macOffset);
++
++                // NOTE: here we use the InputRecord.buf because I did not find
++                // an effective way to work on ByteBuffer when its capacity is 
++                // less than remainingLen.
++
++                // NOTE: remainingLen may be bigger (less than 1 block of the
++                // hash algorithm of the MAC) than the cipheredLength. However,
++                // We won't need to worry about it because we always use a
++                // maximum buffer for every record.  We need a change here if
++                // we use small buffer size in the future.
++                if (remainingLen > buf.length) {
++                    // unlikely to happen, just a placehold
++                    throw new RuntimeException(
++                        "Internal buffer capacity error");
++                }
++
++                // Won't need to worry about the result on the remainder. And
++                // then we won't need to worry about what's actual data to
++                // check MAC tag on.  We start the check from the header of the
++                // buffer so that we don't need to construct a new byte buffer.
++                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
++            }
++
++            bb.limit(macOffset);
++        }
++
++        // Is it a failover?
++        if (reservedBPE != null) {
++            throw reservedBPE;
++        }
+ 
+         return bb.slice();
++    }
++
++    /*
++     * Run MAC computation and comparison
++     *
++     * Please DON'T change the content of the ByteBuffer parameter!
++     */
++    private static boolean checkMacTags(byte contentType, ByteBuffer bb,
++            MAC signer, boolean isSimulated) {
++
++        int tagLen = signer.MAClen();
++        int lim = bb.limit();
++        int macData = lim - tagLen;
++
++        bb.limit(macData);
++        byte[] hash = signer.compute(contentType, bb, isSimulated);
++        if (hash == null || tagLen != hash.length) {
++            // Something is wrong with MAC implementation.
++            throw new RuntimeException("Internal MAC error");
++        }
++
++        bb.position(macData);
++        bb.limit(lim);
++        try {
++            int[] results = compareMacTags(bb, hash);
++            return (results[0] != 0);
++        } finally {
++            bb.rewind();
++            bb.limit(macData);
++        }
++    }
++
++    /*
++     * A constant-time comparison of the MAC tags.
++     *
++     * Please DON'T change the content of the ByteBuffer parameter!
++     */
++    private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
++
++        // An array of hits is used to prevent Hotspot optimization for
++        // the purpose of a constant-time check.
++        int[] results = {0, 0};     // {missed #, matched #}
++
++        // The caller ensures there are enough bytes available in the buffer.
++        // So we won't need to check the remaining of the buffer.
++        for (int i = 0; i < tag.length; i++) {
++            if (bb.get() != tag[i]) {
++                results[0]++;       // mismatched bytes
++            } else {
++                results[1]++;       // matched bytes
++            }
++        }
++
++        return results;
+     }
+ 
+     /*
+diff --git a/src/share/classes/sun/security/ssl/EngineOutputRecord.java b/src/share/classes/sun/security/ssl/EngineOutputRecord.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2013, 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
+@@ -120,7 +120,7 @@ final class EngineOutputRecord extends O
+             throws IOException {
+ 
+         if (signer.MAClen() != 0) {
+-            byte[] hash = signer.compute(contentType(), bb);
++            byte[] hash = signer.compute(contentType(), bb, false);
+ 
+             /*
+              * position was advanced to limit in compute above.
+diff --git a/src/share/classes/sun/security/ssl/InputRecord.java b/src/share/classes/sun/security/ssl/InputRecord.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/InputRecord.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/InputRecord.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2013, 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
+@@ -135,43 +135,173 @@ class InputRecord extends ByteArrayInput
+         return handshakeHash;
+     }
+ 
+-    /*
+-     * Verify and remove the MAC ... used for all records.
+-     */
+-    boolean checkMAC(MAC signer) {
+-        int len = signer.MAClen();
+-        if (len == 0) { // no mac
+-            return true;
++    void decrypt(MAC signer, CipherBox box) throws BadPaddingException {
++
++        BadPaddingException reservedBPE = null;
++        int tagLen = signer.MAClen();
++        int cipheredLength = count - headerSize;
++
++        if (!box.isNullCipher()) {
++            // sanity check length of the ciphertext
++            if (!box.sanityCheck(tagLen, cipheredLength)) {
++                throw new BadPaddingException(
++                    "ciphertext sanity check failed");
++            }
++
++            try {
++                // Note that the CipherBox.decrypt() does not change
++                // the capacity of the buffer.
++                count = headerSize +
++                        box.decrypt(buf, headerSize, cipheredLength, tagLen);
++            } catch (BadPaddingException bpe) {
++                // RFC 2246 states that decryption_failed should be used
++                // for this purpose. However, that allows certain attacks,
++                // so we just send bad record MAC. We also need to make
++                // sure to always check the MAC to avoid a timing attack
++                // for the same issue. See paper by Vaudenay et al and the
++                // update in RFC 4346/5246.
++                //
++                // Failover to message authentication code checking.
++                reservedBPE = bpe;
++            }
+         }
+ 
+-        int offset = count - len;
++        if (tagLen != 0) {
++            int macOffset = count - tagLen;
++            int contentLen = macOffset - headerSize;
+ 
+-        if (offset < headerSize) {
+-            // data length would be negative, something is wrong
+-            return false;
++            // Note that although it is not necessary, we run the same MAC
++            // computation and comparison on the payload for both stream
++            // cipher and CBC block cipher.
++            if (contentLen < 0) {
++                // negative data length, something is wrong
++                if (reservedBPE == null) {
++                    reservedBPE = new BadPaddingException("bad record");
++                }
++
++                // set offset of the dummy MAC
++                macOffset = headerSize + cipheredLength - tagLen;
++                contentLen = macOffset - headerSize;
++            }
++
++            count -= tagLen;  // Set the count before any MAC checking
++                              // exception occurs, so that the following
++                              // process can read the actual decrypted
++                              // content (minus the MAC) in the fragment
++                              // if necessary.
++
++            // Run MAC computation and comparison on the payload.
++            if (checkMacTags(contentType(),
++                    buf, headerSize, contentLen, signer, false)) {
++                if (reservedBPE == null) {
++                    reservedBPE = new BadPaddingException("bad record MAC");
++                }
++            }
++
++            // Run MAC computation and comparison on the remainder.
++            //
++            // It is only necessary for CBC block cipher.  It is used to get a
++            // constant time of MAC computation and comparison on each record.
++            if (box.isCBCMode()) {
++                int remainingLen = calculateRemainingLen(
++                                        signer, cipheredLength, contentLen);
++
++                // NOTE: remainingLen may be bigger (less than 1 block of the
++                // hash algorithm of the MAC) than the cipheredLength. However,
++                // We won't need to worry about it because we always use a
++                // maximum buffer for every record.  We need a change here if
++                // we use small buffer size in the future. 
++                if (remainingLen > buf.length) {
++                    // unlikely to happen, just a placehold
++                    throw new RuntimeException(
++                        "Internal buffer capacity error");
++                }
++
++                // Won't need to worry about the result on the remainder. And
++                // then we won't need to worry about what's actual data to
++                // check MAC tag on.  We start the check from the header of the
++                // buffer so that we don't need to construct a new byte buffer.
++                checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
++            }
+         }
+ 
+-        byte[] mac = signer.compute(contentType(), buf,
+-            headerSize, offset - headerSize);
++        // Is it a failover?
++        if (reservedBPE != null) {
++            throw reservedBPE;
++        }
++    }
+ 
+-        if (len != mac.length) {
++    /*
++     * Run MAC computation and comparison
++     *
++     * Please DON'T change the content of the byte buffer parameter!
++     */
++    static boolean checkMacTags(byte contentType, byte[] buffer,
++            int offset, int contentLen, MAC signer, boolean isSimulated) {
++
++        int tagLen = signer.MAClen();
++        byte[] hash = signer.compute(
++                contentType, buffer, offset, contentLen, isSimulated);
++        if (hash == null || tagLen != hash.length) {
++            // Something is wrong with MAC implementation.
+             throw new RuntimeException("Internal MAC error");
+         }
+ 
+-        for (int i = 0; i < len; i++) {
+-            if (buf[offset + i] != mac[i]) {
+-                return false;
++        int[] results = compareMacTags(buffer, offset + contentLen, hash);
++        return (results[0] != 0);
++    }
++
++    /*
++     * A constant-time comparison of the MAC tags.
++     *
++     * Please DON'T change the content of the byte buffer parameter!
++     */
++    private static int[] compareMacTags(
++            byte[] buffer, int offset, byte[] tag) {
++
++        // An array of hits is used to prevent Hotspot optimization for
++        // the purpose of a constant-time check.
++        int[] results = {0, 0};    // {missed #, matched #}
++
++        // The caller ensures there are enough bytes available in the buffer.
++        // So we won't need to check the length of the buffer.
++        for (int i = 0; i < tag.length; i++) {
++            if (buffer[offset + i] != tag[i]) {
++                results[0]++;       // mismatched bytes
++            } else {
++                results[1]++;       // matched bytes
+             }
+         }
+-        count -= len;
+-        return true;
++
++        return results;
+     }
+ 
+-    void decrypt(CipherBox box) throws BadPaddingException {
+-        int len = count - headerSize;
+-        count = headerSize + box.decrypt(buf, headerSize, len);
++    /*
++     * Calculate the length of a dummy buffer to run MAC computation
++     * and comparison on the remainder.
++     *
++     * The caller MUST ensure that the fullLen is not less than usedLen.
++     */
++    static int calculateRemainingLen(
++            MAC signer, int fullLen, int usedLen) {
++
++        int blockLen = signer.hashBlockLen();
++        int minimalPaddingLen = signer.minimalPaddingLen();
++
++        // (blockLen - minimalPaddingLen) is the maximum message size of
++        // the last block of hash function operation. See FIPS 180-4, or
++        // MD5 specification.
++        fullLen += 13 - (blockLen - minimalPaddingLen);
++        usedLen += 13 - (blockLen - minimalPaddingLen);
++
++        // Note: fullLen is always not less than usedLen, and blockLen
++        // is always bigger than minimalPaddingLen, so we don't worry
++        // about negative values. 0x01 is added to the result to ensure
++        // that the return value is positive.  The extra one byte does
++        // not impact the overall MAC compression function evaluations.
++        return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
++                Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen();
+     }
+-
+ 
+     /*
+      * Well ... hello_request messages are _never_ hashed since we can't
+diff --git a/src/share/classes/sun/security/ssl/MAC.java b/src/share/classes/sun/security/ssl/MAC.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/MAC.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/MAC.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2013, 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
+@@ -44,7 +44,8 @@ import static sun.security.ssl.CipherSui
+  * one of several keyed hashes, as associated with the cipher suite and
+  * protocol version.  (SSL v3.0 uses one construct, TLS uses another.)
+  *
+- * <P>NOTE: MAC computation is the only place in the SSL protocol that the
++ * <P>
++ * NOTE: MAC computation is the only place in the SSL protocol that the
+  * sequence number is used.  It's also reset to zero with each change of
+  * a cipher spec, so this is the only place this state is needed.
+  *
+@@ -129,15 +130,31 @@ final class MAC {
+     }
+ 
+     /**
++     * Returns the hash function block length of the MAC alorithm.
++     */
++    int hashBlockLen() {
++        return macAlg.hashBlockSize;
++    }
++
++    /**
++     * Returns the hash function minimal padding length of the MAC alorithm.
++     */
++    int minimalPaddingLen() {
++        return macAlg.minimalPaddingSize;
++    }
++
++    /**
+      * Computes and returns the MAC for the data in this byte array.
+      *
+      * @param type record type
+      * @param buf compressed record on which the MAC is computed
+      * @param offset start of compressed record data
+      * @param len the size of the compressed record
++     * @param isSimulated if true, simulate the the MAC computation
+      */
+-    final byte[] compute(byte type, byte buf[], int offset, int len) {
+-        return compute(type, null, buf, offset, len);
++    final byte[] compute(byte type, byte buf[],
++            int offset, int len, boolean isSimulated) {
++        return compute(type, null, buf, offset, len, isSimulated);
+     }
+ 
+     /**
+@@ -150,9 +167,10 @@ final class MAC {
+      * @param type record type
+      * @param bb a ByteBuffer in which the position and limit
+      *          demarcate the data to be MAC'd.
++     * @param isSimulated if true, simulate the the MAC computation
+      */
+-    final byte[] compute(byte type, ByteBuffer bb) {
+-        return compute(type, bb, null, 0, bb.remaining());
++    final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
++        return compute(type, bb, null, 0, bb.remaining(), isSimulated);
+     }
+ 
+     // increment the sequence number in the block array
+@@ -168,18 +186,22 @@ final class MAC {
+      * Compute based on either buffer type, either bb.position/limit
+      * or buf/offset/len.
+      */
+-    private byte[] compute(byte type, ByteBuffer bb, byte[] buf, int offset, int len) {
++    private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
++            int offset, int len, boolean isSimulated) {
+ 
+         if (macSize == 0) {
+             return nullMAC;
+         }
+ 
+-        block[BLOCK_OFFSET_TYPE] = type;
+-        block[block.length - 2]  = (byte)(len >> 8);
+-        block[block.length - 1]  = (byte)(len     );
++        // MUST NOT increase the sequence number for a simulated computation.
++        if (!isSimulated) {
++            block[BLOCK_OFFSET_TYPE] = type;
++            block[block.length - 2]  = (byte)(len >> 8);
++            block[block.length - 1]  = (byte)(len     );
+ 
+-        mac.update(block);
+-        incrementSequenceNumber();
++            mac.update(block);
++            incrementSequenceNumber();
++        }
+ 
+         // content
+         if (bb != null) {
+diff --git a/src/share/classes/sun/security/ssl/OutputRecord.java b/src/share/classes/sun/security/ssl/OutputRecord.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/OutputRecord.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/OutputRecord.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2013, 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
+@@ -204,7 +204,7 @@ class OutputRecord extends ByteArrayOutp
+         }
+         if (signer.MAClen() != 0) {
+             byte[] hash = signer.compute(contentType, buf,
+-                    headerSize, count - headerSize);
++                    headerSize, count - headerSize, false);
+             write(hash);
+         }
+     }
+diff --git a/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/share/classes/sun/security/ssl/SSLEngineImpl.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2013, 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
+@@ -919,34 +919,13 @@ final public class SSLEngineImpl extends
+              * throw a fatal alert if the integrity check fails.
+              */
+             try {
+-                decryptedBB = inputRecord.decrypt(readCipher, readBB);
++                decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
+             } catch (BadPaddingException e) {
+-                // RFC 2246 states that decryption_failed should be used
+-                // for this purpose. However, that allows certain attacks,
+-                // so we just send bad record MAC. We also need to make
+-                // sure to always check the MAC to avoid a timing attack
+-                // for the same issue. See paper by Vaudenay et al.
+-                //
+-                // rewind the BB if necessary.
+-                readBB.rewind();
+-
+-                inputRecord.checkMAC(readMAC, readBB);
+-
+-                // use the same alert types as for MAC failure below
+                 byte alertType = (inputRecord.contentType() ==
+                     Record.ct_handshake) ?
+                         Alerts.alert_handshake_failure :
+                         Alerts.alert_bad_record_mac;
+-                fatal(alertType, "Invalid padding", e);
+-            }
+-
+-            if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
+-                if (inputRecord.contentType() == Record.ct_handshake) {
+-                    fatal(Alerts.alert_handshake_failure,
+-                        "bad handshake record MAC");
+-                } else {
+-                    fatal(Alerts.alert_bad_record_mac, "bad record MAC");
+-                }
++                fatal(alertType, e.getMessage(), e);
+             }
+ 
+             // if (!inputRecord.decompress(c))
+diff --git a/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/share/classes/sun/security/ssl/SSLSocketImpl.java
+--- openjdk/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
++++ openjdk/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2013, 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
+@@ -922,27 +922,12 @@ final public class SSLSocketImpl extends
+              * throw a fatal alert if the integrity check fails.
+              */
+             try {
+-                r.decrypt(readCipher);
++                r.decrypt(readMAC, readCipher);
+             } catch (BadPaddingException e) {
+-                // RFC 2246 states that decryption_failed should be used
+-                // for this purpose. However, that allows certain attacks,
+-                // so we just send bad record MAC. We also need to make
+-                // sure to always check the MAC to avoid a timing attack
+-                // for the same issue. See paper by Vaudenay et al.
+-                r.checkMAC(readMAC);
+-                // use the same alert types as for MAC failure below
+                 byte alertType = (r.contentType() == Record.ct_handshake)
+                                         ? Alerts.alert_handshake_failure
+                                         : Alerts.alert_bad_record_mac;
+-                fatal(alertType, "Invalid padding", e);
+-            }
+-            if (!r.checkMAC(readMAC)) {
+-                if (r.contentType() == Record.ct_handshake) {
+-                    fatal(Alerts.alert_handshake_failure,
+-                        "bad handshake record MAC");
+-                } else {
+-                    fatal(Alerts.alert_bad_record_mac, "bad record MAC");
+-                }
++                fatal(alertType, e.getMessage(), e);
+             }
+ 
+             // if (!r.decompress(c))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20130219/8007688.patch	Wed Mar 06 19:22:19 2013 +0000
@@ -0,0 +1,130 @@
+# HG changeset patch
+# User coffeys
+# Date 1360873966 0
+# Node ID 617e68a3948824283f15c36fcd8cf264c1dd0a99
+# Parent  25e83b78298b71abb46eb5a337ed7bddef418ca4
+8007688: Blacklist known bad certificate
+Reviewed-by: mullan
+
+diff --git a/src/share/classes/sun/security/util/UntrustedCertificates.java b/src/share/classes/sun/security/util/UntrustedCertificates.java
+--- openjdk/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java
++++ openjdk/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2012, 2013, 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
+@@ -739,5 +739,111 @@ public final class UntrustedCertificates
+         "B8WfedLHjFW/TMcnXlEWKz4=\n" +
+         "-----END CERTIFICATE-----");
+ 
++        //
++        // Revoked DigiCert code signing certificates used to sign malware
++        //
++
++        // Subject: CN=Buster Paper Comercial Ltda,
++        //          O=Buster Paper Comercial Ltda,
++        //          L=S?o Jos? Dos Campos,
++        //          ST=S?o Paulo,
++        //          C=BR
++        // Issuer:  CN=DigiCert Assured ID Code Signing CA-1,
++        //          OU=www.digicert.com,
++        //          O=DigiCert Inc,
++        //          C=US
++        // Serial:  07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12
++        add("buster-paper-comercial-ltda-72A67312",
++        "-----BEGIN CERTIFICATE-----\n" +
++        "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" +
++        "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +
++        "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" +
++        "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" +
++        "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" +
++        "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" +
++        "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" +
++        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" +
++        "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" +
++        "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" +
++        "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" +
++        "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" +
++        "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" +
++        "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" +
++        "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" +
++        "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" +
++        "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" +
++        "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" +
++        "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" +
++        "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" +
++        "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" +
++        "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" +
++        "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" +
++        "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" +
++        "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" +
++        "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" +
++        "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" +
++        "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" +
++        "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" +
++        "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" +
++        "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" +
++        "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" +
++        "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" +
++        "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" +
++        "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" +
++        "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" +
++        "XMuKLxbh7g==\n" +
++        "-----END CERTIFICATE-----");
++
++        // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME,
++        //          O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME,
++        //          L=S?o Paulo,
++        //          ST=S?o Paulo,
++        //          C=BR
++        // Issuer:  CN=DigiCert Assured ID Code Signing CA-1,
++        //          OU=www.digicert.com,
++        //          O=DigiCert Inc,
++        //          C=US
++        // Serial:  0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f
++        add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F",
++        "-----BEGIN CERTIFICATE-----\n" +
++        "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" +
++        "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +
++        "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" +
++        "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" +
++        "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" +
++        "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" +
++        "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" +
++        "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" +
++        "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" +
++        "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" +
++        "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" +
++        "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" +
++        "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" +
++        "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" +
++        "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" +
++        "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" +
++        "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" +
++        "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" +
++        "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" +
++        "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" +
++        "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" +
++        "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" +
++        "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" +
++        "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" +
++        "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" +
++        "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" +
++        "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" +
++        "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" +
++        "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" +
++        "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" +
++        "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" +
++        "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" +
++        "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" +
++        "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" +
++        "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" +
++        "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" +
++        "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" +
++        "-----END CERTIFICATE-----");
++
+     }
+ }