/*
 * 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 org.conscrypt;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactorySpi;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * An implementation of {@link java.security.cert.CertificateFactory} based on BoringSSL.
 */
@Internal
public class OpenSSLX509CertificateFactory extends CertificateFactorySpi {
    private static final byte[] PKCS7_MARKER = new byte[] {
            '-', '-', '-', '-', '-', 'B', 'E', 'G', 'I', 'N', ' ', 'P', 'K', 'C', 'S', '7'
    };

    private static final int PUSHBACK_SIZE = 64;

    static class ParsingException extends Exception {
        private static final long serialVersionUID = 8390802697728301325L;

        ParsingException(String message) {
            super(message);
        }

        ParsingException(Exception cause) {
            super(cause);
        }

        ParsingException(String message, Exception cause) {
            super(message, cause);
        }
    }

    /**
     * The code for X509 Certificates and CRL is pretty much the same. We use
     * this abstract class to share the code between them. This makes it ugly,
     * but it's already written in this language anyway.
     */
    private static abstract class Parser<T> {
        T generateItem(InputStream inStream) throws ParsingException {
            if (inStream == null) {
                throw new ParsingException("inStream == null");
            }

            final boolean markable = inStream.markSupported();
            if (markable) {
                inStream.mark(PKCS7_MARKER.length);
            }

            final PushbackInputStream pbis = new PushbackInputStream(inStream, PUSHBACK_SIZE);
            try {
                final byte[] buffer = new byte[PKCS7_MARKER.length];

                final int len = pbis.read(buffer);
                if (len < 0) {
                    /* No need to reset here. The stream was empty or EOF. */
                    throw new ParsingException("inStream is empty");
                }
                pbis.unread(buffer, 0, len);

                if (buffer[0] == '-') {
                    if (len == PKCS7_MARKER.length && Arrays.equals(PKCS7_MARKER, buffer)) {
                        List<? extends T> items = fromPkcs7PemInputStream(pbis);
                        if (items.size() == 0) {
                            return null;
                        }
                        items.get(0);
                    } else {
                        return fromX509PemInputStream(pbis);
                    }
                }

                /* PKCS#7 bags have a byte 0x06 at position 4 in the stream. */
                if (buffer[4] == 0x06) {
                    List<? extends T> certs = fromPkcs7DerInputStream(pbis);
                    if (certs.size() == 0) {
                        return null;
                    }
                    return certs.get(0);
                } else {
                    return fromX509DerInputStream(pbis);
                }
            } catch (Exception e) {
                if (markable) {
                    try {
                        inStream.reset();
                    } catch (IOException ignored) {
                    }
                }
                throw new ParsingException(e);
            }
        }

        Collection<? extends T> generateItems(InputStream inStream)
                throws ParsingException {
            if (inStream == null) {
                throw new ParsingException("inStream == null");
            }
            try {
                if (inStream.available() == 0) {
                    // To avoid returning a immutable list in only one path, we create an
                    // empty list here instead of using Collections.emptyList()
                    return new ArrayList<T>();
                }
            } catch (IOException e) {
                throw new ParsingException("Problem reading input stream", e);
            }

            final boolean markable = inStream.markSupported();
            if (markable) {
                inStream.mark(PUSHBACK_SIZE);
            }

            /* Attempt to see if this is a PKCS#7 bag. */
            final PushbackInputStream pbis = new PushbackInputStream(inStream, PUSHBACK_SIZE);
            try {
                final byte[] buffer = new byte[PKCS7_MARKER.length];

                final int len = pbis.read(buffer);
                if (len < 0) {
                    /* No need to reset here. The stream was empty or EOF. */
                    throw new ParsingException("inStream is empty");
                }
                pbis.unread(buffer, 0, len);

                if (len == PKCS7_MARKER.length && Arrays.equals(PKCS7_MARKER, buffer)) {
                    return fromPkcs7PemInputStream(pbis);
                }

                /* PKCS#7 bags have a byte 0x06 at position 4 in the stream. */
                if (buffer[4] == 0x06) {
                    return fromPkcs7DerInputStream(pbis);
                }
            } catch (Exception e) {
                if (markable) {
                    try {
                        inStream.reset();
                    } catch (IOException ignored) {
                    }
                }
                throw new ParsingException(e);
            }

            /*
             * It wasn't, so just try to keep grabbing certificates until we
             * can't anymore.
             */
            final List<T> coll = new ArrayList<T>();
            T c;
            do {
                /*
                 * If this stream supports marking, try to mark here in case
                 * there is an error during certificate generation.
                 */
                if (markable) {
                    inStream.mark(PUSHBACK_SIZE);
                }

                try {
                    c = generateItem(pbis);
                    coll.add(c);
                } catch (ParsingException e) {
                    /*
                     * If this stream supports marking, attempt to reset it to
                     * the mark before the failure.
                     */
                    if (markable) {
                        try {
                            inStream.reset();
                        } catch (IOException ignored) {
                        }
                    }

                    c = null;
                }
            } while (c != null);

            return coll;
        }

