120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang/* 220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * Copyright (C) 2013 The Android Open Source Project 338ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang * 420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * Licensed under the Apache License, Version 2.0 (the "License"); 520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * you may not use this file except in compliance with the License. 620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * You may obtain a copy of the License at 720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * 820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * http://www.apache.org/licenses/LICENSE-2.0 920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * 1020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * Unless required by applicable law or agreed to in writing, software 1120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * distributed under the License is distributed on an "AS IS" BASIS, 1220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * See the License for the specific language governing permissions and 1420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * limitations under the License. 1520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang */ 1620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 1720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changpackage org.conscrypt; 1820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 1920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.io.IOException; 2020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.io.InputStream; 2120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.io.PushbackInputStream; 2220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.security.cert.CertPath; 2338ef2572d26fc760c584a1855a3d002f34eb0231Jiho Changimport java.security.cert.Certificate; 2420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.security.cert.CertificateEncodingException; 2538ef2572d26fc760c584a1855a3d002f34eb0231Jiho Changimport java.security.cert.CertificateException; 2620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.security.cert.X509Certificate; 2720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.util.ArrayList; 2820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.util.Arrays; 2920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.util.Collections; 3020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.util.Iterator; 3120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport java.util.List; 3220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changimport org.conscrypt.OpenSSLX509CertificateFactory.ParsingException; 3320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 3420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Changpublic class OpenSSLX509CertPath extends CertPath { 3520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static final byte[] PKCS7_MARKER = "-----BEGIN PKCS7".getBytes(); 3620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 3720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static final int PUSHBACK_SIZE = 64; 3820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 3920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang /** 4020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * Supported encoding types for CerthPath. Used by the various APIs that 4120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang * encode this into bytes such as {@link #getEncoded()}. 4220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang */ 4320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private enum Encoding { 4420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang PKI_PATH("PkiPath"), 4520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang PKCS7("PKCS7"); 4638ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 4720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private final String apiName; 4820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 4920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang Encoding(String apiName) { 5020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang this.apiName = apiName; 5120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 5220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 5320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang static Encoding findByApiName(String apiName) throws CertificateEncodingException { 5420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang for (Encoding element : values()) { 5520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (element.apiName.equals(apiName)) { 5620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return element; 5720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 5820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 5920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 6020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return null; 6120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 6220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 6320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 6420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang /** Unmodifiable list of encodings for the API. */ 6520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static final List<String> ALL_ENCODINGS = Collections.unmodifiableList(Arrays 6620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang .asList(new String[] { 6720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang Encoding.PKI_PATH.apiName, 6820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang Encoding.PKCS7.apiName, 6920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang })); 7020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 7120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static final Encoding DEFAULT_ENCODING = Encoding.PKI_PATH; 7220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 7320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private final List<? extends X509Certificate> mCertificates; 7420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 7520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang static Iterator<String> getEncodingsIterator() { 7620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return ALL_ENCODINGS.iterator(); 7720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 7820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 7920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang protected OpenSSLX509CertPath(List<? extends X509Certificate> certificates) { 8020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang super("X.509"); 8120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 8220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang mCertificates = certificates; 8320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 8420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 8520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang @Override 8620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang public List<? extends Certificate> getCertificates() { 8720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return Collections.unmodifiableList(mCertificates); 8820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 8920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 9020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private byte[] getEncoded(Encoding encoding) throws CertificateEncodingException { 9120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final OpenSSLX509Certificate[] certs = new OpenSSLX509Certificate[mCertificates.size()]; 9220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final long[] certRefs = new long[certs.length]; 9320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 9420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang for (int i = 0, j = certs.length - 1; j >= 0; i++, j--) { 9520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final X509Certificate cert = mCertificates.get(i); 9620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 9720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (cert instanceof OpenSSLX509Certificate) { 9820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang certs[j] = (OpenSSLX509Certificate) cert; 9920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } else { 10020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang certs[j] = OpenSSLX509Certificate.fromX509Der(cert.getEncoded()); 10120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 10220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 10320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang certRefs[j] = certs[j].getContext(); 10420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 10520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 10620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang switch (encoding) { 10720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang case PKI_PATH: 10820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return NativeCrypto.ASN1_seq_pack_X509(certRefs); 10920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang case PKCS7: 11020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return NativeCrypto.i2d_PKCS7(certRefs); 11120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang default: 11220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new CertificateEncodingException("Unknown encoding"); 11320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 11420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 11520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 11620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang @Override 11720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang public byte[] getEncoded() throws CertificateEncodingException { 11820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return getEncoded(DEFAULT_ENCODING); 11920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 12020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 12120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang @Override 12220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang public byte[] getEncoded(String encoding) throws CertificateEncodingException { 12320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang Encoding enc = Encoding.findByApiName(encoding); 12420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (enc == null) { 12520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new CertificateEncodingException("Invalid encoding: " + encoding); 12620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 12720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 12820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return getEncoded(enc); 12920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 13020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 13120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang @Override 13220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang public Iterator<String> getEncodings() { 13320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return getEncodingsIterator(); 13420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 13520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 13620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static CertPath fromPkiPathEncoding(InputStream inStream) throws CertificateException { 13720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(inStream); 13820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 13920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final boolean markable = inStream.markSupported(); 14020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (markable) { 14120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang inStream.mark(PUSHBACK_SIZE); 14220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 14320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 14420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final long[] certRefs; 14520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang try { 14620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang certRefs = NativeCrypto.ASN1_seq_unpack_X509_bio(bis.getBioContext()); 14720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } catch (Exception e) { 14820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (markable) { 14920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang try { 15020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang inStream.reset(); 15120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } catch (IOException ignored) { 15220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 15320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 15420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new CertificateException(e); 15520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } finally { 15620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang NativeCrypto.BIO_free(bis.getBioContext()); 15720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 15820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 15920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (certRefs == null) { 16020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return new OpenSSLX509CertPath(Collections.<X509Certificate> emptyList()); 16120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 16220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 16320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final List<OpenSSLX509Certificate> certs = 16420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang new ArrayList<OpenSSLX509Certificate>(certRefs.length); 16520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang for (int i = certRefs.length - 1; i >= 0; i--) { 16620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (certRefs[i] == 0) { 16720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang continue; 16820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 16920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang certs.add(new OpenSSLX509Certificate(certRefs[i])); 17020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 17120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 17220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return new OpenSSLX509CertPath(certs); 17320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 17420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 17520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static CertPath fromPkcs7Encoding(InputStream inStream) throws CertificateException { 17620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang try { 17720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (inStream == null || inStream.available() == 0) { 17820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return new OpenSSLX509CertPath(Collections.<X509Certificate> emptyList()); 17920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 18020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } catch (IOException e) { 18120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new CertificateException("Problem reading input stream", e); 18220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 18320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 18420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final boolean markable = inStream.markSupported(); 18520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (markable) { 18620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang inStream.mark(PUSHBACK_SIZE); 18720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 18820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 18920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang /* Attempt to see if this is a PKCS#7 bag. */ 19020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final PushbackInputStream pbis = new PushbackInputStream(inStream, PUSHBACK_SIZE); 19120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang try { 19220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang final byte[] buffer = new byte[PKCS7_MARKER.length]; 19320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 1946201909bad11eab8339ec8dbef4d0152231308afDima Zavin final int len = pbis.read(buffer); 19520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (len < 0) { 19620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang /* No need to reset here. The stream was empty or EOF. */ 19720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new ParsingException("inStream is empty"); 19820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 19920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang pbis.unread(buffer, 0, len); 20020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 20120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (len == PKCS7_MARKER.length && Arrays.equals(PKCS7_MARKER, buffer)) { 20220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return new OpenSSLX509CertPath(OpenSSLX509Certificate.fromPkcs7PemInputStream(pbis)); 20320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 20420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang 2050996d9d5d25dcf3c90e40288a2e151dfbbf16959Dima Zavin return new OpenSSLX509CertPath(OpenSSLX509Certificate.fromPkcs7DerInputStream(pbis)); 20620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } catch (Exception e) { 20720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (markable) { 20820d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang try { 20920d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang inStream.reset(); 21020d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } catch (IOException ignored) { 21120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 21220d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 21320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang throw new CertificateException(e); 21420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 21520d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 21638ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 21720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang private static CertPath fromEncoding(InputStream inStream, Encoding encoding) 21838ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang throws CertificateException { 21938ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang switch (encoding) { 22038ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang case PKI_PATH: 22138ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang return fromPkiPathEncoding(inStream); 22238ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang case PKCS7: 22338ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang return fromPkcs7Encoding(inStream); 22438ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang default: 22538ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang throw new CertificateEncodingException("Unknown encoding"); 22638ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang } 22720d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 22838ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 22938ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang public static CertPath fromEncoding(InputStream inStream, String encoding) 23038ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang throws CertificateException { 23120d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (inStream == null) { 23238ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang throw new CertificateException("inStream == null"); 23320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang } 23438ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 23538ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang Encoding enc = Encoding.findByApiName(encoding); 23620d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang if (enc == null) { 23738ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang throw new CertificateException("Invalid encoding: " + encoding); 23838ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang } 23938ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 240d866f455acab131be8f058733abd9c1ede2fcfeaSeungBeom Kim return fromEncoding(inStream, enc); 24138ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang } 24238ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang 24320d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang public static CertPath fromEncoding(InputStream inStream) throws CertificateException { 24420d3e6e3118a6e19627296e9247e948d54ec0fb8Jiho Chang return fromEncoding(inStream, DEFAULT_ENCODING); 24538ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang } 24638ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang} 24738ef2572d26fc760c584a1855a3d002f34eb0231Jiho Chang