diff options
author | Kenny Root <kroot@google.com> | 2012-12-26 08:44:32 -0800 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2013-01-01 21:50:10 -0800 |
commit | 9ca3d0733e7f93c140fdc693ffb0aaaa21de7a19 (patch) | |
tree | 9b6fe024be737bd535136301c8dc897ee3c86ce3 | |
parent | f0f80b7be6fac9482d06126d5b06357d35fc431d (diff) | |
download | libcore-9ca3d0733e7f93c140fdc693ffb0aaaa21de7a19.zip libcore-9ca3d0733e7f93c140fdc693ffb0aaaa21de7a19.tar.gz libcore-9ca3d0733e7f93c140fdc693ffb0aaaa21de7a19.tar.bz2 |
Add X509CertificateTest in libcore tests
Change-Id: I678a8b89d0514c270ce0ee57057cfaadf3b47543
25 files changed, 1450 insertions, 0 deletions
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java new file mode 100644 index 0000000..e86036b --- /dev/null +++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java @@ -0,0 +1,1081 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.java.security.cert; + +import tests.support.resource.Support_Resources; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Principal; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.SignatureException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateFactory; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.spec.X509EncodedKeySpec; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; + +import junit.framework.TestCase; +import libcore.java.security.StandardNames; + +public class X509CertificateTest extends TestCase { + private Provider[] mX509Providers; + + private static final String CERT_RSA = "x509/cert-rsa.der"; + + private static final String CERT_DSA = "x509/cert-dsa.der"; + + private static final String CERT_EC = "x509/cert-ec.der"; + + private static final String CERT_KEYUSAGE_EXTRALONG = "x509/cert-keyUsage-extraLong.der"; + + private static final String CERT_EXTENDEDKEYUSAGE = "x509/cert-extendedKeyUsage.der"; + + private final static String CERT_RSA_TBS = "x509/cert-rsa-tbs.der"; + + private final static String CERT_RSA_SIGNATURE = "x509/cert-rsa-sig.der"; + + private static final String CERT_USERWITHPATHLEN = "x509/cert-userWithPathLen.der"; + + private static final String CERT_CA = "x509/cert-ca.der"; + + private static final String CERT_CAWITHPATHLEN = "x509/cert-caWithPathLen.der"; + + private static final String CERT_INVALIDIP = "x509/cert-invalidip.der"; + + private static final String CERT_IPV6 = "x509/cert-ipv6.der"; + + private static final String CERT_ALT_OTHER = "x509/cert-alt-other.der"; + + private static final String CERT_ALT_EMAIL = "x509/cert-alt-email.der"; + + private static final String CERT_ALT_DNS = "x509/cert-alt-dns.der"; + + private static final String CERT_ALT_DIRNAME = "x509/cert-alt-dirname.der"; + + private static final String CERT_ALT_URI = "x509/cert-alt-uri.der"; + + private static final String CERT_ALT_RID = "x509/cert-alt-rid.der"; + + private static final String CERT_UNSUPPORTED = "x509/cert-unsupported.der"; + + private final X509Certificate getCertificate(CertificateFactory f, String name) + throws Exception { + final InputStream is = Support_Resources.getStream(name); + assertNotNull("File does not exist: " + name, is); + try { + return (X509Certificate) f.generateCertificate(is); + } finally { + try { + is.close(); + } catch (IOException ignored) { + } + } + } + + private PublicKey getRsaCertificatePublicKey() throws Exception { + final InputStream ris = Support_Resources.getStream("x509/cert-rsa-pubkey.der"); + try { + final int size = ris.available(); + final DataInputStream is = new DataInputStream(ris); + final byte[] keyBytes = new byte[size]; + is.readFully(keyBytes); + + final KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePublic(new X509EncodedKeySpec(keyBytes)); + } finally { + try { + ris.close(); + } catch (IOException ignored) { + } + } + } + + private Date[] getRsaCertificateDates() throws Exception { + final InputStream ris = Support_Resources.getStream("x509/cert-rsa-dates.txt"); + try { + // notBefore=Dec 26 00:19:14 2012 GMT + final SimpleDateFormat sdf = new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz"); + + final BufferedReader buf = new BufferedReader(new InputStreamReader(ris)); + String line = buf.readLine(); + int index = line.indexOf('='); + assertEquals("notBefore", line.substring(0, index)); + final Date startDate = sdf.parse(line.substring(index + 1)); + + line = buf.readLine(); + index = line.indexOf('='); + assertEquals("notAfter", line.substring(0, index)); + final Date endDate = sdf.parse(line.substring(index + 1)); + + assertTrue(startDate.before(endDate)); + assertTrue(endDate.after(startDate)); + + return new Date[] { startDate, endDate }; + } finally { + try { + ris.close(); + } catch (IOException ignored) { + } + } + } + + private BigInteger getRsaCertificateSerial() throws Exception { + final InputStream ris = Support_Resources.getStream("x509/cert-rsa-serial.txt"); + try { + final BufferedReader buf = new BufferedReader(new InputStreamReader(ris)); + + String line = buf.readLine(); + int index = line.indexOf('='); + assertEquals("serial", line.substring(0, index)); + + return new BigInteger(line.substring(index + 1), 16); + } finally { + try { + ris.close(); + } catch (IOException ignored) { + } + } + } + + private byte[] getResourceAsBytes(String name) throws Exception { + final InputStream ris = Support_Resources.getStream(name); + try { + DataInputStream dis = new DataInputStream(ris); + byte[] buf = new byte[ris.available()]; + dis.readFully(buf); + return buf; + } finally { + try { + ris.close(); + } catch (IOException ignored) { + } + } + } + + private byte[] getRsaCertificateSignature() throws Exception { + return getResourceAsBytes(CERT_RSA_SIGNATURE); + } + + private byte[] getRsaCertificateTbs() throws Exception { + return getResourceAsBytes(CERT_RSA_TBS); + } + + public void test_Provider() throws Exception { + final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(errBuffer); + + for (Provider p : mX509Providers) { + try { + CertificateFactory f = CertificateFactory.getInstance("X.509", p); + getPublicKey(f); + getType(f); + check_equals(f); + check_toString(f); + check_hashCode(f); + checkValidity(f); + getVersion(f); + getSerialNumber(f); + getIssuerDN(f); + getIssuerX500Principal(f); + getSubjectDN(f); + getSubjectUniqueID(f); + getSubjectX500Principal(f); + getNotBeforeAndNotAfterDates(f); + getSigAlgName(f); + getSigAlgOID(f); + getSigAlgParams(f); + getIssuerUniqueID(f); + getSubjectUniqueID(f); + getKeyUsage(f); + getExtendedKeyUsage(f); + getBasicConstraints(f); + getSubjectAlternativeNames(f); + getSubjectAlternativeNames_IPV6(f); + getSubjectAlternativeNames_InvalidIP(f); + getSubjectAlternativeNames_Other(f); + getSubjectAlternativeNames_Email(f); + getSubjectAlternativeNames_DNS(f); + getSubjectAlternativeNames_DirName(f); + getSubjectAlternativeNames_URI(f); + getSubjectAlternativeNames_RID(f); + getIssuerAlternativeNames(f); + getTBSCertificate(f); + getSignature(f); + hasUnsupportedCriticalExtension(f); + getEncoded(f); + verify(f); + } catch (Throwable e) { + out.append("Error encountered checking " + p.getName() + "\n"); + e.printStackTrace(out); + } + } + + out.flush(); + if (errBuffer.size() > 0) { + throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n"); + } + } + + private void getPublicKey(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + PublicKey expected = getRsaCertificatePublicKey(); + + PublicKey actual = c.getPublicKey(); + assertEquals(expected, actual); + assertEquals(Arrays.toString(expected.getEncoded()), + Arrays.toString(actual.getEncoded())); + } + + private void getType(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + assertEquals("X.509", c.getType()); + } + + private void verify(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + PublicKey signer = getRsaCertificatePublicKey(); + + c.verify(signer); + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + KeyPair pair = kpg.generateKeyPair(); + PublicKey invalidKey = pair.getPublic(); + + try { + c.verify(invalidKey); + fail("RSA signature should not verify"); + } catch (SignatureException expected) { + } + + Provider[] providers = Security.getProviders("Signature." + c.getSigAlgName()); + for (Provider p : providers) { + c.verify(signer, p.getName()); + + try { + c.verify(invalidKey, p.getName()); + fail("RSA signature should not verify"); + } catch (SignatureException expected) { + } + } + } + + private void check_equals(CertificateFactory f) throws Exception { + X509Certificate c1 = getCertificate(f, CERT_RSA); + X509Certificate c2 = getCertificate(f, CERT_RSA); + + assertEquals(c1, c2); + + X509Certificate c3 = getCertificate(f, CERT_DSA); + assertFalse(c1.equals(c3)); + assertFalse(c3.equals(c1)); + } + + private void check_toString(CertificateFactory f) throws Exception { + X509Certificate c1 = getCertificate(f, CERT_RSA); + + String output1 = c1.toString(); + assertNotNull(output1); + assertTrue(output1.length() > 0); + + X509Certificate c2 = getCertificate(f, CERT_RSA); + assertEquals(c1.toString(), c2.toString()); + + X509Certificate c3 = getCertificate(f, CERT_DSA); + assertFalse(c3.toString().equals(c1.toString())); + } + + private void check_hashCode(CertificateFactory f) throws Exception { + X509Certificate c1 = getCertificate(f, CERT_RSA); + X509Certificate c2 = getCertificate(f, CERT_RSA); + + assertEquals(c1.hashCode(), c2.hashCode()); + + X509Certificate c3 = getCertificate(f, CERT_DSA); + assertFalse(c3.hashCode() == c1.hashCode()); + } + + private void checkValidity(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + Calendar cal = Calendar.getInstance(); + Date[] dates = getRsaCertificateDates(); + + /* + * The certificate validity periods in the test certificate MUST lie + * within the tested period. The API doesn't appear to allow any other + * way to test this code path as an unprivileged user. + */ + Date now = new Date(); + assertTrue(now.after(dates[0])); + assertTrue(now.before(dates[1])); + + /* This assumes the script makes a long-lived cert. */ + c.checkValidity(); + + /* A day after the start date. */ + cal.setTime(dates[0]); + cal.add(Calendar.DAY_OF_MONTH, 1); + c.checkValidity(cal.getTime()); + + /* A second before the start date. */ + cal.setTime(dates[1]); + cal.add(Calendar.SECOND, -1); + c.checkValidity(cal.getTime()); + + try { + cal.setTime(dates[0]); + cal.add(Calendar.SECOND, -1); + c.checkValidity(cal.getTime()); + fail(); + } catch (CertificateNotYetValidException expected) { + } + + try { + cal.setTime(dates[0]); + cal.add(Calendar.MONTH, -6); + c.checkValidity(cal.getTime()); + fail(); + } catch (CertificateNotYetValidException expected) { + } + + try { + cal.setTime(dates[1]); + cal.add(Calendar.SECOND, 1); + c.checkValidity(cal.getTime()); + fail(); + } catch (CertificateExpiredException expected) { + } + + try { + cal.setTime(dates[1]); + cal.add(Calendar.YEAR, 1); + c.checkValidity(cal.getTime()); + fail(); + } catch (CertificateExpiredException expected) { + } + } + + private void getVersion(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + assertEquals(3, c.getVersion()); + } + + private void getSerialNumber(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + BigInteger actual = getRsaCertificateSerial(); + + assertEquals(actual, c.getSerialNumber()); + } + + private void getIssuerDN(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + Principal princ = c.getIssuerDN(); + if (StandardNames.IS_RI) { + assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", + princ.getName()); + } else { + if ("BC".equals(f.getProvider().getName())) { + // TODO: is it acceptable to have this in reverse order? + assertEquals(f.getProvider().getName(), + "C=US,ST=California,L=San Mateo,O=Genius.com Inc,OU=NetOps", + princ.getName()); + } else { + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName()); + } + } + + X509Certificate c2 = getCertificate(f, CERT_RSA); + assertEquals(princ, c2.getIssuerDN()); + } + + private void getIssuerX500Principal(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + final byte[] expected = new byte[] { + 0x30, 0x60, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x53, + 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x6f, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, 0x65, 0x6e, 0x69, 0x75, + 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x0f, 0x30, + 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x06, 0x4e, 0x65, 0x74, 0x4f, + 0x70, 0x73 + }; + X500Principal princ = c.getIssuerX500Principal(); + assertEquals(Arrays.toString(expected), + Arrays.toString(princ.getEncoded())); + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName()); + assertEquals("ou=netops,o=genius.com inc,l=san mateo,st=california,c=us", + princ.getName(X500Principal.CANONICAL)); + assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", + princ.getName(X500Principal.RFC1779)); + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName(X500Principal.RFC2253)); + + X509Certificate c2 = getCertificate(f, CERT_RSA); + assertEquals(princ, c2.getIssuerX500Principal()); + } + + private void getSubjectDN(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + Principal princ = c.getSubjectDN(); + if (StandardNames.IS_RI) { + assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", + princ.getName()); + } else { + if ("BC".equals(f.getProvider().getName())) { + // TODO: is it acceptable to have this in reverse order? + assertEquals(f.getProvider().getName(), + "C=US,ST=California,L=San Mateo,O=Genius.com Inc,OU=NetOps", + princ.getName()); + } else { + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName()); + } + } + + X509Certificate c2 = getCertificate(f, CERT_RSA); + assertEquals(princ, c2.getSubjectDN()); + } + + private void getSubjectUniqueID(CertificateFactory f) throws Exception { + /* This certificate has no unique ID. */ + X509Certificate c = getCertificate(f, CERT_RSA); + assertNull(c.getSubjectUniqueID()); + + // TODO: generate certificate that has a SubjectUniqueID field. + } + + private void getIssuerUniqueID(CertificateFactory f) throws Exception { + /* This certificate has no unique ID. */ + X509Certificate c = getCertificate(f, CERT_RSA); + assertNull(c.getIssuerUniqueID()); + + // TODO: generate certificate that has a IssuerUniqueID field. + } + + private void getSubjectX500Principal(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + final byte[] expected = new byte[] { + 0x30, 0x60, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x53, + 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x6f, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, 0x65, 0x6e, 0x69, 0x75, + 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x0f, 0x30, + 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x06, 0x4e, 0x65, 0x74, 0x4f, + 0x70, 0x73 + }; + X500Principal princ = c.getSubjectX500Principal(); + assertEquals(Arrays.toString(expected), + Arrays.toString(princ.getEncoded())); + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName()); + assertEquals("ou=netops,o=genius.com inc,l=san mateo,st=california,c=us", + princ.getName(X500Principal.CANONICAL)); + assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", + princ.getName(X500Principal.RFC1779)); + assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", + princ.getName(X500Principal.RFC2253)); + + X509Certificate c2 = getCertificate(f, CERT_RSA); + assertEquals(princ, c2.getSubjectX500Principal()); + } + + private static void assertDateEquals(Date date1, Date date2) throws Exception { + SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss"); + + String result1 = formatter.format(date1); + String result2 = formatter.format(date2); + + assertEquals(result1, result2); + } + + private void getNotBeforeAndNotAfterDates(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + Date[] dates = getRsaCertificateDates(); + + assertDateEquals(dates[0], c.getNotBefore()); + assertDateEquals(dates[1], c.getNotAfter()); + } + + private void getSigAlgName(CertificateFactory f) throws Exception { + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_RSA); + assertEquals("SHA1WITHRSA", c.getSigAlgName().toUpperCase(Locale.US)); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_DSA); + assertEquals("SHA1WITHDSA", c.getSigAlgName().toUpperCase(Locale.US)); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_EC); + if (StandardNames.IS_RI) { + assertEquals("SHA1WITHECDSA", c.getSigAlgName().toUpperCase(Locale.US)); + } else { + assertEquals("ECDSA", c.getSigAlgName().toUpperCase(Locale.US)); + } + } + } + + private void getSigAlgOID(CertificateFactory f) throws Exception { + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_RSA); + assertEquals("1.2.840.113549.1.1.5", c.getSigAlgOID()); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_DSA); + assertEquals("1.2.840.10040.4.3", c.getSigAlgOID()); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_EC); + assertEquals("1.2.840.10045.4.1", c.getSigAlgOID()); + } + } + + private void getSigAlgParams(CertificateFactory f) throws Exception { + { + X509Certificate c = getCertificate(f, CERT_RSA); + // Harmony and BC are broken? + String provider = f.getProvider().getName(); + if ("DRLCertFactory".equals(provider) || "BC".equals(provider)) { + assertNotNull(c.getSigAlgParams()); + } else { + assertNull(f.getProvider().getName(), c.getSigAlgParams()); + } + } + + { + X509Certificate c = getCertificate(f, CERT_DSA); + assertNull(f.getProvider().getName(), c.getSigAlgParams()); + } + + { + X509Certificate c = getCertificate(f, CERT_EC); + assertNull(f.getProvider().getName(), c.getSigAlgParams()); + } + } + + private void getKeyUsage(CertificateFactory f) throws Exception { + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_RSA); + boolean[] expected = new boolean[] { + true, /* digitalSignature (0) */ + true, /* nonRepudiation (1) */ + true, /* keyEncipherment (2) */ + false, /* dataEncipherment (3) */ + false, /* keyAgreement (4) */ + false, /* keyCertSign (5) */ + false, /* cRLSign (6) */ + false, /* encipherOnly (7) */ + false, /* decipherOnly (8) */ + }; + assertEquals(Arrays.toString(expected), Arrays.toString(c.getKeyUsage())); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_DSA); + boolean[] expected = new boolean[] { + false, /* digitalSignature (0) */ + false, /* nonRepudiation (1) */ + true, /* keyEncipherment (2) */ + true, /* dataEncipherment (3) */ + false, /* keyAgreement (4) */ + true, /* keyCertSign (5) */ + true, /* cRLSign (6) */ + true, /* encipherOnly (7) */ + false, /* decipherOnly (8) */ + }; + boolean[] actual = c.getKeyUsage(); + assertEquals(9, actual.length); + assertEquals(Arrays.toString(expected), Arrays.toString(actual)); + } + + { + /* The test certificate is sha1WithRSAEncryption */ + X509Certificate c = getCertificate(f, CERT_EC); + boolean[] expected = new boolean[] { + false, /* digitalSignature (0) */ + false, /* nonRepudiation (1) */ + false, /* keyEncipherment (2) */ + false, /* dataEncipherment (3) */ + true, /* keyAgreement (4) */ + false, /* keyCertSign (5) */ + false, /* cRLSign (6) */ + false, /* encipherOnly (7) */ + true, /* decipherOnly (8) */ + }; + boolean[] actual = c.getKeyUsage(); + assertEquals(9, actual.length); + assertEquals(Arrays.toString(expected), Arrays.toString(actual)); + } + + { + /* All the bits are set in addition to some extra ones. */ + X509Certificate c = getCertificate(f, CERT_KEYUSAGE_EXTRALONG); + boolean[] expected = new boolean[] { + true, /* digitalSignature (0) */ + true, /* nonRepudiation (1) */ + true, /* keyEncipherment (2) */ + true, /* dataEncipherment (3) */ + true, /* keyAgreement (4) */ + true, /* keyCertSign (5) */ + true, /* cRLSign (6) */ + true, /* encipherOnly (7) */ + true, /* decipherOnly (8) */ + true, /* ????? (9) */ + true, /* ????? (10) */ + }; + boolean[] actual = c.getKeyUsage(); + assertEquals(11, actual.length); + assertEquals(Arrays.toString(expected), Arrays.toString(actual)); + } + } + + private void getExtendedKeyUsage(CertificateFactory f) throws Exception { + { + /* No ExtendedKeyUsage section */ + final X509Certificate c = getCertificate(f, CERT_RSA); + List<String> actual = c.getExtendedKeyUsage(); + assertNull(actual); + } + + { + /* ExtendedKeyUsage section with one entry of OID 1.2.3.4 */ + final X509Certificate c = getCertificate(f, CERT_EXTENDEDKEYUSAGE); + List<String> actual = c.getExtendedKeyUsage(); + assertNotNull(actual); + assertEquals(1, actual.size()); + assertEquals("1.2.3.4", actual.get(0)); + } + } + + private void getBasicConstraints(CertificateFactory f) throws Exception { + /* Non-CA cert with no pathLenConstraint */ + { + final X509Certificate c = getCertificate(f, CERT_RSA); + assertEquals(f.getProvider().getName(), -1, c.getBasicConstraints()); + } + + /* Non-CA cert with pathLenConstraint */ + { + final X509Certificate c = getCertificate(f, CERT_USERWITHPATHLEN); + assertEquals(f.getProvider().getName(), -1, c.getBasicConstraints()); + } + + /* CA cert with no pathLenConstraint */ + { + final X509Certificate c = getCertificate(f, CERT_CA); + assertEquals(f.getProvider().getName(), Integer.MAX_VALUE, c.getBasicConstraints()); + } + + /* CA cert with pathLenConstraint=10 */ + { + final X509Certificate c = getCertificate(f, CERT_CAWITHPATHLEN); + assertEquals(f.getProvider().getName(), 10, c.getBasicConstraints()); + } + } + + /** Encoding of: OID:1.2.3.4, UTF8:test1 */ + private static byte[] getOIDTestBytes() { + if (StandardNames.IS_RI) { + return new byte[] { 0x30, 0x10, 0x06, 0x03, 0x2a, 0x03, 0x04, (byte) 0xa0, + 0x09, (byte) 0xa0, 0x07, 0x0c, 0x05, 0x74, 0x65, 0x73, 0x74, 0x31 }; + } else { + return new byte[] { (byte) 0xa0, 0x0e, 0x06, 0x03, 0x2a, 0x03, 0x04, + (byte) 0xa0, 0x07, 0x0c, 0x05, 0x74, 0x65, 0x73, 0x74, 0x31 }; + } + } + + private void getSubjectAlternativeNames(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + Collection<List<?>> col = null; + try { + col = c.getSubjectAlternativeNames(); + if ("DRLCertFactory".equals(f.getProvider().getName())) { + fail("Harmony should throw (Provider=" + f.getProvider().getName() + ")"); + } + } catch (CertificateParsingException e) { + if (!"DRLCertFactory".equals(f.getProvider().getName())) { + throw new Exception("Non-Harmony shouldn't throw", e); + } + return; + } + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + checkAlternativeNames(col); + } + + private void checkAlternativeNames(Collection<List<?>> col) { + assertNotNull(col); + + /* + * There should be 9 types of alternative names in this test + * certificate. + */ + boolean[] typesFound = new boolean[9]; + + for (List<?> item : col) { + assertTrue(item.get(0) instanceof Integer); + int type = (Integer) item.get(0); + typesFound[type] = true; + + switch (type) { + case 0: /* OtherName */ + final byte[] der = getOIDTestBytes(); + assertEquals(Arrays.toString(der), Arrays.toString((byte[]) item.get(1))); + break; + case 1: /* rfc822Name: IA5String */ + assertEquals("x509@example.com", (String) item.get(1)); + break; + case 2: /* dNSName: IA5String */ + assertEquals("x509.example.com", (String) item.get(1)); + break; + case 3: /* x400Address: ORAddress */ + assertEquals("UNSUPPORTED", (String) item.get(1)); + break; + case 4: /* directoryName: Name */ + assertEquals("CN=∆ƒ,OU=Über Frîends,O=Awesome Dudes,C=US", (String) item.get(1)); + break; + case 5: /* ediPartyName */ + assertEquals("UNSUPPORTED", Arrays.toString((byte[]) item.get(1))); + break; + case 6: /* uniformResourceIdentifier: IA5String */ + assertEquals("http://www.example.com/?q=awesomeness", (String) item.get(1)); + break; + case 7: /* iPAddress */ + assertEquals("192.168.0.1", (String) item.get(1)); + break; + case 8: + assertEquals("1.2.3.4", (String) item.get(1)); + break; + } + } + + Set<Integer> missing = new HashSet<Integer>(); + for (int i = 0; i < typesFound.length; i++) { + if (!typesFound[i]) { + missing.add(i); + } + } + + // TODO: fix X.400 names and ediPartyName + missing.remove(3); + missing.remove(5); + + if (!missing.isEmpty()) { + fail("Missing types: " + Arrays.toString(missing.toArray(new Integer[missing.size()]))); + } + } + + private void getSubjectAlternativeNames_IPV6(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_IPV6); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(7 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + // RI doesn't apply all the IPv6 shortening rules + if (StandardNames.IS_RI) { + assertEquals("2001:db8:0:0:0:ff00:42:8329", (String) item.get(1)); + } else { + assertEquals("2001:db8::ff00:42:8329", (String) item.get(1)); + } + } + + private void getSubjectAlternativeNames_InvalidIP(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_INVALIDIP); + Collection<List<?>> col = null; + try { + col = c.getSubjectAlternativeNames(); + if ("DRLCertFactory".equals(f.getProvider().getName())) { + fail("Harmony throws (Provider=" + f.getProvider().getName() + ")"); + } + } catch (IllegalArgumentException expected) { + if (!"DRLCertFactory".equals(f.getProvider().getName())) { + fail("Non-Harmony shouldn't throw"); + } + } + assertNull(col); + } + + private void getSubjectAlternativeNames_Other(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_OTHER); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(0 == (Integer) item.get(0)); + + /* OID:1.2.3.4, UTF8:test1 */ + final byte[] der = getOIDTestBytes(); + assertEquals(Arrays.toString(der), Arrays.toString((byte[]) item.get(1))); + } + + private void getSubjectAlternativeNames_Email(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_EMAIL); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(1 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + assertEquals("x509@example.com", (String) item.get(1)); + } + + private void getSubjectAlternativeNames_DNS(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_DNS); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(2 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + assertEquals("x509.example.com", (String) item.get(1)); + } + + private void getSubjectAlternativeNames_DirName(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_DIRNAME); + Collection<List<?>> col = null; + try { + col = c.getSubjectAlternativeNames(); + if ("DRLCertFactory".equals(f.getProvider().getName())) { + fail("Harmony throws (Provider=" + f.getProvider().getName() + ")"); + } + } catch (CertificateParsingException e) { + // Harmony is broken + if (!"DRLCertFactory".equals(f.getProvider().getName())) { + fail("Non-Harmony shouldn't throw"); + } + return; + } + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(String.valueOf((Integer) item.get(0)), 4 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + assertEquals("CN=∆ƒ,OU=Über Frîends,O=Awesome Dudes,C=US", (String) item.get(1)); + } + + private void getSubjectAlternativeNames_URI(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_URI); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(6 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + assertEquals("http://www.example.com/?q=awesomeness", (String) item.get(1)); + } + + private void getSubjectAlternativeNames_RID(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_ALT_RID); + Collection<List<?>> col = c.getSubjectAlternativeNames(); + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + assertNotNull(f.getProvider().getName(), col); + + assertEquals(1, col.size()); + List<?> item = col.iterator().next(); + + assertTrue(item.get(0) instanceof Integer); + assertTrue(8 == (Integer) item.get(0)); + + assertTrue(item.get(1) instanceof String); + assertEquals("1.2.3.4", (String) item.get(1)); + } + + private void getIssuerAlternativeNames(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + Collection<List<?>> col = null; + try { + col = c.getSubjectAlternativeNames(); + if ("DRLCertFactory".equals(f.getProvider().getName())) { + fail("Harmony should throw (Provider=" + f.getProvider().getName() + ")"); + } + } catch (CertificateParsingException e) { + if (!"DRLCertFactory".equals(f.getProvider().getName())) { + throw new Exception("Non-Harmony shouldn't throw", e); + } + return; + } + + // BouncyCastle is broken + if ("BC".equals(f.getProvider().getName())) { + assertNull(col); + return; + } + + checkAlternativeNames(col); + } + + private void getSignature(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + assertEquals(Arrays.toString(getRsaCertificateSignature()), + Arrays.toString(c.getSignature())); + } + + private void getTBSCertificate(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + assertEquals(Arrays.toString(getRsaCertificateTbs()), + Arrays.toString(c.getTBSCertificate())); + } + + private void hasUnsupportedCriticalExtension(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + assertFalse(c.hasUnsupportedCriticalExtension()); + + X509Certificate unsupported = getCertificate(f, CERT_UNSUPPORTED); + assertTrue(unsupported.hasUnsupportedCriticalExtension()); + } + + private void getEncoded(CertificateFactory f) throws Exception { + X509Certificate c = getCertificate(f, CERT_RSA); + + byte[] cBytes = getResourceAsBytes(CERT_RSA); + + assertEquals(Arrays.toString(cBytes), Arrays.toString(c.getEncoded())); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mX509Providers = Security.getProviders("CertificateFactory.X509"); + } +} diff --git a/support/src/test/java/tests/resources/x509/cert-alt-dirname.der b/support/src/test/java/tests/resources/x509/cert-alt-dirname.der Binary files differnew file mode 100644 index 0000000..ae2d2a8 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-dirname.der diff --git a/support/src/test/java/tests/resources/x509/cert-alt-dns.der b/support/src/test/java/tests/resources/x509/cert-alt-dns.der Binary files differnew file mode 100644 index 0000000..008ef31 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-dns.der diff --git a/support/src/test/java/tests/resources/x509/cert-alt-email.der b/support/src/test/java/tests/resources/x509/cert-alt-email.der Binary files differnew file mode 100644 index 0000000..4b0189b --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-email.der diff --git a/support/src/test/java/tests/resources/x509/cert-alt-other.der b/support/src/test/java/tests/resources/x509/cert-alt-other.der Binary files differnew file mode 100644 index 0000000..772d9e9 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-other.der diff --git a/support/src/test/java/tests/resources/x509/cert-alt-rid.der b/support/src/test/java/tests/resources/x509/cert-alt-rid.der Binary files differnew file mode 100644 index 0000000..8a1bf42 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-rid.der diff --git a/support/src/test/java/tests/resources/x509/cert-alt-uri.der b/support/src/test/java/tests/resources/x509/cert-alt-uri.der Binary files differnew file mode 100644 index 0000000..262ffa8 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-alt-uri.der diff --git a/support/src/test/java/tests/resources/x509/cert-ca.der b/support/src/test/java/tests/resources/x509/cert-ca.der Binary files differnew file mode 100644 index 0000000..8699071 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-ca.der diff --git a/support/src/test/java/tests/resources/x509/cert-caWithPathLen.der b/support/src/test/java/tests/resources/x509/cert-caWithPathLen.der Binary files differnew file mode 100644 index 0000000..ac56314 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-caWithPathLen.der diff --git a/support/src/test/java/tests/resources/x509/cert-dsa.der b/support/src/test/java/tests/resources/x509/cert-dsa.der Binary files differnew file mode 100644 index 0000000..9b5e62a --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-dsa.der diff --git a/support/src/test/java/tests/resources/x509/cert-ec.der b/support/src/test/java/tests/resources/x509/cert-ec.der Binary files differnew file mode 100644 index 0000000..a683a5e --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-ec.der diff --git a/support/src/test/java/tests/resources/x509/cert-extendedKeyUsage.der b/support/src/test/java/tests/resources/x509/cert-extendedKeyUsage.der Binary files differnew file mode 100644 index 0000000..be2d20c --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-extendedKeyUsage.der diff --git a/support/src/test/java/tests/resources/x509/cert-invalidip.der b/support/src/test/java/tests/resources/x509/cert-invalidip.der Binary files differnew file mode 100644 index 0000000..63ed7e3 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-invalidip.der diff --git a/support/src/test/java/tests/resources/x509/cert-ipv6.der b/support/src/test/java/tests/resources/x509/cert-ipv6.der Binary files differnew file mode 100644 index 0000000..4ee144a --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-ipv6.der diff --git a/support/src/test/java/tests/resources/x509/cert-keyUsage-extraLong.der b/support/src/test/java/tests/resources/x509/cert-keyUsage-extraLong.der Binary files differnew file mode 100644 index 0000000..464799d --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-keyUsage-extraLong.der diff --git a/support/src/test/java/tests/resources/x509/cert-rsa-dates.txt b/support/src/test/java/tests/resources/x509/cert-rsa-dates.txt new file mode 100644 index 0000000..2bb7733 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa-dates.txt @@ -0,0 +1,2 @@ +notBefore=Dec 31 01:16:36 2012 GMT +notAfter=Dec 29 01:16:36 2022 GMT diff --git a/support/src/test/java/tests/resources/x509/cert-rsa-pubkey.der b/support/src/test/java/tests/resources/x509/cert-rsa-pubkey.der Binary files differnew file mode 100644 index 0000000..dec442f --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa-pubkey.der diff --git a/support/src/test/java/tests/resources/x509/cert-rsa-serial.txt b/support/src/test/java/tests/resources/x509/cert-rsa-serial.txt new file mode 100644 index 0000000..c6f9585 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa-serial.txt @@ -0,0 +1 @@ +serial=925D02E030B81D33 diff --git a/support/src/test/java/tests/resources/x509/cert-rsa-sig.der b/support/src/test/java/tests/resources/x509/cert-rsa-sig.der new file mode 100644 index 0000000..2b80ab0 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa-sig.der @@ -0,0 +1,2 @@ +fD\/o'r9#m
[0n2'9 =^kS5K VILe6$:kOHyd:S=tMTlZK̉F(Q<` +f)
\ No newline at end of file diff --git a/support/src/test/java/tests/resources/x509/cert-rsa-tbs.der b/support/src/test/java/tests/resources/x509/cert-rsa-tbs.der Binary files differnew file mode 100644 index 0000000..6982699 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa-tbs.der diff --git a/support/src/test/java/tests/resources/x509/cert-rsa.der b/support/src/test/java/tests/resources/x509/cert-rsa.der Binary files differnew file mode 100644 index 0000000..5816ec3 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-rsa.der diff --git a/support/src/test/java/tests/resources/x509/cert-unsupported.der b/support/src/test/java/tests/resources/x509/cert-unsupported.der Binary files differnew file mode 100644 index 0000000..525d782 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-unsupported.der diff --git a/support/src/test/java/tests/resources/x509/cert-userWithPathLen.der b/support/src/test/java/tests/resources/x509/cert-userWithPathLen.der Binary files differnew file mode 100644 index 0000000..da64c51 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/cert-userWithPathLen.der diff --git a/support/src/test/java/tests/resources/x509/create.sh b/support/src/test/java/tests/resources/x509/create.sh new file mode 100755 index 0000000..5e78620 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/create.sh @@ -0,0 +1,72 @@ +#!/bin/bash - +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o nounset # Treat unset variables as an error +set -e + +DIR=$(dirname $0) + +openssl req -config ${DIR}/default.cnf -new -nodes -batch > cert-rsa-req.pem +openssl req -in cert-rsa-req.pem -pubkey -noout | openssl rsa -pubin -pubout -outform der > cert-rsa-pubkey.der +openssl x509 -extfile ${DIR}/default.cnf -days 3650 -extensions usr_cert -req -signkey privkey.pem -outform d < cert-rsa-req.pem > cert-rsa.der +rm -f cert-rsa-req.pem + +openssl asn1parse -in cert-rsa.der -inform d -out cert-rsa-tbs.der -noout -strparse 4 +SIG_OFFSET=$(openssl asn1parse -in cert-rsa.der -inform d | tail -1 | cut -f1 -d:) +openssl asn1parse -in cert-rsa.der -inform d -strparse ${SIG_OFFSET} -noout -out cert-rsa-sig.der + +# extract startdate and enddate +openssl x509 -in cert-rsa.der -inform d -noout -startdate -enddate > cert-rsa-dates.txt + +# extract serial +openssl x509 -in cert-rsa.der -inform d -noout -serial > cert-rsa-serial.txt + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions keyUsage_extraLong_cert -req -signkey privkey.pem -outform d > cert-keyUsage-extraLong.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions extendedKeyUsage_cert -req -signkey privkey.pem -outform d > cert-extendedKeyUsage.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions ca_cert -req -signkey privkey.pem -outform d > cert-ca.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions userWithPathLen_cert -req -signkey privkey.pem -outform d > cert-userWithPathLen.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions caWithPathLen_cert -req -signkey privkey.pem -outform d > cert-caWithPathLen.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_other_cert -req -signkey privkey.pem -outform d > cert-alt-other.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_email_cert -req -signkey privkey.pem -outform d > cert-alt-email.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_dns_cert -req -signkey privkey.pem -outform d > cert-alt-dns.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_dirname_cert -req -signkey privkey.pem -outform d > cert-alt-dirname.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_uri_cert -req -signkey privkey.pem -outform d > cert-alt-uri.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions alt_rid_cert -req -signkey privkey.pem -outform d > cert-alt-rid.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions ipv6_cert -req -signkey privkey.pem -outform d > cert-ipv6.der + +openssl req -config ${DIR}/default.cnf -new -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions unsupported_cert -req -signkey privkey.pem -outform d > cert-unsupported.der + +openssl dsaparam -out dsaparam.pem 1024 +openssl req -config ${DIR}/default.cnf -newkey dsa:dsaparam.pem -keyout dsapriv.pem -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions keyUsage_cert -req -signkey dsapriv.pem -outform d > cert-dsa.der +rm -f dsaparam.pem + +openssl ecparam -name sect283k1 -out ecparam.pem +openssl req -config ${DIR}/default.cnf -newkey ec:ecparam.pem -keyout ecpriv.pem -nodes -batch | openssl x509 -extfile ${DIR}/default.cnf -extensions keyUsage_critical_cert -req -signkey ecpriv.pem -outform d > cert-ec.der +rm -f ecparam.pem + +rm -f privkey.pem +rm -f dsapriv.pem +rm -f ecpriv.pem diff --git a/support/src/test/java/tests/resources/x509/default.cnf b/support/src/test/java/tests/resources/x509/default.cnf new file mode 100644 index 0000000..d4b4c80 --- /dev/null +++ b/support/src/test/java/tests/resources/x509/default.cnf @@ -0,0 +1,292 @@ +# This is based on the default OpenSSL configuration file which is +# licensed with the following license: + +# Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# 3. All advertising materials mentioning features or use of this +# software must display the following acknowledgment: +# "This product includes software developed by the OpenSSL Project +# for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +# +# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For written permission, please contact +# openssl-core@openssl.org. +# +# 5. Products derived from this software may not be called "OpenSSL" +# nor may "OpenSSL" appear in their names without prior written +# permission of the OpenSSL Project. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the OpenSSL Project +# for use in the OpenSSL Toolkit (http://www.openssl.org/)" +# +# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# ==================================================================== +# +# This product includes cryptographic software written by Eric Young +# (eay@cryptsoft.com). This product includes software written by Tim +# Hudson (tjh@cryptsoft.com). +# + +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = /root/certificates # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = md5 # which md to use. +preserve = no # keep passed DN ordering + +policy = policy_anything + +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert +string_mask = nombstr +req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = US +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = California + +localityName = Locality Name (eg, city) +localityName_default = San Mateo + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Genius.com Inc + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = NetOps + +commonName = Common Name (eg, your name or your server\'s hostname) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 +unstructuredName = An optional company name + +[ unsupported_cert ] +# Just a made-up OID +1.2.3.4.99999.1.2.3.4 = critical,ASN1:FORMAT:BITLIST,BITSTRING:0,1,2 + +[ keyUsage_critical_cert ] +basicConstraints=CA:FALSE +keyUsage = critical, decipherOnly, keyAgreement + +[ keyUsage_extraLong_cert ] +keyUsage=ASN1:FORMAT:BITLIST,BITSTRING:0,1,2,3,4,5,6,7,8,9,10 + +[ keyUsage_cert ] +basicConstraints=CA:FALSE +keyUsage = encipherOnly, keyEncipherment, dataEncipherment, keyCertSign, cRLSign, cRLSign, keyEncipherment, dataEncipherment, keyCertSign, cRLSign + +[ extendedKeyUsage_cert ] +extendedKeyUsage=1.2.3.4 + +[ userWithPathLen_cert ] +basicConstraints=CA:false,pathlen:10 + +[ ca_cert ] +basicConstraints=CA:true + +[ caWithPathLen_cert ] +basicConstraints=CA:true,pathlen:10 + +[ invalid_ip_cert ] +subjectAltName = ASN1:SEQUENCE:invalid_ip_SEQ +issuerAltName = ASN1:SEQUENCE:invalid_ip_SEQ + +[ invalid_ip_SEQ ] +IP.1 = IMPLICIT:7,FORMAT:HEX,OCTETSTRING:0A + +[ ipv6_cert ] +subjectAltName = ASN1:SEQUENCE:ipv6_SEQ +issuerAltName = ASN1:SEQUENCE:ipv6_SEQ + +[ ipv6_SEQ ] +IP.1 = IMPLICIT:7,FORMAT:HEX,OCTETSTRING:20010DB8000000000000FF0000428329 + +[ usr_cert ] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always +nsComment = "X.509 Unit Test" + +subjectAltName = @alt_names +issuerAltName = @alt_names +#subjectAltName = ASN1:SEQUENCE:raw_alt_names + +[ alt_names ] +otherName.0 = 1.2.3.4;UTF8:test1 +email.0 = x509@example.com +DNS.0 = x509.example.com +dirName.0 = dir_example +URI.0 = http://www.example.com/?q=awesomeness +IP.0 = 192.168.0.1 +RID.0 = 1.2.3.4 + +[ alt_other_cert ] +subjectAltName = otherName:1.2.3.4;UTF8:test1 + +[ alt_email_cert ] +subjectAltName = email:x509@example.com + +[ alt_dns_cert ] +subjectAltName = DNS:x509.example.com + +[ alt_dirname_cert ] +subjectAltName = dirName:dir_example + +[ alt_uri_cert ] +subjectAltName = URI:http://www.example.com/?q=awesomeness + +[ alt_rid_cert ] +subjectAltName = RID:1.2.3.4 + +[ raw_alt_names ] +ediPartyName = IMPLICIT:5,SEQUENCE:ediPartyName_SEQ +x400 = IMPLICIT:3,SEQUENCE:x400_SEQ + +[ x400_SEQ ] +BuiltInStandardAttributes = SEQUENCE:x400_BuiltInStandardAddtributes_SEQ + +[ x400_BuiltInStandardAddtributes_SEQ ] +PersonalName=IMPLICIT:5,SET:x400_PersonalName_SET + +[ x400_PersonalName_SET ] +Surname=IMPLICIT:0,PRINTABLESTRING:Root +GivenName=IMPLICIT:1,PRINTABLESTRING:Kenny + +[ ediPartyName_SEQ ] +partyName = IMPLICIT:1,PRINTABLESTRING:Joe + +[ dir_example ] +C=US +O=Awesome Dudes +OU=Über Frîends +CN=example X.509 +CN=∆ƒ + +[ v3_req ] +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names +issuerAltName = @alt_names +basicConstraints=CA:FALSE +nsComment = "X.509 Unit Test" + +[ v3_ca ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints = CA:true + +[ crl_ext ] +authorityKeyIdentifier=keyid:always,issuer:always |