1 /* X509CertificateFactory.java -- generates X.509 certificates. 2 Copyright (C) 2003 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.java.security.provider; 40 41 import gnu.java.io.Base64InputStream; 42 import gnu.java.lang.CPStringBuilder; 43 import gnu.java.security.x509.X509CRL; 44 import gnu.java.security.x509.X509CertPath; 45 import gnu.java.security.x509.X509Certificate; 46 47 import java.io.BufferedInputStream; 48 import java.io.EOFException; 49 import java.io.IOException; 50 import java.io.InputStream; 51 import java.security.cert.CRL; 52 import java.security.cert.CRLException; 53 import java.security.cert.CertPath; 54 import java.security.cert.Certificate; 55 import java.security.cert.CertificateEncodingException; 56 import java.security.cert.CertificateException; 57 import java.security.cert.CertificateFactorySpi; 58 import java.util.Collection; 59 import java.util.Iterator; 60 import java.util.LinkedList; 61 import java.util.List; 62 63 public class X509CertificateFactory 64 extends CertificateFactorySpi 65 { 66 public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----"; 67 68 public static final String END_CERTIFICATE = "-----END CERTIFICATE-----"; 69 70 public static final String BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; 71 72 public static final String END_X509_CRL = "-----END X509 CRL-----"; 73 X509CertificateFactory()74 public X509CertificateFactory() 75 { 76 super(); 77 } 78 engineGenerateCertificate(InputStream inStream)79 public Certificate engineGenerateCertificate(InputStream inStream) 80 throws CertificateException 81 { 82 try 83 { 84 return generateCert(inStream); 85 } 86 catch (IOException ioe) 87 { 88 CertificateException ce = new CertificateException(ioe.getMessage()); 89 ce.initCause(ioe); 90 throw ce; 91 } 92 } 93 engineGenerateCertificates(InputStream inStream)94 public Collection engineGenerateCertificates(InputStream inStream) 95 throws CertificateException 96 { 97 LinkedList certs = new LinkedList(); 98 while (true) 99 { 100 try 101 { 102 certs.add(generateCert(inStream)); 103 } 104 catch (EOFException eof) 105 { 106 break; 107 } 108 catch (IOException ioe) 109 { 110 CertificateException ce = new CertificateException(ioe.getMessage()); 111 ce.initCause(ioe); 112 throw ce; 113 } 114 } 115 return certs; 116 } 117 engineGenerateCRL(InputStream inStream)118 public CRL engineGenerateCRL(InputStream inStream) throws CRLException 119 { 120 try 121 { 122 return generateCRL(inStream); 123 } 124 catch (IOException ioe) 125 { 126 CRLException crle = new CRLException(ioe.getMessage()); 127 crle.initCause(ioe); 128 throw crle; 129 } 130 } 131 engineGenerateCRLs(InputStream inStream)132 public Collection engineGenerateCRLs(InputStream inStream) 133 throws CRLException 134 { 135 LinkedList crls = new LinkedList(); 136 while (true) 137 { 138 try 139 { 140 crls.add(generateCRL(inStream)); 141 } 142 catch (EOFException eof) 143 { 144 break; 145 } 146 catch (IOException ioe) 147 { 148 CRLException crle = new CRLException(ioe.getMessage()); 149 crle.initCause(ioe); 150 throw crle; 151 } 152 } 153 return crls; 154 } 155 engineGenerateCertPath(List certs)156 public CertPath engineGenerateCertPath(List certs) 157 { 158 return new X509CertPath(certs); 159 } 160 engineGenerateCertPath(InputStream in)161 public CertPath engineGenerateCertPath(InputStream in) 162 throws CertificateEncodingException 163 { 164 return new X509CertPath(in); 165 } 166 engineGenerateCertPath(InputStream in, String encoding)167 public CertPath engineGenerateCertPath(InputStream in, String encoding) 168 throws CertificateEncodingException 169 { 170 return new X509CertPath(in, encoding); 171 } 172 engineGetCertPathEncodings()173 public Iterator engineGetCertPathEncodings() 174 { 175 return X509CertPath.ENCODINGS.iterator(); 176 } 177 generateCert(InputStream inStream)178 private X509Certificate generateCert(InputStream inStream) 179 throws IOException, CertificateException 180 { 181 if (inStream == null) 182 throw new CertificateException("missing input stream"); 183 if (! inStream.markSupported()) 184 inStream = new BufferedInputStream(inStream, 8192); 185 inStream.mark(20); 186 int i = inStream.read(); 187 if (i == -1) 188 throw new EOFException(); 189 // If the input is in binary DER format, the first byte MUST be 190 // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the 191 // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set. 192 // 193 // So if we do not see 0x30 here we will assume it is in Base-64. 194 if (i != 0x30) 195 { 196 inStream.reset(); 197 CPStringBuilder line = new CPStringBuilder(80); 198 do 199 { 200 line.setLength(0); 201 do 202 { 203 i = inStream.read(); 204 if (i == -1) 205 throw new EOFException(); 206 if (i != '\n' && i != '\r') 207 line.append((char) i); 208 } 209 while (i != '\n' && i != '\r'); 210 } 211 while (! line.toString().equals(BEGIN_CERTIFICATE)); 212 X509Certificate ret = new X509Certificate( 213 new BufferedInputStream(new Base64InputStream(inStream), 8192)); 214 line.setLength(0); 215 line.append('-'); // Base64InputStream will eat this. 216 do 217 { 218 i = inStream.read(); 219 if (i == -1) 220 throw new EOFException(); 221 if (i != '\n' && i != '\r') 222 line.append((char) i); 223 } 224 while (i != '\n' && i != '\r'); 225 // XXX ??? 226 if (! line.toString().equals(END_CERTIFICATE)) 227 throw new CertificateException("no end-of-certificate marker"); 228 return ret; 229 } 230 else 231 { 232 inStream.reset(); 233 return new X509Certificate(inStream); 234 } 235 } 236 generateCRL(InputStream inStream)237 private X509CRL generateCRL(InputStream inStream) throws IOException, 238 CRLException 239 { 240 if (inStream == null) 241 throw new CRLException("missing input stream"); 242 if (! inStream.markSupported()) 243 inStream = new BufferedInputStream(inStream, 8192); 244 inStream.mark(20); 245 int i = inStream.read(); 246 if (i == -1) 247 throw new EOFException(); 248 // If the input is in binary DER format, the first byte MUST be 249 // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the 250 // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set. 251 // 252 // So if we do not see 0x30 here we will assume it is in Base-64. 253 if (i != 0x30) 254 { 255 inStream.reset(); 256 CPStringBuilder line = new CPStringBuilder(80); 257 do 258 { 259 line.setLength(0); 260 do 261 { 262 i = inStream.read(); 263 if (i == -1) 264 throw new EOFException(); 265 if (i != '\n' && i != '\r') 266 line.append((char) i); 267 } 268 while (i != '\n' && i != '\r'); 269 } 270 while (! line.toString().startsWith(BEGIN_X509_CRL)); 271 X509CRL ret = new X509CRL( 272 new BufferedInputStream(new Base64InputStream(inStream), 8192)); 273 line.setLength(0); 274 line.append('-'); // Base64InputStream will eat this. 275 do 276 { 277 i = inStream.read(); 278 if (i == -1) 279 throw new EOFException(); 280 if (i != '\n' && i != '\r') 281 line.append((char) i); 282 } 283 while (i != '\n' && i != '\r'); 284 // XXX ??? 285 if (! line.toString().startsWith(END_X509_CRL)) 286 throw new CRLException("no end-of-CRL marker"); 287 return ret; 288 } 289 else 290 { 291 inStream.reset(); 292 return new X509CRL(inStream); 293 } 294 } 295 } 296