132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root/*
232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Copyright (C) 2012 The Android Open Source Project
332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root *
432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * you may not use this file except in compliance with the License.
632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * You may obtain a copy of the License at
732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root *
832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root *
1032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * Unless required by applicable law or agreed to in writing, software
1132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
1232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * See the License for the specific language governing permissions and
1432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root * limitations under the License.
1532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root */
1632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
1832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
1932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.io.IOException;
2032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.io.InputStream;
2132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.io.PushbackInputStream;
2232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CRL;
2332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CRLException;
24e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Rootimport java.security.cert.CertPath;
2532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.Certificate;
2632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateException;
2732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.security.cert.CertificateFactorySpi;
28e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Rootimport java.security.cert.X509Certificate;
2932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.ArrayList;
3032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Arrays;
3132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Collection;
3232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.Collections;
33e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Rootimport java.util.Iterator;
3432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootimport java.util.List;
3532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
3632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootpublic class OpenSSLX509CertificateFactory extends CertificateFactorySpi {
373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    private static final byte[] PKCS7_MARKER = new byte[] {
383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            '-', '-', '-', '-', '-', 'B', 'E', 'G', 'I', 'N', ' ', 'P', 'K', 'C', 'S', '7'
393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    };
4032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
4132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    private static final int PUSHBACK_SIZE = 64;
4232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
4332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    static class ParsingException extends Exception {
4432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        private static final long serialVersionUID = 8390802697728301325L;
4532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
4632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        public ParsingException(String message) {
4732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            super(message);
4832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
4932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
5032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        public ParsingException(Exception cause) {
5132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            super(cause);
5232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
5332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
5432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        public ParsingException(String message, Exception cause) {
5532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            super(message, cause);
5632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
5732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
5832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
5932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    /**
6032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     * The code for X509 Certificates and CRL is pretty much the same. We use
6132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     * this abstract class to share the code between them. This makes it ugly,
6232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     * but it's already written in this language anyway.
6332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root     */
6432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    private static abstract class Parser<T> {
6532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        public T generateItem(InputStream inStream) throws ParsingException {
66eb1df6f347f30dc40815f3776b47632a10216660Kenny Root            if (inStream == null) {
67eb1df6f347f30dc40815f3776b47632a10216660Kenny Root                throw new ParsingException("inStream == null");
68eb1df6f347f30dc40815f3776b47632a10216660Kenny Root            }
69eb1df6f347f30dc40815f3776b47632a10216660Kenny Root
7032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            final boolean markable = inStream.markSupported();
7132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            if (markable) {
7232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                inStream.mark(PKCS7_MARKER.length);
7332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
7432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
7532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            final PushbackInputStream pbis = new PushbackInputStream(inStream, PUSHBACK_SIZE);
7632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            try {
7732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                final byte[] buffer = new byte[PKCS7_MARKER.length];
7832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
7932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                final int len = pbis.read(buffer);
8032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (len < 0) {
8132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    /* No need to reset here. The stream was empty or EOF. */
8232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    throw new ParsingException("inStream is empty");
8332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
8432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                pbis.unread(buffer, 0, len);
8532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
8632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (buffer[0] == '-') {
8732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    if (len == PKCS7_MARKER.length && Arrays.equals(PKCS7_MARKER, buffer)) {
8832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        List<? extends T> items = fromPkcs7PemInputStream(pbis);
8932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        if (items.size() == 0) {
9032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                            return null;
9132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        }
9232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        items.get(0);
9332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    } else {
9432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        return fromX509PemInputStream(pbis);
9532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    }
9632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
9732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
9832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                /* PKCS#7 bags have a byte 0x06 at position 4 in the stream. */
9932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (buffer[4] == 0x06) {
10032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    List<? extends T> certs = fromPkcs7DerInputStream(pbis);
10132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    if (certs.size() == 0) {
10232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        return null;
10332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    }
10432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return certs.get(0);
10532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                } else {
10632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return fromX509DerInputStream(pbis);
10732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
10832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            } catch (Exception e) {
10932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (markable) {
11032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    try {
11132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        inStream.reset();
11232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    } catch (IOException ignored) {
11332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    }
11432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
11532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throw new ParsingException(e);
11632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
11732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
11832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
11932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        public Collection<? extends T> generateItems(InputStream inStream)
12032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throws ParsingException {
121881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root            if (inStream == null) {
1226faa71701f8f8a985db5e914369c97d511532886Kenny Root                throw new ParsingException("inStream == null");
123881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root            }
12432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            try {
125881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root                if (inStream.available() == 0) {
12632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return Collections.emptyList();
12732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
12832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            } catch (IOException e) {
12932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throw new ParsingException("Problem reading input stream", e);
13032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
13132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
13232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            final boolean markable = inStream.markSupported();
13332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            if (markable) {
13432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                inStream.mark(PUSHBACK_SIZE);
13532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
13632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
13732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            /* Attempt to see if this is a PKCS#7 bag. */
13832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            final PushbackInputStream pbis = new PushbackInputStream(inStream, PUSHBACK_SIZE);
13932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            try {
14032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                final byte[] buffer = new byte[PKCS7_MARKER.length];
14132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
14232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                final int len = pbis.read(buffer);
14332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (len < 0) {
14432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    /* No need to reset here. The stream was empty or EOF. */
14532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    throw new ParsingException("inStream is empty");
14632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
14732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                pbis.unread(buffer, 0, len);
14832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
14932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (len == PKCS7_MARKER.length && Arrays.equals(PKCS7_MARKER, buffer)) {
15032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return fromPkcs7PemInputStream(pbis);
15132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
15232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
15332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                /* PKCS#7 bags have a byte 0x06 at position 4 in the stream. */
15432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (buffer[4] == 0x06) {
15532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return fromPkcs7DerInputStream(pbis);
15632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
15732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            } catch (Exception e) {
15832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (markable) {
15932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    try {
16032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        inStream.reset();
16132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    } catch (IOException ignored) {
16232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    }
16332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
16432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throw new ParsingException(e);
16532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            }
16632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
16732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            /*
16832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root             * It wasn't, so just try to keep grabbing certificates until we
16932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root             * can't anymore.
17032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root             */
17132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            final List<T> coll = new ArrayList<T>();
17232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            T c = null;
17332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            do {
17432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                /*
17532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                 * If this stream supports marking, try to mark here in case
17632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                 * there is an error during certificate generation.
17732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                 */
17832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                if (markable) {
17932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    inStream.mark(PUSHBACK_SIZE);
18032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
18132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
18232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                try {
18332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    c = generateItem(pbis);
18432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    coll.add(c);
18532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                } catch (ParsingException e) {
18632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    /*
18732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                     * If this stream supports marking, attempt to reset it to
18832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                     * the mark before the failure.
18932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                     */
19032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    if (markable) {
19132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        try {
19232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                            inStream.reset();
19332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        } catch (IOException ignored) {
19432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        }
19532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    }
19632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
19732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    c = null;
19832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
19932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            } while (c != null);
20032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
20132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            return coll;
20232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
20332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
20432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        protected abstract T fromX509PemInputStream(InputStream pbis) throws ParsingException;
20532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
20632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        protected abstract T fromX509DerInputStream(InputStream pbis) throws ParsingException;
20732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
20832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        protected abstract List<? extends T> fromPkcs7PemInputStream(InputStream is)
20932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throws ParsingException;
21032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
21132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        protected abstract List<? extends T> fromPkcs7DerInputStream(InputStream is)
21232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                throws ParsingException;
21332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
21432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
21532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    private Parser<OpenSSLX509Certificate> certificateParser =
21632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            new Parser<OpenSSLX509Certificate>() {
21732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
21832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public OpenSSLX509Certificate fromX509PemInputStream(InputStream is)
21932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
22032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509Certificate.fromX509PemInputStream(is);
22132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
22232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
22332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
22432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public OpenSSLX509Certificate fromX509DerInputStream(InputStream is)
22532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
22632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509Certificate.fromX509DerInputStream(is);
22732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
22832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
22932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
23032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public List<? extends OpenSSLX509Certificate>
23132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        fromPkcs7PemInputStream(InputStream is) throws ParsingException {
23232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509Certificate.fromPkcs7PemInputStream(is);
23332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
23432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
23532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
23632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public List<? extends OpenSSLX509Certificate>
23732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        fromPkcs7DerInputStream(InputStream is) throws ParsingException {
23832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509Certificate.fromPkcs7DerInputStream(is);
23932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
24032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            };
24132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
24232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    private Parser<OpenSSLX509CRL> crlParser =
24332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            new Parser<OpenSSLX509CRL>() {
24432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
24532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public OpenSSLX509CRL fromX509PemInputStream(InputStream is)
24632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
24732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509CRL.fromX509PemInputStream(is);
24832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
24932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
25032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
25132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public OpenSSLX509CRL fromX509DerInputStream(InputStream is)
25232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
25332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509CRL.fromX509DerInputStream(is);
25432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
25532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
25632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
25732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public List<? extends OpenSSLX509CRL> fromPkcs7PemInputStream(InputStream is)
25832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
25932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509CRL.fromPkcs7PemInputStream(is);
26032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
26132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
26232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                @Override
26332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                public List<? extends OpenSSLX509CRL> fromPkcs7DerInputStream(InputStream is)
26432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                        throws ParsingException {
26532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    return OpenSSLX509CRL.fromPkcs7DerInputStream(is);
26632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                }
26732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            };
26832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
26932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    @Override
27032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    public Certificate engineGenerateCertificate(InputStream inStream) throws CertificateException {
27132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        try {
27232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            return certificateParser.generateItem(inStream);
27332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        } catch (ParsingException e) {
27432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            throw new CertificateException(e);
27532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
27632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
27732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
27832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    @Override
27932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    public Collection<? extends Certificate> engineGenerateCertificates(
28032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            InputStream inStream) throws CertificateException {
28132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        try {
28232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            return certificateParser.generateItems(inStream);
28332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        } catch (ParsingException e) {
28432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            throw new CertificateException(e);
28532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
28632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
28732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
28832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    @Override
28932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    public CRL engineGenerateCRL(InputStream inStream) throws CRLException {
29032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        try {
29132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            return crlParser.generateItem(inStream);
29232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        } catch (ParsingException e) {
29332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            throw new CRLException(e);
29432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
29532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
29632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
29732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    @Override
29832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    public Collection<? extends CRL> engineGenerateCRLs(InputStream inStream) throws CRLException {
299881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root        if (inStream == null) {
300881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root            return Collections.emptyList();
301881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root        }
302881c794faa5fd0a4498a5f331c2fc92dd23b26a2Kenny Root
30332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        try {
30432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            return crlParser.generateItems(inStream);
30532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        } catch (ParsingException e) {
30632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root            throw new CRLException(e);
30732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        }
30832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
309e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
310e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    @Override
311e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    public Iterator<String> engineGetCertPathEncodings() {
312e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        return OpenSSLX509CertPath.getEncodingsIterator();
313e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    }
314e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
315e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    @Override
316e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    public CertPath engineGenerateCertPath(InputStream inStream) throws CertificateException {
317e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        return OpenSSLX509CertPath.fromEncoding(inStream);
318e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    }
319e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
320e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    @Override
321e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    public CertPath engineGenerateCertPath(InputStream inStream, String encoding)
322e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            throws CertificateException {
323e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        return OpenSSLX509CertPath.fromEncoding(inStream, encoding);
324e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    }
325e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
326e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    @Override
327e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    public CertPath engineGenerateCertPath(List<? extends Certificate> certificates)
328e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            throws CertificateException {
329e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        final List<X509Certificate> filtered = new ArrayList<X509Certificate>(certificates.size());
330e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        for (int i = 0; i < certificates.size(); i++) {
331e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            final Certificate c = certificates.get(i);
332e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
333e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            if (!(c instanceof X509Certificate)) {
334e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root                throw new CertificateException("Certificate not X.509 type at index " + i);
335e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            }
336e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
337e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root            filtered.add((X509Certificate) c);
338e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        }
339e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root
340e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root        return new OpenSSLX509CertPath(filtered);
341e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    }
34232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
343