Merge "Assert that PSS AlgorithmParameters work as expected."
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index 5620851..2330925 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -70,9 +70,12 @@
      *            the File object referencing the actual DEX file
      * @param loader
      *            the class loader object creating the DEX file object
+     * @param elements
+     *            the temporary dex path list elements from DexPathList.makeElements
      */
-    DexFile(File file, ClassLoader loader) throws IOException {
-        this(file.getPath(), loader);
+    DexFile(File file, ClassLoader loader, DexPathList.Element[] elements)
+            throws IOException {
+        this(file.getPath(), loader, elements);
     }
 
     /**
@@ -93,7 +96,7 @@
      *             access rights missing for opening it
      */
     public DexFile(String fileName) throws IOException {
-        this(fileName, null);
+        this(fileName, null, null);
     }
 
     /*
@@ -103,9 +106,11 @@
      *            the filename of the DEX file
      * @param loader
      *            the class loader creating the DEX file object
+     * @param elements
+     *            the temporary dex path list elements from DexPathList.makeElements
      */
-    DexFile(String fileName, ClassLoader loader) throws IOException {
-        mCookie = openDexFile(fileName, null, 0, loader);
+    DexFile(String fileName, ClassLoader loader, DexPathList.Element[] elements) throws IOException {
+        mCookie = openDexFile(fileName, null, 0, loader, elements);
         mInternalCookie = mCookie;
         mFileName = fileName;
         guard.open("close");
@@ -124,9 +129,11 @@
      *  Enable optional features.
      * @param loader
      *  The class loader creating the DEX file object.
+     * @param elements
+     *  The temporary dex path list elements from DexPathList.makeElements
      */
-    private DexFile(String sourceName, String outputName, int flags, ClassLoader loader)
-            throws IOException {
+    private DexFile(String sourceName, String outputName, int flags, ClassLoader loader,
+            DexPathList.Element[] elements) throws IOException {
         if (outputName != null) {
             try {
                 String parent = new File(outputName).getParent();
@@ -140,7 +147,7 @@
             }
         }
 
-        mCookie = openDexFile(sourceName, outputName, flags, loader);
+        mCookie = openDexFile(sourceName, outputName, flags, loader, elements);
         mFileName = sourceName;
         //System.out.println("DEX FILE cookie is " + mCookie + " sourceName=" + sourceName + " outputName=" + outputName);
     }
@@ -179,7 +186,7 @@
          * decided to open it multiple times.  In practice this may not
          * be a real issue.
          */
-        return loadDex(sourcePathName, outputPathName, flags, null);
+        return loadDex(sourcePathName, outputPathName, flags, null, null);
     }
 
     /*
@@ -194,13 +201,15 @@
      *  Enable optional features.  (Currently none defined.)
      * @param loader
      *  Class loader that is aloading the DEX file.
+     * @param elements
+     *  The temporary dex path list elements from DexPathList.makeElements
      * @return
      *  A new or previously-opened DexFile.
      * @throws IOException
      *  If unable to open the source or output file.
      */
     static DexFile loadDex(String sourcePathName, String outputPathName,
-        int flags, ClassLoader loader) throws IOException {
+        int flags, ClassLoader loader, DexPathList.Element[] elements) throws IOException {
 
         /*
          * TODO: we may want to cache previously-opened DexFile objects.
@@ -209,7 +218,7 @@
          * decided to open it multiple times.  In practice this may not
          * be a real issue.
          */
-        return new DexFile(sourcePathName, outputPathName, flags, loader);
+        return new DexFile(sourcePathName, outputPathName, flags, loader, elements);
     }
 
     /**
@@ -359,14 +368,15 @@
      * failure, an IOException is thrown.
      */
     private static Object openDexFile(String sourceName, String outputName, int flags,
-            ClassLoader loader) throws IOException {
+            ClassLoader loader, DexPathList.Element[] elements) throws IOException {
         // Use absolute paths to enable the use of relative paths when testing on host.
         return openDexFileNative(new File(sourceName).getAbsolutePath(),
                                  (outputName == null)
                                      ? null
                                      : new File(outputName).getAbsolutePath(),
                                  flags,
-                                 loader);
+                                 loader,
+                                 elements);
     }
 
     /*
@@ -382,7 +392,7 @@
      * failure, an IOException is thrown.
      */
     private static native Object openDexFileNative(String sourceName, String outputName, int flags,
-            ClassLoader loader);
+            ClassLoader loader, DexPathList.Element[] elements);
 
     /**
      * Returns true if the VM believes that the apk/jar file is out of date
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
index 49da901..d4f80e9 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/dalvik/src/main/java/dalvik/system/DexPathList.java
@@ -240,7 +240,8 @@
                                           List<IOException> suppressedExceptions,
                                           boolean ignoreDexFiles,
                                           ClassLoader loader) {
-        List<Element> elements = new ArrayList<>();
+        Element[] elements = new Element[files.size()];
+        int elementsPos = 0;
         /*
          * Open all files and load the (direct or contained) dex files
          * up front.
@@ -259,12 +260,12 @@
             } else if (file.isDirectory()) {
                 // We support directories for looking up resources and native libraries.
                 // Looking up resources in directories is useful for running libcore tests.
-                elements.add(new Element(file, true, null, null));
+                elements[elementsPos++] = new Element(file, true, null, null);
             } else if (file.isFile()) {
                 if (!ignoreDexFiles && name.endsWith(DEX_SUFFIX)) {
                     // Raw dex file (not inside a zip/jar).
                     try {
-                        dex = loadDexFile(file, optimizedDirectory, loader);
+                        dex = loadDexFile(file, optimizedDirectory, loader, elements);
                     } catch (IOException ex) {
                         System.logE("Unable to load dex file: " + file, ex);
                     }
@@ -273,7 +274,7 @@
 
                     if (!ignoreDexFiles) {
                         try {
-                            dex = loadDexFile(file, optimizedDirectory, loader);
+                            dex = loadDexFile(file, optimizedDirectory, loader, elements);
                         } catch (IOException suppressed) {
                             /*
                              * IOException might get thrown "legitimately" by the DexFile constructor if
@@ -291,11 +292,13 @@
             }
 
             if ((zip != null) || (dex != null)) {
-                elements.add(new Element(dir, false, zip, dex));
+                elements[elementsPos++] = new Element(dir, false, zip, dex);
             }
         }
-
-        return elements.toArray(new Element[elements.size()]);
+        if (elementsPos != elements.length) {
+            elements = Arrays.copyOf(elements, elementsPos);
+        }
+        return elements;
     }
 
     /**
@@ -303,13 +306,14 @@
      * {@code optimizedDirectory} is {@code null}. An application image file may be associated with
      * the {@code loader} if it is not null.
      */
-    private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader)
+    private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader,
+                                       Element[] elements)
             throws IOException {
         if (optimizedDirectory == null) {
-            return new DexFile(file, loader);
+            return new DexFile(file, loader, elements);
         } else {
             String optimizedPath = optimizedPathFor(file, optimizedDirectory);
-            return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader);
+            return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader, elements);
         }
     }
 
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index f8ab870..a353494 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -349,7 +349,7 @@
             kpAlgorithm = "EC";
         } else if (sigAlgorithm.endsWith("DSA")) {
             kpAlgorithm = "DSA";
-        } else if (sigAlgorithm.endsWith("RSA")) {
+        } else if ((sigAlgorithm.endsWith("RSA")) || (sigAlgorithm.endsWith("RSA/PSS"))) {
             kpAlgorithm = "RSA";
         } else {
             throw new Exception("Unknown KeyPair algorithm for Signature algorithm "
@@ -913,6 +913,266 @@
         (byte) 0xEE, (byte) 0x89, (byte) 0x59, (byte) 0xC5,
     };
 
+    /*
+     * echo "This is a signed message from Kenny Root." | openssl sha1 -binary -out digest.bin \
+     *     && openssl pkeyutl -sign -in digest.bin -inkey privkey.pem \
+     *         -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha1 -pkeyopt rsa_pss_saltlen:20 \
+     *     | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] SHA1withRSAPSS_Vector2Signature = new byte[] {
+        (byte) 0x66, (byte) 0xE3, (byte) 0xA5, (byte) 0x20, (byte) 0xE9, (byte) 0x5D,
+        (byte) 0xDF, (byte) 0x99, (byte) 0xA6, (byte) 0x04, (byte) 0x77, (byte) 0xF8,
+        (byte) 0x39, (byte) 0x78, (byte) 0x74, (byte) 0xF5, (byte) 0xC2, (byte) 0x4E,
+        (byte) 0x9E, (byte) 0xEB, (byte) 0x24, (byte) 0xDE, (byte) 0xB4, (byte) 0x36,
+        (byte) 0x69, (byte) 0x1F, (byte) 0xAC, (byte) 0x01, (byte) 0xFF, (byte) 0x5A,
+        (byte) 0xE3, (byte) 0x89, (byte) 0x8A, (byte) 0xE9, (byte) 0x92, (byte) 0x32,
+        (byte) 0xA7, (byte) 0xA4, (byte) 0xC0, (byte) 0x25, (byte) 0x00, (byte) 0x14,
+        (byte) 0xFF, (byte) 0x38, (byte) 0x19, (byte) 0x37, (byte) 0x84, (byte) 0x1A,
+        (byte) 0x3D, (byte) 0xCA, (byte) 0xEE, (byte) 0xF3, (byte) 0xC6, (byte) 0x91,
+        (byte) 0xED, (byte) 0x02, (byte) 0xE6, (byte) 0x1D, (byte) 0x73, (byte) 0xDA,
+        (byte) 0xD4, (byte) 0x55, (byte) 0x93, (byte) 0x54, (byte) 0x9A, (byte) 0xE6,
+        (byte) 0x2E, (byte) 0x7D, (byte) 0x5C, (byte) 0x41, (byte) 0xAF, (byte) 0xED,
+        (byte) 0xAD, (byte) 0x8E, (byte) 0x7F, (byte) 0x47, (byte) 0x3B, (byte) 0x23,
+        (byte) 0xC3, (byte) 0xB8, (byte) 0xBB, (byte) 0xCD, (byte) 0x87, (byte) 0xC4,
+        (byte) 0xA3, (byte) 0x32, (byte) 0x16, (byte) 0x57, (byte) 0xCC, (byte) 0xB8,
+        (byte) 0xB6, (byte) 0x96, (byte) 0x84, (byte) 0x1A, (byte) 0xBC, (byte) 0xF8,
+        (byte) 0x09, (byte) 0x53, (byte) 0xB0, (byte) 0x9D, (byte) 0xE1, (byte) 0x6F,
+        (byte) 0xB2, (byte) 0xEB, (byte) 0x83, (byte) 0xDC, (byte) 0x61, (byte) 0x31,
+        (byte) 0xD7, (byte) 0x02, (byte) 0xB4, (byte) 0xD1, (byte) 0xBA, (byte) 0xBD,
+        (byte) 0xF0, (byte) 0x78, (byte) 0xC6, (byte) 0xBE, (byte) 0x1F, (byte) 0xB0,
+        (byte) 0xE1, (byte) 0xCA, (byte) 0x32, (byte) 0x57, (byte) 0x9F, (byte) 0x8C,
+        (byte) 0xD3, (byte) 0xBB, (byte) 0x04, (byte) 0x1B, (byte) 0x30, (byte) 0x74,
+        (byte) 0x5D, (byte) 0xEA, (byte) 0xD3, (byte) 0x6B, (byte) 0x74, (byte) 0x31,
+        (byte) 0x6F, (byte) 0x33, (byte) 0x5A, (byte) 0x70, (byte) 0x96, (byte) 0x8B,
+        (byte) 0xCB, (byte) 0x22, (byte) 0xF3, (byte) 0xAA, (byte) 0x74, (byte) 0x82,
+        (byte) 0xB2, (byte) 0x82, (byte) 0x71, (byte) 0x4D, (byte) 0x42, (byte) 0x13,
+        (byte) 0x3F, (byte) 0xEA, (byte) 0xE3, (byte) 0x39, (byte) 0xC5, (byte) 0x03,
+        (byte) 0x27, (byte) 0xFF, (byte) 0x78, (byte) 0xB2, (byte) 0xA6, (byte) 0x71,
+        (byte) 0x07, (byte) 0x1C, (byte) 0xB3, (byte) 0x97, (byte) 0xFB, (byte) 0xE8,
+        (byte) 0x85, (byte) 0x6D, (byte) 0x14, (byte) 0xDF, (byte) 0xF9, (byte) 0x7D,
+        (byte) 0x0D, (byte) 0x0C, (byte) 0x9F, (byte) 0xC3, (byte) 0xE2, (byte) 0xDB,
+        (byte) 0xE0, (byte) 0xA5, (byte) 0x05, (byte) 0xBC, (byte) 0x47, (byte) 0x36,
+        (byte) 0xEB, (byte) 0x1E, (byte) 0xBA, (byte) 0x60, (byte) 0x12, (byte) 0x19,
+        (byte) 0xA5, (byte) 0x7E, (byte) 0x55, (byte) 0x0C, (byte) 0x9B, (byte) 0xD4,
+        (byte) 0x9A, (byte) 0xE9, (byte) 0x72, (byte) 0x5C, (byte) 0x5B, (byte) 0xF4,
+        (byte) 0xAA, (byte) 0x4A, (byte) 0x12, (byte) 0x8B, (byte) 0xC2, (byte) 0x8E,
+        (byte) 0xC2, (byte) 0x9A, (byte) 0x3E, (byte) 0x0C, (byte) 0x40, (byte) 0xA4,
+        (byte) 0x0A, (byte) 0xFF, (byte) 0xF8, (byte) 0xC1, (byte) 0x85, (byte) 0x59,
+        (byte) 0xDA, (byte) 0xC6, (byte) 0x8C, (byte) 0x83, (byte) 0x2A, (byte) 0x68,
+        (byte) 0x84, (byte) 0x53, (byte) 0x17, (byte) 0x28, (byte) 0x78, (byte) 0x3F,
+        (byte) 0x5A, (byte) 0xA4, (byte) 0x04, (byte) 0xE6, (byte) 0x23, (byte) 0x8D,
+        (byte) 0x2A, (byte) 0x71, (byte) 0xC1, (byte) 0xBC, (byte) 0x1C, (byte) 0xFD,
+        (byte) 0x75, (byte) 0x16, (byte) 0x6E, (byte) 0x85,
+    };
+
+    /*
+     * echo "This is a signed message from Kenny Root." | openssl sha224 -binary -out digest.bin \
+     *     && openssl pkeyutl -sign -in digest.bin -inkey privkey.pem \
+     *         -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha224 -pkeyopt rsa_pss_saltlen:28 \
+     *     | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] SHA224withRSAPSS_Vector2Signature = new byte[] {
+        (byte) 0x86, (byte) 0x41, (byte) 0xCC, (byte) 0x4B, (byte) 0x82, (byte) 0x74,
+        (byte) 0x04, (byte) 0x43, (byte) 0x8C, (byte) 0xAB, (byte) 0xF6, (byte) 0x3B,
+        (byte) 0xFB, (byte) 0x94, (byte) 0xBC, (byte) 0x4C, (byte) 0x0A, (byte) 0xFE,
+        (byte) 0x0F, (byte) 0x4F, (byte) 0x0F, (byte) 0x9F, (byte) 0x84, (byte) 0x35,
+        (byte) 0x57, (byte) 0x8B, (byte) 0x8D, (byte) 0xC3, (byte) 0x58, (byte) 0xA6,
+        (byte) 0x70, (byte) 0xAC, (byte) 0x40, (byte) 0x6D, (byte) 0xBC, (byte) 0xC1,
+        (byte) 0x6A, (byte) 0xFA, (byte) 0x31, (byte) 0x3B, (byte) 0x7A, (byte) 0x23,
+        (byte) 0xCA, (byte) 0x1F, (byte) 0xCD, (byte) 0xA7, (byte) 0xE3, (byte) 0xD6,
+        (byte) 0x7C, (byte) 0x2C, (byte) 0xF3, (byte) 0x6F, (byte) 0xF5, (byte) 0x82,
+        (byte) 0x9E, (byte) 0x18, (byte) 0x70, (byte) 0x90, (byte) 0xE6, (byte) 0xA3,
+        (byte) 0x44, (byte) 0x61, (byte) 0xB6, (byte) 0x46, (byte) 0x9B, (byte) 0x0D,
+        (byte) 0xE5, (byte) 0x3C, (byte) 0xAE, (byte) 0x22, (byte) 0xF4, (byte) 0x87,
+        (byte) 0xB7, (byte) 0x03, (byte) 0xD8, (byte) 0x42, (byte) 0x33, (byte) 0x4E,
+        (byte) 0xCC, (byte) 0x7A, (byte) 0xDF, (byte) 0xD7, (byte) 0x57, (byte) 0xEB,
+        (byte) 0x51, (byte) 0x6C, (byte) 0xB1, (byte) 0x99, (byte) 0x4D, (byte) 0x94,
+        (byte) 0x82, (byte) 0xA7, (byte) 0x69, (byte) 0x85, (byte) 0x8D, (byte) 0x82,
+        (byte) 0x18, (byte) 0xE4, (byte) 0x53, (byte) 0xF5, (byte) 0x9F, (byte) 0x82,
+        (byte) 0x1C, (byte) 0xE1, (byte) 0x25, (byte) 0x1C, (byte) 0x8E, (byte) 0xE7,
+        (byte) 0xC1, (byte) 0xEC, (byte) 0xBE, (byte) 0x3F, (byte) 0xC3, (byte) 0xED,
+        (byte) 0x41, (byte) 0x89, (byte) 0x94, (byte) 0x13, (byte) 0x11, (byte) 0x75,
+        (byte) 0x3F, (byte) 0x38, (byte) 0x52, (byte) 0x58, (byte) 0xAB, (byte) 0x88,
+        (byte) 0x01, (byte) 0x30, (byte) 0xB4, (byte) 0xCD, (byte) 0x45, (byte) 0x3E,
+        (byte) 0x1A, (byte) 0x5F, (byte) 0x36, (byte) 0xF8, (byte) 0x51, (byte) 0x90,
+        (byte) 0x6E, (byte) 0x6F, (byte) 0x31, (byte) 0x9D, (byte) 0x40, (byte) 0x90,
+        (byte) 0x1A, (byte) 0xA8, (byte) 0x10, (byte) 0xEF, (byte) 0x9D, (byte) 0xF8,
+        (byte) 0xB0, (byte) 0x03, (byte) 0x01, (byte) 0xFB, (byte) 0xD8, (byte) 0x3D,
+        (byte) 0x83, (byte) 0x79, (byte) 0x01, (byte) 0xA7, (byte) 0x82, (byte) 0xC2,
+        (byte) 0x46, (byte) 0x35, (byte) 0x68, (byte) 0xD2, (byte) 0x08, (byte) 0x81,
+        (byte) 0x31, (byte) 0x14, (byte) 0xE8, (byte) 0x13, (byte) 0x8C, (byte) 0xD4,
+        (byte) 0xC4, (byte) 0xCB, (byte) 0xB9, (byte) 0x85, (byte) 0x25, (byte) 0x93,
+        (byte) 0x40, (byte) 0x88, (byte) 0x34, (byte) 0x11, (byte) 0xDA, (byte) 0xFF,
+        (byte) 0xEF, (byte) 0x4D, (byte) 0xDC, (byte) 0x31, (byte) 0x74, (byte) 0x7B,
+        (byte) 0x5E, (byte) 0xA7, (byte) 0x51, (byte) 0x15, (byte) 0x13, (byte) 0xB1,
+        (byte) 0x9E, (byte) 0x06, (byte) 0x51, (byte) 0xBA, (byte) 0x11, (byte) 0xDA,
+        (byte) 0x64, (byte) 0x1B, (byte) 0x78, (byte) 0x76, (byte) 0x57, (byte) 0x96,
+        (byte) 0xF3, (byte) 0x1B, (byte) 0x86, (byte) 0xB2, (byte) 0xF3, (byte) 0x66,
+        (byte) 0x64, (byte) 0x2B, (byte) 0x04, (byte) 0x81, (byte) 0x8C, (byte) 0xDC,
+        (byte) 0xE0, (byte) 0xEA, (byte) 0x66, (byte) 0x62, (byte) 0x44, (byte) 0x31,
+        (byte) 0xA2, (byte) 0x19, (byte) 0xF1, (byte) 0x77, (byte) 0x67, (byte) 0x58,
+        (byte) 0x18, (byte) 0x5B, (byte) 0xCB, (byte) 0xBA, (byte) 0x28, (byte) 0x91,
+        (byte) 0x47, (byte) 0x5B, (byte) 0x4F, (byte) 0x17, (byte) 0x23, (byte) 0x2A,
+        (byte) 0xE4, (byte) 0xB0, (byte) 0xAE, (byte) 0x82, (byte) 0x4E, (byte) 0xCA,
+        (byte) 0xA6, (byte) 0x12, (byte) 0xCA, (byte) 0x70,
+    };
+
+    /*
+     * echo "This is a signed message from Kenny Root." | openssl sha256 -binary -out digest.bin \
+     *     && openssl pkeyutl -sign -in digest.bin -inkey privkey.pem \
+     *         -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha256 -pkeyopt rsa_pss_saltlen:32 \
+     *     | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] SHA256withRSAPSS_Vector2Signature = new byte[] {
+        (byte) 0x94, (byte) 0x33, (byte) 0xCB, (byte) 0x9E, (byte) 0x2C, (byte) 0x17,
+        (byte) 0x46, (byte) 0xB3, (byte) 0x8F, (byte) 0xB7, (byte) 0x93, (byte) 0x98,
+        (byte) 0xA3, (byte) 0x45, (byte) 0xEA, (byte) 0xD4, (byte) 0x51, (byte) 0x60,
+        (byte) 0x3E, (byte) 0x00, (byte) 0xA3, (byte) 0x93, (byte) 0x05, (byte) 0x0F,
+        (byte) 0xCB, (byte) 0x6E, (byte) 0xFF, (byte) 0xA5, (byte) 0x97, (byte) 0x18,
+        (byte) 0xF6, (byte) 0xED, (byte) 0x6B, (byte) 0x6C, (byte) 0xAD, (byte) 0x9C,
+        (byte) 0x73, (byte) 0x63, (byte) 0x9C, (byte) 0x5B, (byte) 0xA5, (byte) 0xA1,
+        (byte) 0x42, (byte) 0xA3, (byte) 0x0E, (byte) 0x32, (byte) 0xF5, (byte) 0xF0,
+        (byte) 0x55, (byte) 0xEE, (byte) 0x58, (byte) 0xC1, (byte) 0xBD, (byte) 0x99,
+        (byte) 0x0A, (byte) 0x2B, (byte) 0xFD, (byte) 0xBD, (byte) 0x1E, (byte) 0x23,
+        (byte) 0xEF, (byte) 0x99, (byte) 0x7D, (byte) 0xC1, (byte) 0xE2, (byte) 0xD5,
+        (byte) 0x71, (byte) 0x6C, (byte) 0x96, (byte) 0x70, (byte) 0xC3, (byte) 0x75,
+        (byte) 0x48, (byte) 0x83, (byte) 0x85, (byte) 0x5E, (byte) 0xC6, (byte) 0x3A,
+        (byte) 0xFF, (byte) 0xE5, (byte) 0xF1, (byte) 0x6B, (byte) 0x85, (byte) 0x7B,
+        (byte) 0x61, (byte) 0xA6, (byte) 0xB1, (byte) 0xCF, (byte) 0x60, (byte) 0x09,
+        (byte) 0x32, (byte) 0xAF, (byte) 0xEF, (byte) 0x95, (byte) 0xA4, (byte) 0x1B,
+        (byte) 0xD6, (byte) 0xFA, (byte) 0xD0, (byte) 0xD7, (byte) 0x17, (byte) 0xCA,
+        (byte) 0xB0, (byte) 0x19, (byte) 0x21, (byte) 0x7F, (byte) 0x5E, (byte) 0x9B,
+        (byte) 0xBB, (byte) 0xB8, (byte) 0xE0, (byte) 0xB1, (byte) 0x95, (byte) 0xB3,
+        (byte) 0xDA, (byte) 0x0B, (byte) 0xB8, (byte) 0xFA, (byte) 0x15, (byte) 0x75,
+        (byte) 0x73, (byte) 0x88, (byte) 0xC8, (byte) 0x45, (byte) 0x33, (byte) 0xD1,
+        (byte) 0x5C, (byte) 0xB7, (byte) 0xFB, (byte) 0x38, (byte) 0x05, (byte) 0xA0,
+        (byte) 0x85, (byte) 0x99, (byte) 0x2C, (byte) 0xB1, (byte) 0xC2, (byte) 0xFE,
+        (byte) 0xAC, (byte) 0x5D, (byte) 0x2C, (byte) 0x1B, (byte) 0xD3, (byte) 0x42,
+        (byte) 0x81, (byte) 0xC8, (byte) 0x1C, (byte) 0xB7, (byte) 0x53, (byte) 0x7E,
+        (byte) 0xC5, (byte) 0x9F, (byte) 0x84, (byte) 0x97, (byte) 0x6F, (byte) 0x00,
+        (byte) 0xC3, (byte) 0x5E, (byte) 0x8B, (byte) 0x67, (byte) 0x3D, (byte) 0x9A,
+        (byte) 0xD0, (byte) 0xE2, (byte) 0x9B, (byte) 0x2D, (byte) 0xC6, (byte) 0xD8,
+        (byte) 0xEF, (byte) 0x19, (byte) 0x14, (byte) 0x49, (byte) 0x88, (byte) 0x52,
+        (byte) 0xF7, (byte) 0x93, (byte) 0xEB, (byte) 0xDB, (byte) 0xB6, (byte) 0x55,
+        (byte) 0x05, (byte) 0xB6, (byte) 0xE7, (byte) 0x70, (byte) 0xE4, (byte) 0x5A,
+        (byte) 0x9E, (byte) 0x80, (byte) 0x78, (byte) 0x48, (byte) 0xA8, (byte) 0xE5,
+        (byte) 0x59, (byte) 0x8D, (byte) 0x1C, (byte) 0x5D, (byte) 0x95, (byte) 0x38,
+        (byte) 0x25, (byte) 0xFC, (byte) 0x38, (byte) 0xC3, (byte) 0xFF, (byte) 0xE2,
+        (byte) 0x6F, (byte) 0xE4, (byte) 0xFC, (byte) 0x64, (byte) 0x8B, (byte) 0xCA,
+        (byte) 0x91, (byte) 0x5F, (byte) 0x0B, (byte) 0x4E, (byte) 0x9A, (byte) 0xB5,
+        (byte) 0x22, (byte) 0x5D, (byte) 0xC5, (byte) 0x5A, (byte) 0x77, (byte) 0xED,
+        (byte) 0x23, (byte) 0xE0, (byte) 0x13, (byte) 0x8F, (byte) 0xAC, (byte) 0x13,
+        (byte) 0xE5, (byte) 0x81, (byte) 0xEE, (byte) 0xD1, (byte) 0xAD, (byte) 0x8A,
+        (byte) 0x0F, (byte) 0x2B, (byte) 0x4C, (byte) 0xB2, (byte) 0x13, (byte) 0x54,
+        (byte) 0x44, (byte) 0x8E, (byte) 0x53, (byte) 0xE2, (byte) 0x33, (byte) 0x14,
+        (byte) 0x7F, (byte) 0x9B, (byte) 0xA9, (byte) 0xD3, (byte) 0xBB, (byte) 0xFC,
+        (byte) 0xAC, (byte) 0xC9, (byte) 0x31, (byte) 0xB6,
+    };
+
+    /*
+     * echo "This is a signed message from Kenny Root." | openssl sha384 -binary -out digest.bin \
+     *     && openssl pkeyutl -sign -in digest.bin -inkey privkey.pem \
+     *         -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha384 -pkeyopt rsa_pss_saltlen:48 \
+     *     | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] SHA384withRSAPSS_Vector2Signature = new byte[] {
+        (byte) 0x20, (byte) 0xCB, (byte) 0x97, (byte) 0x9C, (byte) 0x2E, (byte) 0x51,
+        (byte) 0x59, (byte) 0x56, (byte) 0x9F, (byte) 0x04, (byte) 0x47, (byte) 0x7C,
+        (byte) 0x5C, (byte) 0x57, (byte) 0x59, (byte) 0xBC, (byte) 0x43, (byte) 0xD9,
+        (byte) 0x4B, (byte) 0xEC, (byte) 0xAC, (byte) 0xB9, (byte) 0x88, (byte) 0xA2,
+        (byte) 0x30, (byte) 0x8B, (byte) 0xEE, (byte) 0x2F, (byte) 0xC1, (byte) 0x73,
+        (byte) 0xF1, (byte) 0x13, (byte) 0xB2, (byte) 0x5E, (byte) 0x1A, (byte) 0xC8,
+        (byte) 0xD2, (byte) 0xAA, (byte) 0x27, (byte) 0x16, (byte) 0xA1, (byte) 0x14,
+        (byte) 0xAB, (byte) 0x45, (byte) 0x8A, (byte) 0x7E, (byte) 0x22, (byte) 0x22,
+        (byte) 0x2A, (byte) 0x2E, (byte) 0xDA, (byte) 0x6A, (byte) 0x7E, (byte) 0x3F,
+        (byte) 0x66, (byte) 0x99, (byte) 0x55, (byte) 0xAF, (byte) 0x2B, (byte) 0x94,
+        (byte) 0xD8, (byte) 0x6B, (byte) 0xC2, (byte) 0x60, (byte) 0xB5, (byte) 0x55,
+        (byte) 0xA9, (byte) 0x26, (byte) 0x29, (byte) 0xFC, (byte) 0x17, (byte) 0x56,
+        (byte) 0x05, (byte) 0xB7, (byte) 0x48, (byte) 0x2F, (byte) 0xAB, (byte) 0x68,
+        (byte) 0xCF, (byte) 0x37, (byte) 0x62, (byte) 0x79, (byte) 0x4F, (byte) 0x32,
+        (byte) 0x04, (byte) 0xF6, (byte) 0xEA, (byte) 0xBE, (byte) 0x79, (byte) 0x84,
+        (byte) 0x73, (byte) 0xEE, (byte) 0x1C, (byte) 0xEE, (byte) 0x9F, (byte) 0x72,
+        (byte) 0x7A, (byte) 0xC6, (byte) 0x64, (byte) 0xB4, (byte) 0x4F, (byte) 0xDE,
+        (byte) 0x0B, (byte) 0x38, (byte) 0x47, (byte) 0x62, (byte) 0xA9, (byte) 0xFD,
+        (byte) 0x1B, (byte) 0x75, (byte) 0xEC, (byte) 0xFE, (byte) 0x2D, (byte) 0x04,
+        (byte) 0x2D, (byte) 0x0A, (byte) 0xCE, (byte) 0x13, (byte) 0xFA, (byte) 0xDA,
+        (byte) 0x3F, (byte) 0x4C, (byte) 0x11, (byte) 0xEA, (byte) 0x02, (byte) 0x00,
+        (byte) 0x0A, (byte) 0x93, (byte) 0x12, (byte) 0xDC, (byte) 0x60, (byte) 0xE7,
+        (byte) 0x52, (byte) 0x90, (byte) 0x8A, (byte) 0xA3, (byte) 0xAE, (byte) 0xC5,
+        (byte) 0x9A, (byte) 0xD7, (byte) 0xD5, (byte) 0x0D, (byte) 0xBC, (byte) 0x7A,
+        (byte) 0xDB, (byte) 0xF4, (byte) 0x10, (byte) 0xE0, (byte) 0xDB, (byte) 0xC0,
+        (byte) 0x97, (byte) 0xF1, (byte) 0x84, (byte) 0xCF, (byte) 0x66, (byte) 0xB2,
+        (byte) 0x04, (byte) 0x58, (byte) 0x81, (byte) 0xB5, (byte) 0x9B, (byte) 0x4A,
+        (byte) 0xF9, (byte) 0xD7, (byte) 0xCA, (byte) 0x51, (byte) 0x09, (byte) 0x67,
+        (byte) 0x48, (byte) 0x7B, (byte) 0xE5, (byte) 0xE9, (byte) 0x07, (byte) 0x4E,
+        (byte) 0x6A, (byte) 0xC1, (byte) 0xA6, (byte) 0x68, (byte) 0x90, (byte) 0x17,
+        (byte) 0xAB, (byte) 0x0E, (byte) 0xFB, (byte) 0x3E, (byte) 0x39, (byte) 0x74,
+        (byte) 0x85, (byte) 0x04, (byte) 0x42, (byte) 0x0A, (byte) 0x9E, (byte) 0x02,
+        (byte) 0xA9, (byte) 0x50, (byte) 0xFF, (byte) 0x23, (byte) 0x2D, (byte) 0x30,
+        (byte) 0xDD, (byte) 0x17, (byte) 0xC0, (byte) 0x82, (byte) 0xF7, (byte) 0xBB,
+        (byte) 0x3B, (byte) 0x03, (byte) 0xBD, (byte) 0xB1, (byte) 0x96, (byte) 0xCD,
+        (byte) 0x71, (byte) 0x3F, (byte) 0x67, (byte) 0x59, (byte) 0x5E, (byte) 0x45,
+        (byte) 0xE0, (byte) 0x1C, (byte) 0x80, (byte) 0x52, (byte) 0xD7, (byte) 0xF0,
+        (byte) 0xC1, (byte) 0xE6, (byte) 0xCF, (byte) 0x59, (byte) 0x13, (byte) 0x25,
+        (byte) 0x6F, (byte) 0x9F, (byte) 0xBB, (byte) 0xB9, (byte) 0x7F, (byte) 0x7E,
+        (byte) 0x7D, (byte) 0x93, (byte) 0xD9, (byte) 0x3F, (byte) 0x95, (byte) 0xB7,
+        (byte) 0x9A, (byte) 0xDB, (byte) 0xE2, (byte) 0x2C, (byte) 0x53, (byte) 0x83,
+        (byte) 0x9A, (byte) 0x06, (byte) 0x6D, (byte) 0x22, (byte) 0x81, (byte) 0xB5,
+        (byte) 0x63, (byte) 0xAE, (byte) 0x4A, (byte) 0xEE,
+    };
+
+    /*
+     * echo "This is a signed message from Kenny Root." | openssl sha512 -binary -out digest.bin \
+     *     && openssl pkeyutl -sign -in digest.bin -inkey privkey.pem \
+     *         -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha512 -pkeyopt rsa_pss_saltlen:64 \
+     *     | recode ../x1 | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] SHA512withRSAPSS_Vector2Signature = new byte[] {
+        (byte) 0x9F, (byte) 0xED, (byte) 0xF8, (byte) 0xEE, (byte) 0x30, (byte) 0x5F,
+        (byte) 0x30, (byte) 0x63, (byte) 0x1D, (byte) 0x86, (byte) 0xD3, (byte) 0xAD,
+        (byte) 0x1D, (byte) 0xD8, (byte) 0xD2, (byte) 0x67, (byte) 0xE2, (byte) 0x43,
+        (byte) 0x64, (byte) 0x71, (byte) 0x98, (byte) 0x82, (byte) 0x00, (byte) 0x84,
+        (byte) 0x2C, (byte) 0x88, (byte) 0x1A, (byte) 0x28, (byte) 0xCD, (byte) 0xA2,
+        (byte) 0x34, (byte) 0x17, (byte) 0x0F, (byte) 0x34, (byte) 0x8A, (byte) 0x10,
+        (byte) 0x79, (byte) 0x6C, (byte) 0xCB, (byte) 0xDA, (byte) 0x2F, (byte) 0xDF,
+        (byte) 0x4D, (byte) 0x98, (byte) 0x01, (byte) 0xE8, (byte) 0xB3, (byte) 0xF5,
+        (byte) 0xCD, (byte) 0x60, (byte) 0xEA, (byte) 0xDE, (byte) 0xA5, (byte) 0x0C,
+        (byte) 0x09, (byte) 0xA1, (byte) 0x4A, (byte) 0xC4, (byte) 0x6B, (byte) 0x09,
+        (byte) 0xB3, (byte) 0x37, (byte) 0x1F, (byte) 0x8A, (byte) 0x64, (byte) 0x81,
+        (byte) 0x2E, (byte) 0x22, (byte) 0x75, (byte) 0x24, (byte) 0x3B, (byte) 0xC0,
+        (byte) 0x0E, (byte) 0x1F, (byte) 0x37, (byte) 0xC9, (byte) 0x1E, (byte) 0x6F,
+        (byte) 0xAF, (byte) 0x3E, (byte) 0x9B, (byte) 0x3F, (byte) 0xA3, (byte) 0xC3,
+        (byte) 0x0B, (byte) 0xB9, (byte) 0x83, (byte) 0x60, (byte) 0x02, (byte) 0xC6,
+        (byte) 0x29, (byte) 0x83, (byte) 0x09, (byte) 0x16, (byte) 0xD9, (byte) 0x3D,
+        (byte) 0x84, (byte) 0x02, (byte) 0x81, (byte) 0x20, (byte) 0xE9, (byte) 0x01,
+        (byte) 0x5B, (byte) 0x85, (byte) 0xC8, (byte) 0x81, (byte) 0x25, (byte) 0x6B,
+        (byte) 0xCB, (byte) 0x78, (byte) 0x48, (byte) 0x65, (byte) 0x3A, (byte) 0xD6,
+        (byte) 0x95, (byte) 0x9B, (byte) 0x62, (byte) 0x2D, (byte) 0x84, (byte) 0x54,
+        (byte) 0x12, (byte) 0x94, (byte) 0xB7, (byte) 0xF0, (byte) 0x1C, (byte) 0xB6,
+        (byte) 0x59, (byte) 0xCD, (byte) 0xC3, (byte) 0x86, (byte) 0xE6, (byte) 0x63,
+        (byte) 0xD7, (byte) 0x99, (byte) 0x9A, (byte) 0xC4, (byte) 0xBF, (byte) 0x8E,
+        (byte) 0xDD, (byte) 0x46, (byte) 0x10, (byte) 0xBE, (byte) 0xAB, (byte) 0x78,
+        (byte) 0xC6, (byte) 0x30, (byte) 0x47, (byte) 0x23, (byte) 0xB6, (byte) 0x2C,
+        (byte) 0x02, (byte) 0x5E, (byte) 0x1F, (byte) 0x07, (byte) 0x96, (byte) 0x54,
+        (byte) 0xEE, (byte) 0x28, (byte) 0xC7, (byte) 0xEC, (byte) 0x57, (byte) 0xDB,
+        (byte) 0x9E, (byte) 0xEF, (byte) 0xE4, (byte) 0x11, (byte) 0xF8, (byte) 0x04,
+        (byte) 0xA9, (byte) 0x26, (byte) 0xC2, (byte) 0x61, (byte) 0xF1, (byte) 0x84,
+        (byte) 0xEB, (byte) 0x94, (byte) 0xBD, (byte) 0x48, (byte) 0xCA, (byte) 0xD1,
+        (byte) 0x84, (byte) 0xCE, (byte) 0x82, (byte) 0x2E, (byte) 0xF6, (byte) 0x4E,
+        (byte) 0x17, (byte) 0x6F, (byte) 0x78, (byte) 0xB9, (byte) 0x0B, (byte) 0xA9,
+        (byte) 0x7D, (byte) 0xBC, (byte) 0xE5, (byte) 0xF8, (byte) 0x7D, (byte) 0xA8,
+        (byte) 0x76, (byte) 0x7A, (byte) 0x8B, (byte) 0xB5, (byte) 0x05, (byte) 0x42,
+        (byte) 0x37, (byte) 0xDA, (byte) 0x15, (byte) 0xE2, (byte) 0xC4, (byte) 0x70,
+        (byte) 0x6E, (byte) 0x95, (byte) 0x60, (byte) 0x47, (byte) 0xF9, (byte) 0x0F,
+        (byte) 0xF4, (byte) 0xA2, (byte) 0x73, (byte) 0xF1, (byte) 0x73, (byte) 0xBD,
+        (byte) 0x0B, (byte) 0x9B, (byte) 0x44, (byte) 0xB6, (byte) 0xA9, (byte) 0xAF,
+        (byte) 0x50, (byte) 0x2D, (byte) 0x5C, (byte) 0xA3, (byte) 0x72, (byte) 0x6F,
+        (byte) 0x85, (byte) 0xE8, (byte) 0x0C, (byte) 0xF9, (byte) 0xE1, (byte) 0xE8,
+        (byte) 0xF7, (byte) 0xC0, (byte) 0x85, (byte) 0x14, (byte) 0x53, (byte) 0x95,
+        (byte) 0xF9, (byte) 0x9E, (byte) 0x65, (byte) 0x05, (byte) 0xF0, (byte) 0x22,
+        (byte) 0x7F, (byte) 0x4F, (byte) 0x40, (byte) 0x45,
+    };
+
     public void testGetCommonInstances_Success() throws Exception {
         assertNotNull(Signature.getInstance("SHA1withRSA"));
         assertNotNull(Signature.getInstance("SHA256withRSA"));
@@ -988,6 +1248,71 @@
                 sig.verify(MD5withRSA_Vector2Signature));
     }
 
+    public void testVerify_SHA1withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(keySpec);
+
+        Signature sig = Signature.getInstance("SHA1withRSA/PSS");
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+
+        assertTrue("Signature must verify",
+                sig.verify(SHA1withRSAPSS_Vector2Signature));
+    }
+
+    public void testVerify_SHA224withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(keySpec);
+
+        Signature sig = Signature.getInstance("SHA224withRSA/PSS");
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+
+        assertTrue("Signature must verify",
+                sig.verify(SHA224withRSAPSS_Vector2Signature));
+    }
+
+    public void testVerify_SHA256withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(keySpec);
+
+        Signature sig = Signature.getInstance("SHA256withRSA/PSS");
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+
+        assertTrue("Signature must verify",
+                sig.verify(SHA256withRSAPSS_Vector2Signature));
+    }
+
+    public void testVerify_SHA384withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(keySpec);
+
+        Signature sig = Signature.getInstance("SHA384withRSA/PSS");
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+
+        assertTrue("Signature must verify",
+                sig.verify(SHA384withRSAPSS_Vector2Signature));
+    }
+
+    public void testVerify_SHA512withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(keySpec);
+
+        Signature sig = Signature.getInstance("SHA512withRSA/PSS");
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+
+        assertTrue("Signature must verify",
+                sig.verify(SHA512withRSAPSS_Vector2Signature));
+    }
+
     public void testVerify_SHA1withRSA_Key_InitSignThenInitVerify_Success() throws Exception {
         KeyFactory kf = KeyFactory.getInstance("RSA");
         RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
@@ -1287,6 +1612,111 @@
         assertTrue("Signature must verify correctly", sig.verify(signature));
     }
 
+    public void testSign_SHA1withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
+                RSA_2048_privateExponent);
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+
+        Signature sig = Signature.getInstance("SHA1withRSA/PSS");
+        sig.initSign(privKey);
+        sig.update(Vector2Data);
+
+        byte[] signature = sig.sign();
+        assertNotNull("Signature must not be null", signature);
+
+        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+        assertTrue("Signature must verify correctly", sig.verify(signature));
+    }
+
+    public void testSign_SHA224withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
+                RSA_2048_privateExponent);
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+
+        Signature sig = Signature.getInstance("SHA224withRSA/PSS");
+        sig.initSign(privKey);
+        sig.update(Vector2Data);
+
+        byte[] signature = sig.sign();
+        assertNotNull("Signature must not be null", signature);
+
+        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+        assertTrue("Signature must verify correctly", sig.verify(signature));
+    }
+
+    public void testSign_SHA256withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
+                RSA_2048_privateExponent);
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+
+        Signature sig = Signature.getInstance("SHA256withRSA/PSS");
+        sig.initSign(privKey);
+        sig.update(Vector2Data);
+
+        byte[] signature = sig.sign();
+        assertNotNull("Signature must not be null", signature);
+
+        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+        assertTrue("Signature must verify correctly", sig.verify(signature));
+    }
+
+    public void testSign_SHA384withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
+                RSA_2048_privateExponent);
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+
+        Signature sig = Signature.getInstance("SHA384withRSA/PSS");
+        sig.initSign(privKey);
+        sig.update(Vector2Data);
+
+        byte[] signature = sig.sign();
+        assertNotNull("Signature must not be null", signature);
+
+        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+        assertTrue("Signature must verify correctly", sig.verify(signature));
+    }
+
+    public void testSign_SHA512withRSAPSS_Key_Success() throws Exception {
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
+                RSA_2048_privateExponent);
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+
+        Signature sig = Signature.getInstance("SHA512withRSA/PSS");
+        sig.initSign(privKey);
+        sig.update(Vector2Data);
+
+        byte[] signature = sig.sign();
+        assertNotNull("Signature must not be null", signature);
+
+        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
+                RSA_2048_publicExponent);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        sig.initVerify(pubKey);
+        sig.update(Vector2Data);
+        assertTrue("Signature must verify correctly", sig.verify(signature));
+    }
+
     public void testSign_NONEwithRSA_Key_Success() throws Exception {
         KeyFactory kf = KeyFactory.getInstance("RSA");
         RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java b/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java
index 91c596f..0290509 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DistinguishedNameParserTest.java
@@ -19,8 +19,13 @@
 import javax.net.ssl.DistinguishedNameParser;
 import javax.security.auth.x500.X500Principal;
 import junit.framework.TestCase;
+
 import java.util.Arrays;
 
+/**
+ * See also {@link libcore.javax.security.auth.x500.X500PrincipalTest} as it shows some cases
+ * we are not checking as they are not allowed by the X500 principal in the first place.
+ */
 public final class DistinguishedNameParserTest extends TestCase {
     public void testGetCns() {
         assertCns("");
@@ -28,25 +33,91 @@
         assertCns("ou=xxx,cn=xxx", "xxx");
         assertCns("ou=xxx+cn=yyy,cn=zzz+cn=abc", "yyy", "zzz", "abc");
         assertCns("cn=a,cn=b", "a", "b");
+        assertCns("cn=a   c,cn=b", "a   c", "b");
+        assertCns("cn=a   ,cn=b", "a", "b");
         assertCns("cn=Cc,cn=Bb,cn=Aa", "Cc", "Bb", "Aa");
         assertCns("cn=imap.gmail.com", "imap.gmail.com");
         assertCns("l=\"abcn=a,b\", cn=c", "c");
+        assertCns("l=\"abcn=a,b\", cn=c", "c");
+        assertCns("l=\"abcn=a,b\", cn= c", "c");
+        assertCns("cn=<", "<");
+        assertCns("cn=>", ">");
+        assertCns("cn= >", ">");
+        assertCns("cn=a b", "a b");
+        assertCns("cn   =a b", "a b");
+        assertCns("Cn=a b", "a b");
+        assertCns("cN=a b", "a b");
+        assertCns("CN=a b", "a b");
+        assertCns("cn=a#b", "a#b");
+        assertCns("cn=#130161", "a");
+        assertCns("l=q\t+cn=p", "p");
+        assertCns("l=q\n+cn=p", "p");
+        assertCns("l=q\n,cn=p", "p");
+        assertCns("l=,cn=p", "p");
+        assertCns("l=\tq\n,cn=\tp", "\tp");
+    }
+
+    /** A cn=, generates an empty value, unless it's at the very end. */
+    public void emptyValues() {
+        assertCns("l=,cn=+cn=q", "", "q");
+        assertCns("l=,cn=,cn=q", "", "q");
+        assertCns("l=,cn=");
+        assertCns("l=,cn=q,cn=   ", "q");
+        assertCns("l=,cn=q  ,cn=   ", "q");
+        assertCns("l=,cn=\"\"");
+        assertCns("l=,cn=\"  \",cn=\"  \"","  ");
+        assertCns("l=,cn=  ,cn=  ","");
+        assertCns("l=,cn=,cn=  ,cn=  ", "", "");
+    }
+
+
+    public void testGetCns_escapedChars() {
+        assertCns("cn=\\,", ",");
+        assertCns("cn=\\#", "#");
+        assertCns("cn=\\+", "+");
+        assertCns("cn=\\\"", "\"");
+        assertCns("cn=\\\\", "\\");
+        assertCns("cn=\\<", "<");
+        assertCns("cn=\\>", ">");
+        assertCns("cn=\\;", ";");
+        assertCns("cn=\\+", "+");
+        assertCns("cn=\"\\+\"", "+");
+        assertCns("cn=\"\\,\"", ",");
+        assertCns("cn= a =", "a =");
+        assertCns("cn==", "=");
+    }
+
+    public void testGetCns_whitespace() {
+        assertCns("cn= p", "p");
+        assertCns("cn=\np", "\np");
+        assertCns("cn=\tp", "\tp");
     }
 
     public void testGetCnsWithOid() {
         assertCns("2.5.4.3=a,ou=xxx", "a");
+        assertCns("2.5.4.3=\" a \",ou=xxx", " a ");
+        assertCns("2.5.5.3=a,ou=xxx,cn=b", "b");
     }
 
     public void testGetCnsWithQuotedStrings() {
         assertCns("cn=\"\\\" a ,=<>#;\"", "\" a ,=<>#;");
         assertCns("cn=abc\\,def", "abc,def");
+        assertCns("cn=\"\\\" a ,\\=<>\\#;\"", "\" a ,=<>#;");
     }
 
     public void testGetCnsWithUtf8() {
+        assertCns("cn=\"Lu\\C4\\8Di\\C4\\87\"", "\u004c\u0075\u010d\u0069\u0107");
         assertCns("cn=Lu\\C4\\8Di\\C4\\87", "\u004c\u0075\u010d\u0069\u0107");
+        assertCns("cn=Lu\\C4\\8di\\c4\\87", "\u004c\u0075\u010d\u0069\u0107");
+        assertCns("cn=\"Lu\\C4\\8di\\c4\\87\"", "\u004c\u0075\u010d\u0069\u0107");
+        assertCns("cn=\u004c\u0075\u010d\u0069\u0107", "\u004c\u0075\u010d\u0069\u0107");
+        // \63=c
+        expectExceptionInPrincipal("\\63n=ab");
+        expectExceptionInPrincipal("cn=\\a");
     }
 
     public void testGetCnsWithWhitespace() {
+
         assertCns("ou=a, cn=  a  b  ,o=x", "a  b");
         assertCns("cn=\"  a  b  \" ,o=x", "  a  b  ");
     }
@@ -54,7 +125,6 @@
     private void assertCns(String dn, String... expected) {
         X500Principal principal = new X500Principal(dn);
         DistinguishedNameParser parser = new DistinguishedNameParser(principal);
-
         // Test getAllMostSpecificFirst
         assertEquals(dn, Arrays.asList(expected), parser.getAllMostSpecificFirst("cn"));
 
@@ -65,4 +135,28 @@
             assertNull(dn, parser.findMostSpecific("cn"));
         }
     }
+
+    private void assertGetAttribute(String dn, String attribute, String... expected) {
+        X500Principal principal = new X500Principal(dn);
+        DistinguishedNameParser parser = new DistinguishedNameParser(principal);
+        // Test getAllMostSpecificFirst
+        assertEquals(dn, Arrays.asList(expected), parser.getAllMostSpecificFirst(attribute));
+
+        // Test findMostSpecific
+        if (expected.length > 0) {
+            assertEquals(dn, expected[0], parser.findMostSpecific(attribute));
+        } else {
+            assertNull(dn, parser.findMostSpecific(attribute));
+        }
+    }
+
+    private void expectExceptionInPrincipal(String dn) {
+        try {
+            X500Principal principal = new X500Principal(dn);
+            fail("Expected " + IllegalArgumentException.class.getName()
+                    + " because of incorrect input name");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index 571aa9c..4f5d658 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -103,6 +103,33 @@
                               new byte[] { 48, 21, 49, 19, 48, 17, 6, 10, 9, -110, 38, -119, -109, -14, 44, 100, 1, 25, 22, 3, 99, 111, 109 });
     }
 
+    public void testExceptionsForWrongDNs() {
+        expectExceptionInDNConstructor("cn=\\n");
+        expectExceptionInDNConstructor("cn=a;b");
+        expectExceptionInDNConstructor("cn=  #a");
+        expectExceptionInDNConstructor("l=a,cn=+p");
+        expectExceptionInDNConstructor("l=+a,cn=p");
+        expectExceptionInDNConstructor("\nl=q\n,cn=p");
+        expectExceptionInDNConstructor("\tl=q,cn=p");
+        expectExceptionInDNConstructor("<=q,cn=p");
+        expectExceptionInDNConstructor("l=q\n,,cn=p");
+        expectExceptionInDNConstructor("l=q\n+,cn=p");
+        expectExceptionInDNConstructor("+l=q,cn=p");
+        expectExceptionInDNConstructor(",l=q,cn=p");
+        expectExceptionInDNConstructor("l");
+        expectExceptionInDNConstructor("l=\\g0");
+    }
+
+    private void expectExceptionInDNConstructor(String dn) {
+        try {
+            X500Principal principal = new X500Principal(dn);
+            fail("Expected " + IllegalArgumentException.class.getName()
+                    + " because of incorrect input name");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+    }
+
     private void testIA5StringEncoding(String name, byte[] expectedEncoded) {
         X500Principal original = new X500Principal(name);