Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/provider/X509Factory.java
41159 views
1
/*
2
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.provider;
27
28
import java.io.*;
29
import java.security.PublicKey;
30
import java.util.*;
31
import java.security.cert.*;
32
33
import jdk.internal.event.EventHelper;
34
import jdk.internal.event.X509CertificateEvent;
35
import sun.security.util.KeyUtil;
36
import sun.security.util.Pem;
37
import sun.security.x509.*;
38
import sun.security.pkcs.PKCS7;
39
import sun.security.provider.certpath.X509CertPath;
40
import sun.security.provider.certpath.X509CertificatePair;
41
import sun.security.util.DerValue;
42
import sun.security.util.Cache;
43
import java.util.Base64;
44
import sun.security.pkcs.ParsingException;
45
46
/**
47
* This class defines a certificate factory for X.509 v3 certificates {@literal &}
48
* certification paths, and X.509 v2 certificate revocation lists (CRLs).
49
*
50
* @author Jan Luehe
51
* @author Hemma Prafullchandra
52
* @author Sean Mullan
53
*
54
*
55
* @see java.security.cert.CertificateFactorySpi
56
* @see java.security.cert.Certificate
57
* @see java.security.cert.CertPath
58
* @see java.security.cert.CRL
59
* @see java.security.cert.X509Certificate
60
* @see java.security.cert.X509CRL
61
* @see sun.security.x509.X509CertImpl
62
* @see sun.security.x509.X509CRLImpl
63
*/
64
65
public class X509Factory extends CertificateFactorySpi {
66
67
public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
68
public static final String END_CERT = "-----END CERTIFICATE-----";
69
70
private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX
71
72
private static final Cache<Object, X509CertImpl> certCache
73
= Cache.newSoftMemoryCache(750);
74
private static final Cache<Object, X509CRLImpl> crlCache
75
= Cache.newSoftMemoryCache(750);
76
77
/**
78
* Generates an X.509 certificate object and initializes it with
79
* the data read from the input stream <code>is</code>.
80
*
81
* @param is an input stream with the certificate data.
82
*
83
* @return an X.509 certificate object initialized with the data
84
* from the input stream.
85
*
86
* @exception CertificateException on parsing errors.
87
*/
88
@Override
89
public Certificate engineGenerateCertificate(InputStream is)
90
throws CertificateException
91
{
92
if (is == null) {
93
// clear the caches (for debugging)
94
certCache.clear();
95
X509CertificatePair.clearCache();
96
throw new CertificateException("Missing input stream");
97
}
98
try {
99
byte[] encoding = readOneBlock(is);
100
if (encoding != null) {
101
X509CertImpl cert = getFromCache(certCache, encoding);
102
if (cert != null) {
103
return cert;
104
}
105
cert = new X509CertImpl(encoding);
106
addToCache(certCache, cert.getEncodedInternal(), cert);
107
// record cert details if necessary
108
commitEvent(cert);
109
return cert;
110
} else {
111
throw new IOException("Empty input");
112
}
113
} catch (IOException ioe) {
114
throw new CertificateException("Could not parse certificate: " +
115
ioe.toString(), ioe);
116
}
117
}
118
119
/**
120
* Read from the stream until length bytes have been read or EOF has
121
* been reached. Return the number of bytes actually read.
122
*/
123
private static int readFully(InputStream in, ByteArrayOutputStream bout,
124
int length) throws IOException {
125
int read = 0;
126
byte[] buffer = new byte[2048];
127
while (length > 0) {
128
int n = in.read(buffer, 0, length<2048?length:2048);
129
if (n <= 0) {
130
break;
131
}
132
bout.write(buffer, 0, n);
133
read += n;
134
length -= n;
135
}
136
return read;
137
}
138
139
/**
140
* Return an interned X509CertImpl for the given certificate.
141
* If the given X509Certificate or X509CertImpl is already present
142
* in the cert cache, the cached object is returned. Otherwise,
143
* if it is a X509Certificate, it is first converted to a X509CertImpl.
144
* Then the X509CertImpl is added to the cache and returned.
145
*
146
* Note that all certificates created via generateCertificate(InputStream)
147
* are already interned and this method does not need to be called.
148
* It is useful for certificates that cannot be created via
149
* generateCertificate() and for converting other X509Certificate
150
* implementations to an X509CertImpl.
151
*
152
* @param c The source X509Certificate
153
* @return An X509CertImpl object that is either a cached certificate or a
154
* newly built X509CertImpl from the provided X509Certificate
155
* @throws CertificateException if failures occur while obtaining the DER
156
* encoding for certificate data.
157
*/
158
public static synchronized X509CertImpl intern(X509Certificate c)
159
throws CertificateException {
160
if (c == null) {
161
return null;
162
}
163
boolean isImpl = c instanceof X509CertImpl;
164
byte[] encoding;
165
if (isImpl) {
166
encoding = ((X509CertImpl)c).getEncodedInternal();
167
} else {
168
encoding = c.getEncoded();
169
}
170
X509CertImpl newC = getFromCache(certCache, encoding);
171
if (newC != null) {
172
return newC;
173
}
174
if (isImpl) {
175
newC = (X509CertImpl)c;
176
} else {
177
newC = new X509CertImpl(encoding);
178
encoding = newC.getEncodedInternal();
179
}
180
addToCache(certCache, encoding, newC);
181
return newC;
182
}
183
184
/**
185
* Return an interned X509CRLImpl for the given certificate.
186
* For more information, see intern(X509Certificate).
187
*
188
* @param c The source X509CRL
189
* @return An X509CRLImpl object that is either a cached CRL or a
190
* newly built X509CRLImpl from the provided X509CRL
191
* @throws CRLException if failures occur while obtaining the DER
192
* encoding for CRL data.
193
*/
194
public static synchronized X509CRLImpl intern(X509CRL c)
195
throws CRLException {
196
if (c == null) {
197
return null;
198
}
199
boolean isImpl = c instanceof X509CRLImpl;
200
byte[] encoding;
201
if (isImpl) {
202
encoding = ((X509CRLImpl)c).getEncodedInternal();
203
} else {
204
encoding = c.getEncoded();
205
}
206
X509CRLImpl newC = getFromCache(crlCache, encoding);
207
if (newC != null) {
208
return newC;
209
}
210
if (isImpl) {
211
newC = (X509CRLImpl)c;
212
} else {
213
newC = new X509CRLImpl(encoding);
214
encoding = newC.getEncodedInternal();
215
}
216
addToCache(crlCache, encoding, newC);
217
return newC;
218
}
219
220
/**
221
* Get the X509CertImpl or X509CRLImpl from the cache.
222
*/
223
private static synchronized <K,V> V getFromCache(Cache<K,V> cache,
224
byte[] encoding) {
225
Object key = new Cache.EqualByteArray(encoding);
226
return cache.get(key);
227
}
228
229
/**
230
* Add the X509CertImpl or X509CRLImpl to the cache.
231
*/
232
private static synchronized <V> void addToCache(Cache<Object, V> cache,
233
byte[] encoding, V value) {
234
if (encoding.length > ENC_MAX_LENGTH) {
235
return;
236
}
237
Object key = new Cache.EqualByteArray(encoding);
238
cache.put(key, value);
239
}
240
241
/**
242
* Generates a <code>CertPath</code> object and initializes it with
243
* the data read from the <code>InputStream</code> inStream. The data
244
* is assumed to be in the default encoding.
245
*
246
* @param inStream an <code>InputStream</code> containing the data
247
* @return a <code>CertPath</code> initialized with the data from the
248
* <code>InputStream</code>
249
* @exception CertificateException if an exception occurs while decoding
250
* @since 1.4
251
*/
252
@Override
253
public CertPath engineGenerateCertPath(InputStream inStream)
254
throws CertificateException
255
{
256
if (inStream == null) {
257
throw new CertificateException("Missing input stream");
258
}
259
try {
260
byte[] encoding = readOneBlock(inStream);
261
if (encoding != null) {
262
return new X509CertPath(new ByteArrayInputStream(encoding));
263
} else {
264
throw new IOException("Empty input");
265
}
266
} catch (IOException ioe) {
267
throw new CertificateException(ioe.getMessage());
268
}
269
}
270
271
/**
272
* Generates a <code>CertPath</code> object and initializes it with
273
* the data read from the <code>InputStream</code> inStream. The data
274
* is assumed to be in the specified encoding.
275
*
276
* @param inStream an <code>InputStream</code> containing the data
277
* @param encoding the encoding used for the data
278
* @return a <code>CertPath</code> initialized with the data from the
279
* <code>InputStream</code>
280
* @exception CertificateException if an exception occurs while decoding or
281
* the encoding requested is not supported
282
* @since 1.4
283
*/
284
@Override
285
public CertPath engineGenerateCertPath(InputStream inStream,
286
String encoding) throws CertificateException
287
{
288
if (inStream == null) {
289
throw new CertificateException("Missing input stream");
290
}
291
try {
292
byte[] data = readOneBlock(inStream);
293
if (data != null) {
294
return new X509CertPath(new ByteArrayInputStream(data), encoding);
295
} else {
296
throw new IOException("Empty input");
297
}
298
} catch (IOException ioe) {
299
throw new CertificateException(ioe.getMessage());
300
}
301
}
302
303
/**
304
* Generates a <code>CertPath</code> object and initializes it with
305
* a <code>List</code> of <code>Certificate</code>s.
306
* <p>
307
* The certificates supplied must be of a type supported by the
308
* <code>CertificateFactory</code>. They will be copied out of the supplied
309
* <code>List</code> object.
310
*
311
* @param certificates a <code>List</code> of <code>Certificate</code>s
312
* @return a <code>CertPath</code> initialized with the supplied list of
313
* certificates
314
* @exception CertificateException if an exception occurs
315
* @since 1.4
316
*/
317
@Override
318
public CertPath
319
engineGenerateCertPath(List<? extends Certificate> certificates)
320
throws CertificateException
321
{
322
return(new X509CertPath(certificates));
323
}
324
325
/**
326
* Returns an iteration of the <code>CertPath</code> encodings supported
327
* by this certificate factory, with the default encoding first.
328
* <p>
329
* Attempts to modify the returned <code>Iterator</code> via its
330
* <code>remove</code> method result in an
331
* <code>UnsupportedOperationException</code>.
332
*
333
* @return an <code>Iterator</code> over the names of the supported
334
* <code>CertPath</code> encodings (as <code>String</code>s)
335
* @since 1.4
336
*/
337
@Override
338
public Iterator<String> engineGetCertPathEncodings() {
339
return(X509CertPath.getEncodingsStatic());
340
}
341
342
/**
343
* Returns a (possibly empty) collection view of X.509 certificates read
344
* from the given input stream <code>is</code>.
345
*
346
* @param is the input stream with the certificates.
347
*
348
* @return a (possibly empty) collection view of X.509 certificate objects
349
* initialized with the data from the input stream.
350
*
351
* @exception CertificateException on parsing errors.
352
*/
353
@Override
354
public Collection<? extends java.security.cert.Certificate>
355
engineGenerateCertificates(InputStream is)
356
throws CertificateException {
357
if (is == null) {
358
throw new CertificateException("Missing input stream");
359
}
360
try {
361
return parseX509orPKCS7Cert(is);
362
} catch (IOException ioe) {
363
throw new CertificateException(ioe);
364
}
365
}
366
367
/**
368
* Generates an X.509 certificate revocation list (CRL) object and
369
* initializes it with the data read from the given input stream
370
* <code>is</code>.
371
*
372
* @param is an input stream with the CRL data.
373
*
374
* @return an X.509 CRL object initialized with the data
375
* from the input stream.
376
*
377
* @exception CRLException on parsing errors.
378
*/
379
@Override
380
public CRL engineGenerateCRL(InputStream is)
381
throws CRLException
382
{
383
if (is == null) {
384
// clear the cache (for debugging)
385
crlCache.clear();
386
throw new CRLException("Missing input stream");
387
}
388
try {
389
byte[] encoding = readOneBlock(is);
390
if (encoding != null) {
391
X509CRLImpl crl = getFromCache(crlCache, encoding);
392
if (crl != null) {
393
return crl;
394
}
395
crl = new X509CRLImpl(encoding);
396
addToCache(crlCache, crl.getEncodedInternal(), crl);
397
return crl;
398
} else {
399
throw new IOException("Empty input");
400
}
401
} catch (IOException ioe) {
402
throw new CRLException(ioe.getMessage());
403
}
404
}
405
406
/**
407
* Returns a (possibly empty) collection view of X.509 CRLs read
408
* from the given input stream <code>is</code>.
409
*
410
* @param is the input stream with the CRLs.
411
*
412
* @return a (possibly empty) collection view of X.509 CRL objects
413
* initialized with the data from the input stream.
414
*
415
* @exception CRLException on parsing errors.
416
*/
417
@Override
418
public Collection<? extends java.security.cert.CRL> engineGenerateCRLs(
419
InputStream is) throws CRLException
420
{
421
if (is == null) {
422
throw new CRLException("Missing input stream");
423
}
424
try {
425
return parseX509orPKCS7CRL(is);
426
} catch (IOException ioe) {
427
throw new CRLException(ioe.getMessage());
428
}
429
}
430
431
/*
432
* Parses the data in the given input stream as a sequence of DER
433
* encoded X.509 certificates (in binary or base 64 encoded format) OR
434
* as a single PKCS#7 encoded blob (in binary or base64 encoded format).
435
*/
436
private Collection<? extends java.security.cert.Certificate>
437
parseX509orPKCS7Cert(InputStream is)
438
throws CertificateException, IOException
439
{
440
int peekByte;
441
byte[] data;
442
PushbackInputStream pbis = new PushbackInputStream(is);
443
Collection<X509CertImpl> coll = new ArrayList<>();
444
445
// Test the InputStream for end-of-stream. If the stream's
446
// initial state is already at end-of-stream then return
447
// an empty collection. Otherwise, push the byte back into the
448
// stream and let readOneBlock look for the first certificate.
449
peekByte = pbis.read();
450
if (peekByte == -1) {
451
return new ArrayList<>(0);
452
} else {
453
pbis.unread(peekByte);
454
data = readOneBlock(pbis);
455
}
456
457
// If we end up with a null value after reading the first block
458
// then we know the end-of-stream has been reached and no certificate
459
// data has been found.
460
if (data == null) {
461
throw new CertificateException("No certificate data found");
462
}
463
464
try {
465
PKCS7 pkcs7 = new PKCS7(data);
466
X509Certificate[] certs = pkcs7.getCertificates();
467
// certs are optional in PKCS #7
468
if (certs != null) {
469
return Arrays.asList(certs);
470
} else {
471
// no certificates provided
472
return new ArrayList<>(0);
473
}
474
} catch (ParsingException e) {
475
while (data != null) {
476
coll.add(new X509CertImpl(data));
477
data = readOneBlock(pbis);
478
}
479
}
480
return coll;
481
}
482
483
/*
484
* Parses the data in the given input stream as a sequence of DER encoded
485
* X.509 CRLs (in binary or base 64 encoded format) OR as a single PKCS#7
486
* encoded blob (in binary or base 64 encoded format).
487
*/
488
private Collection<? extends java.security.cert.CRL>
489
parseX509orPKCS7CRL(InputStream is)
490
throws CRLException, IOException
491
{
492
int peekByte;
493
byte[] data;
494
PushbackInputStream pbis = new PushbackInputStream(is);
495
Collection<X509CRLImpl> coll = new ArrayList<>();
496
497
// Test the InputStream for end-of-stream. If the stream's
498
// initial state is already at end-of-stream then return
499
// an empty collection. Otherwise, push the byte back into the
500
// stream and let readOneBlock look for the first CRL.
501
peekByte = pbis.read();
502
if (peekByte == -1) {
503
return new ArrayList<>(0);
504
} else {
505
pbis.unread(peekByte);
506
data = readOneBlock(pbis);
507
}
508
509
// If we end up with a null value after reading the first block
510
// then we know the end-of-stream has been reached and no CRL
511
// data has been found.
512
if (data == null) {
513
throw new CRLException("No CRL data found");
514
}
515
516
try {
517
PKCS7 pkcs7 = new PKCS7(data);
518
X509CRL[] crls = pkcs7.getCRLs();
519
// CRLs are optional in PKCS #7
520
if (crls != null) {
521
return Arrays.asList(crls);
522
} else {
523
// no crls provided
524
return new ArrayList<>(0);
525
}
526
} catch (ParsingException e) {
527
while (data != null) {
528
coll.add(new X509CRLImpl(data));
529
data = readOneBlock(pbis);
530
}
531
}
532
return coll;
533
}
534
535
/**
536
* Returns an ASN.1 SEQUENCE from a stream, which might be a BER-encoded
537
* binary block or a PEM-style BASE64-encoded ASCII data. In the latter
538
* case, it's de-BASE64'ed before return.
539
*
540
* After the reading, the input stream pointer is after the BER block, or
541
* after the newline character after the -----END SOMETHING----- line.
542
*
543
* @param is the InputStream
544
* @return byte block or null if end of stream
545
* @throws IOException If any parsing error
546
*/
547
private static byte[] readOneBlock(InputStream is) throws IOException {
548
549
// The first character of a BLOCK.
550
int c = is.read();
551
if (c == -1) {
552
return null;
553
}
554
if (c == DerValue.tag_Sequence) {
555
ByteArrayOutputStream bout = new ByteArrayOutputStream(2048);
556
bout.write(c);
557
readBERInternal(is, bout, c);
558
return bout.toByteArray();
559
} else {
560
// Read BASE64 encoded data, might skip info at the beginning
561
ByteArrayOutputStream data = new ByteArrayOutputStream();
562
563
// Step 1: Read until header is found
564
int hyphen = (c=='-') ? 1: 0; // count of consequent hyphens
565
int last = (c=='-') ? -1: c; // the char before hyphen
566
while (true) {
567
int next = is.read();
568
if (next == -1) {
569
// We accept useless data after the last block,
570
// say, empty lines.
571
return null;
572
}
573
if (next == '-') {
574
hyphen++;
575
} else {
576
hyphen = 0;
577
last = next;
578
}
579
if (hyphen == 5 && (last == -1 || last == '\r' || last == '\n')) {
580
break;
581
}
582
}
583
584
// Step 2: Read the rest of header, determine the line end
585
int end;
586
StringBuilder header = new StringBuilder("-----");
587
while (true) {
588
int next = is.read();
589
if (next == -1) {
590
throw new IOException("Incomplete data");
591
}
592
if (next == '\n') {
593
end = '\n';
594
break;
595
}
596
if (next == '\r') {
597
next = is.read();
598
if (next == -1) {
599
throw new IOException("Incomplete data");
600
}
601
if (next == '\n') {
602
end = '\n';
603
} else {
604
end = '\r';
605
// Skip all white space chars
606
if (next != 9 && next != 10 && next != 13 && next != 32) {
607
data.write(next);
608
}
609
}
610
break;
611
}
612
header.append((char)next);
613
}
614
615
// Step 3: Read the data
616
while (true) {
617
int next = is.read();
618
if (next == -1) {
619
throw new IOException("Incomplete data");
620
}
621
if (next != '-') {
622
// Skip all white space chars
623
if (next != 9 && next != 10 && next != 13 && next != 32) {
624
data.write(next);
625
}
626
} else {
627
break;
628
}
629
}
630
631
// Step 4: Consume the footer
632
StringBuilder footer = new StringBuilder("-");
633
while (true) {
634
int next = is.read();
635
// Add next == '\n' for maximum safety, in case endline
636
// is not consistent.
637
if (next == -1 || next == end || next == '\n') {
638
break;
639
}
640
if (next != '\r') footer.append((char)next);
641
}
642
643
checkHeaderFooter(header.toString().stripTrailing(),
644
footer.toString().stripTrailing());
645
646
try {
647
return Base64.getDecoder().decode(data.toByteArray());
648
} catch (IllegalArgumentException e) {
649
throw new IOException(e);
650
}
651
}
652
}
653
654
private static void checkHeaderFooter(String header,
655
String footer) throws IOException {
656
if (header.length() < 16 || !header.startsWith("-----BEGIN ") ||
657
!header.endsWith("-----")) {
658
throw new IOException("Illegal header: " + header);
659
}
660
if (footer.length() < 14 || !footer.startsWith("-----END ") ||
661
!footer.endsWith("-----")) {
662
throw new IOException("Illegal footer: " + footer);
663
}
664
String headerType = header.substring(11, header.length()-5);
665
String footerType = footer.substring(9, footer.length()-5);
666
if (!headerType.equals(footerType)) {
667
throw new IOException("Header and footer do not match: " +
668
header + " " + footer);
669
}
670
}
671
672
/**
673
* Read one BER data block. This method is aware of indefinite-length BER
674
* encoding and will read all of the sub-sections in a recursive way
675
*
676
* @param is Read from this InputStream
677
* @param bout Write into this OutputStream
678
* @param tag Tag already read (-1 mean not read)
679
* @return The current tag, used to check EOC in indefinite-length BER
680
* @throws IOException Any parsing error
681
*/
682
private static int readBERInternal(InputStream is,
683
ByteArrayOutputStream bout, int tag) throws IOException {
684
685
if (tag == -1) { // Not read before the call, read now
686
tag = is.read();
687
if (tag == -1) {
688
throw new IOException("BER/DER tag info absent");
689
}
690
if ((tag & 0x1f) == 0x1f) {
691
throw new IOException("Multi octets tag not supported");
692
}
693
bout.write(tag);
694
}
695
696
int n = is.read();
697
if (n == -1) {
698
throw new IOException("BER/DER length info absent");
699
}
700
bout.write(n);
701
702
int length;
703
704
if (n == 0x80) { // Indefinite-length encoding
705
if ((tag & 0x20) != 0x20) {
706
throw new IOException(
707
"Non constructed encoding must have definite length");
708
}
709
while (true) {
710
int subTag = readBERInternal(is, bout, -1);
711
if (subTag == 0) { // EOC, end of indefinite-length section
712
break;
713
}
714
}
715
} else {
716
if (n < 0x80) {
717
length = n;
718
} else if (n == 0x81) {
719
length = is.read();
720
if (length == -1) {
721
throw new IOException("Incomplete BER/DER length info");
722
}
723
bout.write(length);
724
} else if (n == 0x82) {
725
int highByte = is.read();
726
int lowByte = is.read();
727
if (lowByte == -1) {
728
throw new IOException("Incomplete BER/DER length info");
729
}
730
bout.write(highByte);
731
bout.write(lowByte);
732
length = (highByte << 8) | lowByte;
733
} else if (n == 0x83) {
734
int highByte = is.read();
735
int midByte = is.read();
736
int lowByte = is.read();
737
if (lowByte == -1) {
738
throw new IOException("Incomplete BER/DER length info");
739
}
740
bout.write(highByte);
741
bout.write(midByte);
742
bout.write(lowByte);
743
length = (highByte << 16) | (midByte << 8) | lowByte;
744
} else if (n == 0x84) {
745
int highByte = is.read();
746
int nextByte = is.read();
747
int midByte = is.read();
748
int lowByte = is.read();
749
if (lowByte == -1) {
750
throw new IOException("Incomplete BER/DER length info");
751
}
752
if (highByte > 127) {
753
throw new IOException("Invalid BER/DER data (a little huge?)");
754
}
755
bout.write(highByte);
756
bout.write(nextByte);
757
bout.write(midByte);
758
bout.write(lowByte);
759
length = (highByte << 24 ) | (nextByte << 16) |
760
(midByte << 8) | lowByte;
761
} else { // ignore longer length forms
762
throw new IOException("Invalid BER/DER data (too huge?)");
763
}
764
if (readFully(is, bout, length) != length) {
765
throw new IOException("Incomplete BER/DER data");
766
}
767
}
768
return tag;
769
}
770
771
private void commitEvent(X509CertImpl info) {
772
X509CertificateEvent xce = new X509CertificateEvent();
773
if (xce.shouldCommit() || EventHelper.isLoggingSecurity()) {
774
PublicKey pKey = info.getPublicKey();
775
String algId = info.getSigAlgName();
776
String serNum = info.getSerialNumber().toString(16);
777
String subject = info.getSubjectDN().getName();
778
String issuer = info.getIssuerDN().getName();
779
String keyType = pKey.getAlgorithm();
780
int length = KeyUtil.getKeySize(pKey);
781
int hashCode = info.hashCode();
782
long beginDate = info.getNotBefore().getTime();
783
long endDate = info.getNotAfter().getTime();
784
if (xce.shouldCommit()) {
785
xce.algorithm = algId;
786
xce.serialNumber = serNum;
787
xce.subject = subject;
788
xce.issuer = issuer;
789
xce.keyType = keyType;
790
xce.keyLength = length;
791
xce.certificateId = hashCode;
792
xce.validFrom = beginDate;
793
xce.validUntil = endDate;
794
xce.commit();
795
}
796
if (EventHelper.isLoggingSecurity()) {
797
EventHelper.logX509CertificateEvent(algId,
798
serNum,
799
subject,
800
issuer,
801
keyType,
802
length,
803
hashCode,
804
beginDate,
805
endDate);
806
}
807
}
808
}
809
}
810
811