Index: modules/security/src/test/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImplTest.java =================================================================== --- modules/security/src/test/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImplTest.java (revision 405699) +++ modules/security/src/test/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImplTest.java (working copy) @@ -133,9 +133,9 @@ CertFactoryTestData.getCRLEncoding()); try { crl = certFactory.engineGenerateCRL(bais); - assertNotNull("First generated certificate is null", crl); + assertNotNull("First generated CRL is null", crl); crl = certFactory.engineGenerateCRL(bais); - assertNotNull("Second generated certificate is null", crl); + assertNotNull("Second generated CRL is null", crl); } catch (CRLException e) { e.printStackTrace(); fail("Unexpected CRLException: " + e.getMessage()); @@ -146,6 +146,25 @@ fail("Expected CRLException was not thrown."); } catch (CRLException e) { } + + // Base64 testing + bais = new ByteArrayInputStream( + CertFactoryTestData.getBase64CRLEncoding()); + try { + crl = certFactory.engineGenerateCRL(bais); + assertNotNull("First generated CRL is null", crl); + crl = certFactory.engineGenerateCRL(bais); + assertNotNull("Second generated CRL is null", crl); + } catch (CRLException e) { + e.printStackTrace(); + fail("Unexpected CRLException: " + e.getMessage()); + } + + try { + certFactory.engineGenerateCRL(bais); + fail("Expected CRLException was not thrown."); + } catch (CRLException e) { + } } /** @@ -165,6 +184,18 @@ e.printStackTrace(); fail("Unexpected CRLException: " + e.getMessage()); } + + // Base64 testing + bais = new ByteArrayInputStream( + CertFactoryTestData.getBase64CRLEncoding()); + try { + assertTrue("The size of collection is not correct", + certFactory.engineGenerateCRLs(bais).size() == 2); + } catch (CRLException e) { + e.printStackTrace(); + fail("Unexpected CRLException: " + e.getMessage()); + } + } /** Index: modules/security/src/test/java/common/org/apache/harmony/security/support/provider/cert/CertFactoryTestData.java =================================================================== --- modules/security/src/test/java/common/org/apache/harmony/security/support/provider/cert/CertFactoryTestData.java (revision 405699) +++ modules/security/src/test/java/common/org/apache/harmony/security/support/provider/cert/CertFactoryTestData.java (working copy) @@ -267,6 +267,31 @@ "wGByqGSM44BAMBAQADLwAwLAIUYp/1MGXvQ1a/wF+WvmRGnQHJ" + "+nQCFBJ4JFNfcCN7wNUpSOnUYHEC8uIn"; + private static String crlEncodingPEM = + "-----BEGIN X509 CRL-----\n" + + "MIIBNDCB8gIBATAMBgcqhkjOOAQDAQEAMBUxEzARBgNVBAoTCk" + + "NSTCBJc3N1ZXIXDTA1MDcxMzA5NDkzMFoXDTA1MDcxMzA5NTEx" + + "MFowgZgwEwICAisXDTA1MDcxMzA5NDkzMVowbAICAjcXDTA1MD" + + "cxMzA5NDkzMVowVzAKBgNVHRUEAwoBATAcBgNVHRgEFRgTMjAw" + + "NTA3MTMwOTQ5MzAuNTYyWjArBgNVHR0BAf8EITAfpB0xGzAZBg" + + "NVBAoTEkNlcnRpZmljYXRlIElzc3VlcjATAgIDCRcNMDUwNzEz" + + "MDk0OTMxWqAPMA0wCwYDVR0UBAQCAhFcMAwGByqGSM44BAMBAQ" + + "ADLwAwLAIUYp/1MGXvQ1a/wF+WvmRGnQHJ+nQCFBJ4JFNfcCN7" + + "wNUpSOnUYHEC8uIm\n" + + "-----END X509 CRL-----\n" + + "-----BEGIN X509 CRL-----\n" + + "MIIBNDCB8gIBATAMBgcqhkjOOAQDAQEAMB" + + "UxEzARBgNVBAoTCkNSTCBJc3N1ZXIXDTA1MDcxMzA5NDkzMFoX" + + "DTA1MDcxMzA5NTExMFowgZgwEwICAisXDTA1MDcxMzA5NDkzMV" + + "owbAICAjcXDTA1MDcxMzA5NDkzMVowVzAKBgNVHRUEAwoBATAc" + + "BgNVHRgEFRgTMjAwNTA3MTMwOTQ5MzAuNTYyWjArBgNVHR0BAf" + + "8EITAfpB0xGzAZBgNVBAoTEkNlcnRpZmljYXRlIElzc3VlcjAT" + + "AgIDCRcNMDUwNzEzMDk0OTMxWqAPMA0wCwYDVR0UBAQCAhFcMA" + + "wGByqGSM44BAMBAQADLwAwLAIUYp/1MGXvQ1a/wF+WvmRGnQHJ" + + "+nQCFBJ4JFNfcCN7wNUpSOnUYHEC8uIo\n" + + "-----END X509 CRL-----\n"; + + public static byte[] getCertPathPKCS7Encoding() { return Base64.decode(certPathPKCS7Base64.getBytes()); } @@ -283,6 +308,10 @@ return base64certEncoding.getBytes(); } + public static byte[] getBase64CRLEncoding() { + return crlEncodingPEM.getBytes(); + } + public static byte[] getCRLEncoding() { return Base64.decode(crlEncodingBase64.getBytes()); } Index: modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/Cache.java =================================================================== --- modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/Cache.java (revision 405699) +++ modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/Cache.java (working copy) @@ -49,7 +49,7 @@ //private long[] demanded = new long[cache_size]; // the number of bytes which will be used for array hash generation. - private final int prefix_size = 28; + private int prefix_size; private int last_cached = 0; private boolean cache_is_full = false; @@ -65,16 +65,21 @@ * @param pref_size: the number of bytes which will be used * for array hash generation. */ - public Cache(int size) { + public Cache(int pref_size, int size) { cache_size = size; + prefix_size = pref_size; hashes = new long[cache_size]; hashes_idx = new long[cache_size]; encodings = new byte[cache_size][]; cache = new Object[cache_size]; } + public Cache(int pref_size) { + this(pref_size, 900); + } + public Cache() { - this(900); + this(28, 900); } // Returns the hash value of the array (which length should be Index: modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java =================================================================== --- modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java (revision 405699) +++ modules/security/src/main/java/common/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java (working copy) @@ -45,7 +45,7 @@ public class X509CertFactoryImpl extends CertificateFactorySpi { private static Cache CERT_CASHE = new Cache(); - private static Cache CRL_CASHE = new Cache(); + private static Cache CRL_CASHE = new Cache(24); public X509CertFactoryImpl() {} @@ -172,29 +172,75 @@ inStream = new RestoringInputStream(inStream); } inStream.mark(32); - byte[] buff = new byte[28]; - if (inStream.read(buff) < 28) { + byte[] buff = new byte[25]; // take one byte for new line + if (inStream.read(buff) < 25) { throw new CRLException( "Input Stream contains not enought data."); } - - inStream.reset(); - long hash = CRL_CASHE.getHash(buff); - if (CRL_CASHE.contains(hash)) { - byte[] encoding = new byte[BerInputStream.getLength(buff)]; - inStream.read(encoding); - CRL res = - (CRL) CRL_CASHE.get(hash, encoding); - if (res != null) { - return res; + if ("-----BEGIN X509 CRL-----".equals(new String(buff, 0, 24))) { + int size = inStream.available(); + if (size == 0) { + size = 1024; } - res = new X509CRLImpl(encoding); - CRL_CASHE.put(hash, encoding, res); + buff = new byte[size]; + int index=0, ch; + while ((ch = inStream.read()) != '-') { + if (ch == -1) { + throw new CRLException( + "Incorrect Base64 encoding: unexpected EOF."); + } + buff[index++] = (byte) ch; + if (index == size) { + byte[] newbuff = new byte[size+1024]; + System.arraycopy(buff, 0, newbuff, 0, size); + buff = newbuff; + } + } + byte[] tmp = new byte[21]; + inStream.read(tmp); + if (!new String(tmp).startsWith("----END X509 CRL-----")) { + throw new CRLException( + "Incorrect Base64 encoding: 'END X509 CRL' expected."); + } + // skip new line: set the position to the next certificate: + inStream.mark(1); + while (((ch = inStream.read()) != -1) && (ch == '\n' || ch == '\r')) { + inStream.mark(1); + } + inStream.reset(); + buff = Base64.decode(buff, index); + if (buff == null) { + throw new CRLException("Incorrect Base64 encoding."); + } + long hash = CRL_CASHE.getHash(buff); + if (CRL_CASHE.contains(hash)) { + X509CRL res = (X509CRL) CRL_CASHE.get(hash, buff); + if (res != null) { + return res; + } + } + X509CRL res = new X509CRLImpl(buff); + CRL_CASHE.put(hash, buff, res); return res; } else { - X509CRL res = new X509CRLImpl(inStream); - CRL_CASHE.put(hash, res.getEncoded(), res); - return res; + inStream.reset(); + long hash = CRL_CASHE.getHash(buff); + if (CRL_CASHE.contains(hash)) { + byte[] encoding = new byte[BerInputStream.getLength(buff)]; + inStream.read(encoding); + CRL res = + (CRL) CRL_CASHE.get(hash, encoding); + if (res != null) { + return res; + } + res = new X509CRLImpl(encoding); + CRL_CASHE.put(hash, encoding, res); + return res; + } else { + X509CRL res = new X509CRLImpl(inStream); + CRL_CASHE.put(hash, res.getEncoded(), res); + return res; + } } } catch (IOException e) { throw new CRLException(e);