@@ -25,6 +25,7 @@ This file is part of the iText (R) project.
25
25
import com .itextpdf .commons .actions .contexts .IMetaInfo ;
26
26
import com .itextpdf .bouncycastleconnector .BouncyCastleFactoryCreator ;
27
27
import com .itextpdf .commons .bouncycastle .IBouncyCastleFactory ;
28
+ import com .itextpdf .commons .bouncycastle .asn1 .ocsp .IBasicOCSPResponse ;
28
29
import com .itextpdf .commons .bouncycastle .asn1 .tsp .ITSTInfo ;
29
30
import com .itextpdf .commons .bouncycastle .cert .ocsp .AbstractOCSPException ;
30
31
import com .itextpdf .commons .utils .DateTimeUtil ;
@@ -52,6 +53,7 @@ This file is part of the iText (R) project.
52
53
import java .io .ByteArrayInputStream ;
53
54
import java .io .IOException ;
54
55
import java .security .GeneralSecurityException ;
56
+ import java .security .cert .CRL ;
55
57
import java .security .cert .Certificate ;
56
58
import java .security .cert .X509CRL ;
57
59
import java .security .cert .X509Certificate ;
@@ -156,9 +158,10 @@ public ValidationReport validateSignatures(PdfDocument document) {
156
158
157
159
ValidationReport validateLatestSignature (PdfDocument document ) {
158
160
ValidationReport validationReport = new ValidationReport ();
159
- updateValidationOcspClient (validationReport , validationContext , document );
160
- updateValidationCrlClient (validationReport , validationContext , document );
161
161
PdfPKCS7 pkcs7 = mathematicallyVerifySignature (validationReport , document );
162
+ updateValidationClients (pkcs7 , validationReport , validationContext , document );
163
+ // We only retrieve not signed revocation data at the very beginning of signature processing.
164
+ retrieveNotSignedRevocationInfoFromSignatureContainer (pkcs7 , validationContext );
162
165
if (stopValidation (validationReport , validationContext )) {
163
166
return validationReport ;
164
167
}
@@ -167,66 +170,44 @@ ValidationReport validateLatestSignature(PdfDocument document) {
167
170
certificateRetriever .addKnownCertificates (certificatesFromDss );
168
171
169
172
if (pkcs7 .isTsp ()) {
170
- validateTimestampChain (validationReport , pkcs7 .getTimeStampTokenInfo (), pkcs7 .getCertificates (),
171
- pkcs7 .getSigningCertificate ());
172
- updateValidationOcspClient ( validationReport , validationContext , document );
173
- updateValidationCrlClient ( validationReport , validationContext , document );
173
+ validateTimestampChain (validationReport , pkcs7 .getCertificates (), pkcs7 .getSigningCertificate ());
174
+ if ( updateLastKnownPoE ( validationReport , pkcs7 .getTimeStampTokenInfo ())) {
175
+ updateValidationClients ( pkcs7 , validationReport , validationContext , document );
176
+ }
174
177
return validationReport ;
175
178
}
176
179
180
+ boolean isPoEUpdated = false ;
177
181
Date previousLastKnowPoE = lastKnownPoE ;
178
182
ValidationContext previousValidationContext = validationContext ;
179
183
if (pkcs7 .getTimeStampTokenInfo () != null ) {
180
- try {
181
- if (!pkcs7 .verifyTimestampImprint ()) {
182
- validationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , CANNOT_VERIFY_TIMESTAMP ,
183
- ReportItemStatus .INVALID ));
184
- }
185
- } catch (GeneralSecurityException e ) {
186
- validationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , CANNOT_VERIFY_TIMESTAMP , e ,
187
- ReportItemStatus .INVALID ));
188
- }
189
- if (stopValidation (validationReport , validationContext )) {
190
- return validationReport ;
191
- }
192
-
193
- PdfPKCS7 timestampSignatureContainer = pkcs7 .getTimestampSignatureContainer ();
194
- try {
195
- if (!timestampSignatureContainer .verifySignatureIntegrityAndAuthenticity ()) {
196
- validationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION ,
197
- CANNOT_VERIFY_TIMESTAMP , ReportItemStatus .INVALID ));
198
- }
199
- } catch (GeneralSecurityException e ) {
200
- validationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION ,
201
- CANNOT_VERIFY_TIMESTAMP , e , ReportItemStatus .INVALID ));
202
- }
203
- if (stopValidation (validationReport , validationContext )) {
204
- return validationReport ;
184
+ ValidationReport tsValidationReport = validateEmbeddedTimestamp (pkcs7 );
185
+ isPoEUpdated = updateLastKnownPoE (tsValidationReport , pkcs7 .getTimeStampTokenInfo ());
186
+ if (isPoEUpdated ) {
187
+ PdfPKCS7 timestampSignatureContainer = pkcs7 .getTimestampSignatureContainer ();
188
+ retrieveSignedRevocationInfoFromSignatureContainer (timestampSignatureContainer , validationContext );
189
+ updateValidationClients (pkcs7 , tsValidationReport , validationContext , document );
205
190
}
206
-
207
- Certificate [] timestampCertificates = timestampSignatureContainer .getCertificates ();
208
- validateTimestampChain (validationReport , pkcs7 .getTimeStampTokenInfo (), timestampCertificates ,
209
- timestampSignatureContainer .getSigningCertificate ());
210
- if (stopValidation (validationReport , validationContext )) {
191
+ validationReport .merge (tsValidationReport );
192
+ if (stopValidation (tsValidationReport , validationContext )) {
211
193
return validationReport ;
212
194
}
213
195
}
214
- updateValidationOcspClient (validationReport , validationContext , document );
215
- updateValidationCrlClient (validationReport , validationContext , document );
216
196
217
197
Certificate [] certificates = pkcs7 .getCertificates ();
218
198
certificateRetriever .addKnownCertificates (Arrays .asList (certificates ));
219
199
X509Certificate signingCertificate = pkcs7 .getSigningCertificate ();
220
200
221
201
ValidationReport signatureReport = new ValidationReport ();
222
202
certificateChainValidator .validate (signatureReport , validationContext , signingCertificate , lastKnownPoE );
223
- if (signatureReport .getValidationResult () != ValidationResult .VALID ) {
203
+ if (isPoEUpdated && signatureReport .getValidationResult () != ValidationResult .VALID ) {
224
204
// We can only use PoE retrieved from timestamp attribute in case main signature validation is successful.
225
- // That's why if the result is not valid, we set back lastKnownPoE value, validation context and DSS .
205
+ // That's why if the result is not valid, we set back lastKnownPoE value, validation context and rev data .
226
206
lastKnownPoE = previousLastKnowPoE ;
227
207
validationContext = previousValidationContext ;
228
- updateValidationOcspClient (validationReport , validationContext , document );
229
- updateValidationCrlClient (validationReport , validationContext , document );
208
+ PdfPKCS7 timestampSignatureContainer = pkcs7 .getTimestampSignatureContainer ();
209
+ retrieveSignedRevocationInfoFromSignatureContainer (timestampSignatureContainer , validationContext );
210
+ updateValidationClients (pkcs7 , validationReport , validationContext , document );
230
211
}
231
212
return validationReport .merge (signatureReport );
232
213
}
@@ -255,32 +236,100 @@ private PdfPKCS7 mathematicallyVerifySignature(ValidationReport validationReport
255
236
return pkcs7 ;
256
237
}
257
238
258
- private ValidationReport validateTimestampChain (ValidationReport validationReport , ITSTInfo timeStampTokenInfo ,
259
- Certificate [] knownCerts , X509Certificate signingCert ) {
260
- certificateRetriever .addKnownCertificates (Arrays .asList (knownCerts ));
261
-
239
+ private ValidationReport validateEmbeddedTimestamp (PdfPKCS7 pkcs7 ) {
262
240
ValidationReport tsValidationReport = new ValidationReport ();
241
+ try {
242
+ if (!pkcs7 .verifyTimestampImprint ()) {
243
+ tsValidationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , CANNOT_VERIFY_TIMESTAMP ,
244
+ ReportItemStatus .INVALID ));
245
+ }
246
+ } catch (GeneralSecurityException e ) {
247
+ tsValidationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , CANNOT_VERIFY_TIMESTAMP , e ,
248
+ ReportItemStatus .INVALID ));
249
+ }
250
+ if (stopValidation (tsValidationReport , validationContext )) {
251
+ return tsValidationReport ;
252
+ }
263
253
264
- certificateChainValidator .validate (tsValidationReport ,
254
+ PdfPKCS7 timestampSignatureContainer = pkcs7 .getTimestampSignatureContainer ();
255
+ retrieveSignedRevocationInfoFromSignatureContainer (timestampSignatureContainer , validationContext );
256
+ try {
257
+ if (!timestampSignatureContainer .verifySignatureIntegrityAndAuthenticity ()) {
258
+ tsValidationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION ,
259
+ CANNOT_VERIFY_TIMESTAMP , ReportItemStatus .INVALID ));
260
+ }
261
+ } catch (GeneralSecurityException e ) {
262
+ tsValidationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION ,
263
+ CANNOT_VERIFY_TIMESTAMP , e , ReportItemStatus .INVALID ));
264
+ }
265
+ if (stopValidation (tsValidationReport , validationContext )) {
266
+ return tsValidationReport ;
267
+ }
268
+
269
+ Certificate [] timestampCertificates = timestampSignatureContainer .getCertificates ();
270
+ validateTimestampChain (tsValidationReport , timestampCertificates ,
271
+ timestampSignatureContainer .getSigningCertificate ());
272
+ return tsValidationReport ;
273
+ }
274
+
275
+ private void validateTimestampChain (ValidationReport validationReport , Certificate [] knownCerts ,
276
+ X509Certificate signingCert ) {
277
+ certificateRetriever .addKnownCertificates (Arrays .asList (knownCerts ));
278
+
279
+ certificateChainValidator .validate (validationReport ,
265
280
validationContext .setCertificateSource (CertificateSource .TIMESTAMP ),
266
281
signingCert , lastKnownPoE );
267
- validationReport .merge (tsValidationReport );
268
- if (tsValidationReport .getValidationResult () == ValidationReport .ValidationResult .VALID ) {
282
+ }
283
+
284
+ private boolean updateLastKnownPoE (ValidationReport tsValidationReport , ITSTInfo timeStampTokenInfo ) {
285
+ if (tsValidationReport .getValidationResult () == ValidationResult .VALID ) {
269
286
try {
270
287
lastKnownPoE = timeStampTokenInfo .getGenTime ();
271
288
if (validationContext .getTimeBasedContext () == TimeBasedContext .PRESENT ) {
272
289
validationContext = validationContext .setTimeBasedContext (TimeBasedContext .HISTORICAL );
273
290
}
291
+ return true ;
274
292
} catch (Exception e ) {
275
- validationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , TIMESTAMP_EXTRACTION_FAILED , e ,
293
+ tsValidationReport .addReportItem (new ReportItem (TIMESTAMP_VERIFICATION , TIMESTAMP_EXTRACTION_FAILED , e ,
276
294
ReportItemStatus .INDETERMINATE ));
277
295
}
278
296
}
279
- return validationReport ;
297
+ return false ;
280
298
}
281
299
282
- private void updateValidationOcspClient (ValidationReport validationReport , ValidationContext context ,
283
- PdfDocument document ) {
300
+ private void updateValidationClients (PdfPKCS7 pkcs7 , ValidationReport validationReport ,
301
+ ValidationContext validationContext , PdfDocument document ) {
302
+ retrieveOcspResponsesFromDss (validationReport , validationContext , document );
303
+ retrieveCrlResponsesFromDss (validationReport , validationContext , document );
304
+ retrieveSignedRevocationInfoFromSignatureContainer (pkcs7 , validationContext );
305
+ }
306
+
307
+ private void retrieveSignedRevocationInfoFromSignatureContainer (PdfPKCS7 pkcs7 ,
308
+ ValidationContext validationContext ) {
309
+ if (pkcs7 .getCRLs () != null ) {
310
+ for (CRL crl : pkcs7 .getCRLs ()) {
311
+ validationCrlClient .addCrl ((X509CRL ) crl , lastKnownPoE , validationContext .getTimeBasedContext ());
312
+ }
313
+ }
314
+ if (pkcs7 .getOcsp () != null ) {
315
+ validationOcspClient .addResponse (BOUNCY_CASTLE_FACTORY .createBasicOCSPResp (pkcs7 .getOcsp ()), lastKnownPoE ,
316
+ validationContext .getTimeBasedContext ());
317
+ }
318
+ }
319
+
320
+ private void retrieveNotSignedRevocationInfoFromSignatureContainer (PdfPKCS7 pkcs7 ,
321
+ ValidationContext validationContext ) {
322
+ for (CRL crl : pkcs7 .getSignedDataCRLs ()) {
323
+ validationCrlClient .addCrl ((X509CRL ) crl , lastKnownPoE , validationContext .getTimeBasedContext ());
324
+ }
325
+ for (IBasicOCSPResponse oscp : pkcs7 .getSignedDataOcsps ()) {
326
+ validationOcspClient .addResponse (BOUNCY_CASTLE_FACTORY .createBasicOCSPResp (oscp ), lastKnownPoE ,
327
+ validationContext .getTimeBasedContext ());
328
+ }
329
+ }
330
+
331
+ private void retrieveOcspResponsesFromDss (ValidationReport validationReport , ValidationContext context ,
332
+ PdfDocument document ) {
284
333
PdfDictionary dss = document .getCatalog ().getPdfObject ().getAsDictionary (PdfName .DSS );
285
334
if (dss != null ) {
286
335
PdfArray ocsps = dss .getAsArray (PdfName .OCSPs );
@@ -300,8 +349,8 @@ private void updateValidationOcspClient(ValidationReport validationReport, Valid
300
349
}
301
350
}
302
351
303
- private void updateValidationCrlClient (ValidationReport validationReport , ValidationContext context ,
304
- PdfDocument document ) {
352
+ private void retrieveCrlResponsesFromDss (ValidationReport validationReport , ValidationContext context ,
353
+ PdfDocument document ) {
305
354
PdfDictionary dss = document .getCatalog ().getPdfObject ().getAsDictionary (PdfName .DSS );
306
355
if (dss != null ) {
307
356
PdfArray crls = dss .getAsArray (PdfName .CRLs );
@@ -346,4 +395,3 @@ private boolean stopValidation(ValidationReport result, ValidationContext valida
346
395
&& result .getValidationResult () == ValidationResult .INVALID ;
347
396
}
348
397
}
349
-
0 commit comments