@@ -1832,5 +1832,381 @@ public void testStoreToByteArrayThreaded()
18321832 }
18331833 }
18341834 }
1835+
1836+ /*
1837+ * Test that SecretKey entries can be stored with one iteration count,
1838+ * then retrieved successfully after the iteration count changes.
1839+ * This verifies that SecretKey decryption uses the stored kdfIterations
1840+ * instead of the current global WKS_PBKDF2_ITERATION_COUNT.
1841+ */
1842+ @ Test
1843+ public void testSecretKeyWithIterationCountChange ()
1844+ throws KeyStoreException , IOException , FileNotFoundException ,
1845+ NoSuchProviderException , NoSuchAlgorithmException ,
1846+ CertificateException , InvalidKeySpecException ,
1847+ UnrecoverableKeyException {
1848+
1849+ KeyStore store = null ;
1850+ KeyGenerator kg = null ;
1851+ SecretKey aesKey1 = null ;
1852+ SecretKey aesKey2 = null ;
1853+ SecretKey hmacKey = null ;
1854+ Key keyOut = null ;
1855+ ByteArrayOutputStream baos = null ;
1856+ ByteArrayInputStream bais = null ;
1857+ String origIterationCount =
1858+ Security .getProperty ("wolfjce.wks.iterationCount" );
1859+
1860+ try {
1861+ /* Create KeyStore and load empty */
1862+ store = KeyStore .getInstance (storeType , storeProvider );
1863+ store .load (null , storePass .toCharArray ());
1864+
1865+ /* Set iteration count to 20000 */
1866+ Security .setProperty ("wolfjce.wks.iterationCount" , "20000" );
1867+
1868+ /* Generate and store AES key with 20000 iterations */
1869+ kg = KeyGenerator .getInstance ("AES" );
1870+ assertNotNull (kg );
1871+ kg .init (256 , rand );
1872+ aesKey1 = kg .generateKey ();
1873+ assertNotNull (aesKey1 );
1874+ store .setKeyEntry ("aesKey1" , aesKey1 ,
1875+ storePass .toCharArray (), null );
1876+
1877+ /* Store KeyStore to byte array */
1878+ baos = new ByteArrayOutputStream ();
1879+ store .store (baos , storePass .toCharArray ());
1880+
1881+ /* Change iteration count to 15000 (LOWER) */
1882+ Security .setProperty ("wolfjce.wks.iterationCount" , "15000" );
1883+
1884+ /* Load KeyStore from byte array */
1885+ bais = new ByteArrayInputStream (baos .toByteArray ());
1886+ store = KeyStore .getInstance (storeType , storeProvider );
1887+ store .load (bais , storePass .toCharArray ());
1888+
1889+ /* Retrieve and verify key works with lower iteration count */
1890+ keyOut = store .getKey ("aesKey1" , storePass .toCharArray ());
1891+ assertNotNull (keyOut );
1892+ assertTrue (keyOut instanceof SecretKey );
1893+ assertTrue (Arrays .equals (aesKey1 .getEncoded (),
1894+ keyOut .getEncoded ()));
1895+
1896+ /* Add new key with lower iteration count (15000) */
1897+ aesKey2 = kg .generateKey ();
1898+ assertNotNull (aesKey2 );
1899+ store .setKeyEntry ("aesKey2" , aesKey2 ,
1900+ storePass .toCharArray (), null );
1901+
1902+ /* Store KeyStore again */
1903+ baos = new ByteArrayOutputStream ();
1904+ store .store (baos , storePass .toCharArray ());
1905+
1906+ /* Change iteration count to 30000 (higher than both) */
1907+ Security .setProperty ("wolfjce.wks.iterationCount" , "30000" );
1908+
1909+ /* Load KeyStore from byte array */
1910+ bais = new ByteArrayInputStream (baos .toByteArray ());
1911+ store = KeyStore .getInstance (storeType , storeProvider );
1912+ store .load (bais , storePass .toCharArray ());
1913+
1914+ /* Verify both keys work with higher iteration count set */
1915+ keyOut = store .getKey ("aesKey1" , storePass .toCharArray ());
1916+ assertNotNull (keyOut );
1917+ assertTrue (keyOut instanceof SecretKey );
1918+ assertTrue (Arrays .equals (aesKey1 .getEncoded (),
1919+ keyOut .getEncoded ()));
1920+
1921+ keyOut = store .getKey ("aesKey2" , storePass .toCharArray ());
1922+ assertNotNull (keyOut );
1923+ assertTrue (keyOut instanceof SecretKey );
1924+ assertTrue (Arrays .equals (aesKey2 .getEncoded (),
1925+ keyOut .getEncoded ()));
1926+
1927+ /* Add HMAC key with new higher iteration count (30000) */
1928+ kg = KeyGenerator .getInstance ("HmacSHA256" );
1929+ assertNotNull (kg );
1930+ kg .init (256 , rand );
1931+ hmacKey = kg .generateKey ();
1932+ assertNotNull (hmacKey );
1933+ store .setKeyEntry ("hmacKey" , hmacKey ,
1934+ storePass .toCharArray (), null );
1935+
1936+ /* Verify all three keys work together */
1937+ keyOut = store .getKey ("aesKey1" , storePass .toCharArray ());
1938+ assertTrue (Arrays .equals (aesKey1 .getEncoded (),
1939+ keyOut .getEncoded ()));
1940+ keyOut = store .getKey ("aesKey2" , storePass .toCharArray ());
1941+ assertTrue (Arrays .equals (aesKey2 .getEncoded (),
1942+ keyOut .getEncoded ()));
1943+ keyOut = store .getKey ("hmacKey" , storePass .toCharArray ());
1944+ assertTrue (Arrays .equals (hmacKey .getEncoded (),
1945+ keyOut .getEncoded ()));
1946+
1947+ } finally {
1948+ /* Reset iteration count back to original value */
1949+ if (origIterationCount != null ) {
1950+ Security .setProperty ("wolfjce.wks.iterationCount" ,
1951+ origIterationCount );
1952+ }
1953+ else {
1954+ Security .setProperty ("wolfjce.wks.iterationCount" , "10000" );
1955+ }
1956+ }
1957+ }
1958+
1959+ /*
1960+ * Test that PrivateKey entries can be stored with one iteration count,
1961+ * then retrieved successfully after the iteration count changes.
1962+ * This is a regression test to ensure PrivateKey continues to work
1963+ * correctly alongside the SecretKey fix.
1964+ */
1965+ @ Test
1966+ public void testPrivateKeyWithIterationCountChange ()
1967+ throws KeyStoreException , IOException , FileNotFoundException ,
1968+ NoSuchProviderException , NoSuchAlgorithmException ,
1969+ CertificateException , InvalidKeySpecException ,
1970+ UnrecoverableKeyException {
1971+
1972+ KeyStore store = null ;
1973+ PrivateKey keyOut = null ;
1974+ Certificate [] chainOut = null ;
1975+ ByteArrayOutputStream baos = null ;
1976+ ByteArrayInputStream bais = null ;
1977+ String origIterationCount =
1978+ Security .getProperty ("wolfjce.wks.iterationCount" );
1979+
1980+ try {
1981+ /* Create KeyStore and load empty */
1982+ store = KeyStore .getInstance (storeType , storeProvider );
1983+ store .load (null , storePass .toCharArray ());
1984+
1985+ /* Set iteration count to 20000 */
1986+ Security .setProperty ("wolfjce.wks.iterationCount" , "20000" );
1987+
1988+ /* Store RSA PrivateKey with cert chain at 20000 iterations */
1989+ store .setKeyEntry ("serverRsa" , serverKeyRsa ,
1990+ storePass .toCharArray (), rsaServerChain );
1991+ assertEquals (1 , store .size ());
1992+ assertTrue (store .isKeyEntry ("serverRsa" ));
1993+
1994+ /* Store KeyStore to byte array */
1995+ baos = new ByteArrayOutputStream ();
1996+ store .store (baos , storePass .toCharArray ());
1997+
1998+ /* Change iteration count to 15000 (LOWER) */
1999+ Security .setProperty ("wolfjce.wks.iterationCount" , "15000" );
2000+
2001+ /* Load KeyStore from byte array */
2002+ bais = new ByteArrayInputStream (baos .toByteArray ());
2003+ store = KeyStore .getInstance (storeType , storeProvider );
2004+ store .load (bais , storePass .toCharArray ());
2005+
2006+ /* Retrieve and verify key works with lower iteration count */
2007+ keyOut = (PrivateKey )store .getKey ("serverRsa" ,
2008+ storePass .toCharArray ());
2009+ assertNotNull (keyOut );
2010+ assertTrue (keyOut instanceof PrivateKey );
2011+ assertTrue (Arrays .equals (serverKeyRsa .getEncoded (),
2012+ keyOut .getEncoded ()));
2013+ chainOut = store .getCertificateChain ("serverRsa" );
2014+ assertNotNull (chainOut );
2015+ assertTrue (Arrays .equals (rsaServerChain , chainOut ));
2016+
2017+ /* Add ECC PrivateKey with lower iteration count (15000) */
2018+ store .setKeyEntry ("serverEcc" , serverKeyEcc ,
2019+ storePass .toCharArray (), eccServerChain );
2020+
2021+ /* Store KeyStore again */
2022+ baos = new ByteArrayOutputStream ();
2023+ store .store (baos , storePass .toCharArray ());
2024+
2025+ /* Change iteration count to 30000 (HIGHER than both) */
2026+ Security .setProperty ("wolfjce.wks.iterationCount" , "30000" );
2027+
2028+ /* Load KeyStore from byte array */
2029+ bais = new ByteArrayInputStream (baos .toByteArray ());
2030+ store = KeyStore .getInstance (storeType , storeProvider );
2031+ store .load (bais , storePass .toCharArray ());
2032+
2033+ /* Verify both keys work with higher iteration count set */
2034+ keyOut = (PrivateKey )store .getKey ("serverRsa" ,
2035+ storePass .toCharArray ());
2036+ assertNotNull (keyOut );
2037+ assertTrue (Arrays .equals (serverKeyRsa .getEncoded (),
2038+ keyOut .getEncoded ()));
2039+ chainOut = store .getCertificateChain ("serverRsa" );
2040+ assertTrue (Arrays .equals (rsaServerChain , chainOut ));
2041+
2042+ keyOut = (PrivateKey )store .getKey ("serverEcc" ,
2043+ storePass .toCharArray ());
2044+ assertNotNull (keyOut );
2045+ assertTrue (Arrays .equals (serverKeyEcc .getEncoded (),
2046+ keyOut .getEncoded ()));
2047+ chainOut = store .getCertificateChain ("serverEcc" );
2048+ assertTrue (Arrays .equals (eccServerChain , chainOut ));
2049+
2050+ } finally {
2051+ /* Reset iteration count back to original value */
2052+ if (origIterationCount != null ) {
2053+ Security .setProperty ("wolfjce.wks.iterationCount" ,
2054+ origIterationCount );
2055+ }
2056+ else {
2057+ Security .setProperty ("wolfjce.wks.iterationCount" , "10000" );
2058+ }
2059+ }
2060+ }
2061+
2062+ /*
2063+ * Test that a KeyStore can contain PrivateKey, SecretKey, and
2064+ * Certificate entries encrypted with different iteration counts,
2065+ * and all can be retrieved correctly regardless of what the current
2066+ * iteration count property is set to.
2067+ */
2068+ @ Test
2069+ public void testMixedIterationCountsInSameKeyStore ()
2070+ throws KeyStoreException , IOException , FileNotFoundException ,
2071+ NoSuchProviderException , NoSuchAlgorithmException ,
2072+ CertificateException , InvalidKeySpecException ,
2073+ UnrecoverableKeyException {
2074+
2075+ KeyStore store = null ;
2076+ KeyGenerator kg = null ;
2077+ SecretKey aesKey1 = null ;
2078+ SecretKey aesKey2 = null ;
2079+ SecretKey hmacKey = null ;
2080+ Key keyOut = null ;
2081+ PrivateKey privKeyOut = null ;
2082+ Certificate [] chainOut = null ;
2083+ Certificate certOut = null ;
2084+ ByteArrayOutputStream baos = null ;
2085+ ByteArrayInputStream bais = null ;
2086+ String origIterationCount =
2087+ Security .getProperty ("wolfjce.wks.iterationCount" );
2088+
2089+ try {
2090+ /* Create KeyStore and load empty */
2091+ store = KeyStore .getInstance (storeType , storeProvider );
2092+ store .load (null , storePass .toCharArray ());
2093+
2094+ /* Set iteration count to 12000 and add first entries */
2095+ Security .setProperty ("wolfjce.wks.iterationCount" , "12000" );
2096+
2097+ kg = KeyGenerator .getInstance ("AES" );
2098+ kg .init (256 , rand );
2099+ aesKey1 = kg .generateKey ();
2100+ store .setKeyEntry ("aesKey12k" , aesKey1 ,
2101+ storePass .toCharArray (), null );
2102+ store .setKeyEntry ("rsaKey12k" , serverKeyRsa ,
2103+ storePass .toCharArray (), rsaServerChain );
2104+
2105+ /* Change to 18000 and add more entries */
2106+ Security .setProperty ("wolfjce.wks.iterationCount" , "18000" );
2107+
2108+ kg = KeyGenerator .getInstance ("HmacSHA256" );
2109+ kg .init (256 , rand );
2110+ hmacKey = kg .generateKey ();
2111+ store .setKeyEntry ("hmacKey18k" , hmacKey ,
2112+ storePass .toCharArray (), null );
2113+ store .setKeyEntry ("eccKey18k" , serverKeyEcc ,
2114+ storePass .toCharArray (), eccServerChain );
2115+
2116+ /* Change to 25000 and add more entries */
2117+ Security .setProperty ("wolfjce.wks.iterationCount" , "25000" );
2118+
2119+ kg = KeyGenerator .getInstance ("AES" );
2120+ kg .init (128 , rand );
2121+ aesKey2 = kg .generateKey ();
2122+ store .setKeyEntry ("aesKey25k" , aesKey2 ,
2123+ storePass .toCharArray (), null );
2124+ store .setCertificateEntry ("clientCertRsa" , clientCertRsa );
2125+
2126+ /* Store KeyStore to byte array with 25000 iteration count */
2127+ baos = new ByteArrayOutputStream ();
2128+ store .store (baos , storePass .toCharArray ());
2129+
2130+ /* Change iteration count to something completely different */
2131+ Security .setProperty ("wolfjce.wks.iterationCount" , "35000" );
2132+
2133+ /* Load KeyStore */
2134+ bais = new ByteArrayInputStream (baos .toByteArray ());
2135+ store = KeyStore .getInstance (storeType , storeProvider );
2136+ store .load (bais , storePass .toCharArray ());
2137+
2138+ /* Verify all entries can be retrieved correctly with 35000 set */
2139+ assertEquals (6 , store .size ());
2140+
2141+ /* Verify 12000-iteration entries */
2142+ keyOut = store .getKey ("aesKey12k" , storePass .toCharArray ());
2143+ assertNotNull (keyOut );
2144+ assertTrue (Arrays .equals (aesKey1 .getEncoded (),
2145+ keyOut .getEncoded ()));
2146+
2147+ privKeyOut = (PrivateKey )store .getKey ("rsaKey12k" ,
2148+ storePass .toCharArray ());
2149+ assertNotNull (privKeyOut );
2150+ assertTrue (Arrays .equals (serverKeyRsa .getEncoded (),
2151+ privKeyOut .getEncoded ()));
2152+ chainOut = store .getCertificateChain ("rsaKey12k" );
2153+ assertTrue (Arrays .equals (rsaServerChain , chainOut ));
2154+
2155+ /* Verify 18000-iteration entries */
2156+ keyOut = store .getKey ("hmacKey18k" , storePass .toCharArray ());
2157+ assertNotNull (keyOut );
2158+ assertTrue (Arrays .equals (hmacKey .getEncoded (),
2159+ keyOut .getEncoded ()));
2160+
2161+ privKeyOut = (PrivateKey )store .getKey ("eccKey18k" ,
2162+ storePass .toCharArray ());
2163+ assertNotNull (privKeyOut );
2164+ assertTrue (Arrays .equals (serverKeyEcc .getEncoded (),
2165+ privKeyOut .getEncoded ()));
2166+ chainOut = store .getCertificateChain ("eccKey18k" );
2167+ assertTrue (Arrays .equals (eccServerChain , chainOut ));
2168+
2169+ /* Verify 25000-iteration entries */
2170+ keyOut = store .getKey ("aesKey25k" , storePass .toCharArray ());
2171+ assertNotNull (keyOut );
2172+ assertTrue (Arrays .equals (aesKey2 .getEncoded (),
2173+ keyOut .getEncoded ()));
2174+
2175+ certOut = store .getCertificate ("clientCertRsa" );
2176+ assertNotNull (certOut );
2177+ assertEquals (clientCertRsa , certOut );
2178+
2179+ /* Change iteration count again and verify still works */
2180+ Security .setProperty ("wolfjce.wks.iterationCount" , "11000" );
2181+
2182+ /* Re-store and reload with new iteration count */
2183+ baos = new ByteArrayOutputStream ();
2184+ store .store (baos , storePass .toCharArray ());
2185+ bais = new ByteArrayInputStream (baos .toByteArray ());
2186+ store = KeyStore .getInstance (storeType , storeProvider );
2187+ store .load (bais , storePass .toCharArray ());
2188+
2189+ /* Verify all original entries still work */
2190+ keyOut = store .getKey ("aesKey12k" , storePass .toCharArray ());
2191+ assertTrue (Arrays .equals (aesKey1 .getEncoded (),
2192+ keyOut .getEncoded ()));
2193+ keyOut = store .getKey ("hmacKey18k" , storePass .toCharArray ());
2194+ assertTrue (Arrays .equals (hmacKey .getEncoded (),
2195+ keyOut .getEncoded ()));
2196+ keyOut = store .getKey ("aesKey25k" , storePass .toCharArray ());
2197+ assertTrue (Arrays .equals (aesKey2 .getEncoded (),
2198+ keyOut .getEncoded ()));
2199+
2200+ } finally {
2201+ /* Reset iteration count back to original value */
2202+ if (origIterationCount != null ) {
2203+ Security .setProperty ("wolfjce.wks.iterationCount" ,
2204+ origIterationCount );
2205+ }
2206+ else {
2207+ Security .setProperty ("wolfjce.wks.iterationCount" , "10000" );
2208+ }
2209+ }
2210+ }
18352211}
18362212
0 commit comments