        protected abstract T fromX509PemInputStream(InputStream pbis) throws ParsingException;

        protected abstract T fromX509DerInputStream(InputStream pbis) throws ParsingException;

        protected abstract List<? extends T> fromPkcs7PemInputStream(InputStream is)
                throws ParsingException;

        protected abstract List<? extends T> fromPkcs7DerInputStream(InputStream is)
                throws ParsingException;
    }

    private Parser<OpenSSLX509Certificate> certificateParser =
            new Parser<OpenSSLX509Certificate>() {
                @Override
                public OpenSSLX509Certificate fromX509PemInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509Certificate.fromX509PemInputStream(is);
                }

                @Override
                public OpenSSLX509Certificate fromX509DerInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509Certificate.fromX509DerInputStream(is);
                }

                @Override
                public List<? extends OpenSSLX509Certificate>
                        fromPkcs7PemInputStream(InputStream is) throws ParsingException {
                    return OpenSSLX509Certificate.fromPkcs7PemInputStream(is);
                }

                @Override
                public List<? extends OpenSSLX509Certificate>
                        fromPkcs7DerInputStream(InputStream is) throws ParsingException {
                    return OpenSSLX509Certificate.fromPkcs7DerInputStream(is);
                }
            };

    private Parser<OpenSSLX509CRL> crlParser =
            new Parser<OpenSSLX509CRL>() {
                @Override
                public OpenSSLX509CRL fromX509PemInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509CRL.fromX509PemInputStream(is);
                }

                @Override
                public OpenSSLX509CRL fromX509DerInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509CRL.fromX509DerInputStream(is);
                }

                @Override
                public List<? extends OpenSSLX509CRL> fromPkcs7PemInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509CRL.fromPkcs7PemInputStream(is);
                }

                @Override
                public List<? extends OpenSSLX509CRL> fromPkcs7DerInputStream(InputStream is)
                        throws ParsingException {
                    return OpenSSLX509CRL.fromPkcs7DerInputStream(is);
                }
            };

    public OpenSSLX509CertificateFactory() {}

    @Override
    public Certificate engineGenerateCertificate(InputStream inStream) throws CertificateException {
        try {
            return certificateParser.generateItem(inStream);
        } catch (ParsingException e) {
            throw new CertificateException(e);
        }
    }

    @Override
    public Collection<? extends Certificate> engineGenerateCertificates(
            InputStream inStream) throws CertificateException {
        try {
            return certificateParser.generateItems(inStream);
        } catch (ParsingException e) {
            throw new CertificateException(e);
        }
    }

    @Override
    public CRL engineGenerateCRL(InputStream inStream) throws CRLException {
        try {
            return crlParser.generateItem(inStream);
        } catch (ParsingException e) {
            throw new CRLException(e);
        }
    }

    @Override
    public Collection<? extends CRL> engineGenerateCRLs(InputStream inStream) throws CRLException {
        if (inStream == null) {
            return Collections.emptyList();
        }

        try {
            return crlParser.generateItems(inStream);
        } catch (ParsingException e) {
            throw new CRLException(e);
        }
    }

    @Override
    public Iterator<String> engineGetCertPathEncodings() {
        return OpenSSLX509CertPath.getEncodingsIterator();
    }

    @Override
    public CertPath engineGenerateCertPath(InputStream inStream) throws CertificateException {
        return OpenSSLX509CertPath.fromEncoding(inStream);
    }

    @Override
    public CertPath engineGenerateCertPath(InputStream inStream, String encoding)
            throws CertificateException {
        return OpenSSLX509CertPath.fromEncoding(inStream, encoding);
    }

    @Override
    public CertPath engineGenerateCertPath(List<? extends Certificate> certificates)
            throws CertificateException {
        final List<X509Certificate> filtered = new ArrayList<X509Certificate>(certificates.size());
        for (int i = 0; i < certificates.size(); i++) {
            final Certificate c = certificates.get(i);

            if (!(c instanceof X509Certificate)) {
                throw new CertificateException("Certificate not X.509 type at index " + i);
            }

            filtered.add((X509Certificate) c);
        }

        return new OpenSSLX509CertPath(filtered);
    }
}
