diff options
Diffstat (limited to 'moaSig/moa-sig-lib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/CMSSignatureVerificationInvoker.java')
-rw-r--r-- | moaSig/moa-sig-lib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/CMSSignatureVerificationInvoker.java | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/moaSig/moa-sig-lib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/CMSSignatureVerificationInvoker.java b/moaSig/moa-sig-lib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/CMSSignatureVerificationInvoker.java new file mode 100644 index 0000000..aca6f58 --- /dev/null +++ b/moaSig/moa-sig-lib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/CMSSignatureVerificationInvoker.java @@ -0,0 +1,371 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.server.invoke; + +import iaik.server.modules.IAIKException; +import iaik.server.modules.IAIKRuntimeException; +import iaik.server.modules.cmsverify.CMSSignatureVerificationModule; +import iaik.server.modules.cmsverify.CMSSignatureVerificationModuleFactory; +import iaik.server.modules.cmsverify.CMSSignatureVerificationProfile; +import iaik.server.modules.cmsverify.CMSSignatureVerificationResult; +import iaik.x509.X509Certificate; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import at.gv.egovernment.moa.logging.LoggingContext; +import at.gv.egovernment.moa.logging.LoggingContextManager; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContent; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContentExcplicit; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContentReference; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSDataObject; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.server.config.TrustProfile; +import at.gv.egovernment.moa.spss.server.logging.IaikLog; +import at.gv.egovernment.moa.spss.server.logging.TransactionId; +import at.gv.egovernment.moa.spss.server.transaction.TransactionContext; +import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager; +import at.gv.egovernment.moa.spss.util.CertificateUtils; +import at.gv.egovernment.moa.spss.util.QCSSCDResult; + +/** + * A class providing an interface to the + * <code>CMSSignatureVerificationModule</code>. + * + * This class performs the invocation of the + * <code>iaik.server.modules.cmsverify.CMSSignatureVerificationModule</code> + * from a <code>VerifyCMSSignatureRequest</code>. The result of the invocation + * is integrated into a <code>VerifyCMSSignatureResponse</code> returned. + * + * @author Patrick Peck + * @version $Id$ + */ +public class CMSSignatureVerificationInvoker { + + /** The single instance of this class. */ + private static CMSSignatureVerificationInvoker instance = null; + + /** + * Return the only instance of this class. + * + * @return The only instance of this class. + */ + public static synchronized CMSSignatureVerificationInvoker getInstance() { + if (instance == null) { + instance = new CMSSignatureVerificationInvoker(); + } + return instance; + } + + /** + * Create a new <code>CMSSignatureVerificationInvoker</code>. + * + * Protected to disallow multiple instances. + */ + protected CMSSignatureVerificationInvoker() { + } + + /** + * Verify a CMS signature. + * + * @param request The <code>VerifyCMSSignatureRequest</code> containing the + * CMS signature, as well as additional data needed for verification. + * @return Element A <code>VerifyCMSSignatureResponse</code> containing the + * answer to the <code>VerifyCMSSignatureRequest</code>. + * @throws MOAException An error occurred while processing the request. + */ + public VerifyCMSSignatureResponse verifyCMSSignature(VerifyCMSSignatureRequest request) + throws MOAException { + + CMSSignatureVerificationProfileFactory profileFactory = + new CMSSignatureVerificationProfileFactory(request); + VerifyCMSSignatureResponseBuilder responseBuilder = + new VerifyCMSSignatureResponseBuilder(); + TransactionContext context = + TransactionContextManager.getInstance().getTransactionContext(); + LoggingContext loggingCtx = + LoggingContextManager.getInstance().getLoggingContext(); + InputStream signature; + InputStream signedContent = null; + CMSSignatureVerificationProfile profile; + Date signingTime; + List results; + CMSSignatureVerificationResult result; + int[] signatories; + InputStream input; + byte[] buf = new byte[256]; + + // get the signature + signature = request.getCMSSignature(); + + // get the actual trustprofile + TrustProfile trustProfile = context.getConfiguration().getTrustProfile(request.getTrustProfileId()); + + try { + // get the signed content + signedContent = getSignedContent(request); + + // build the profile + profile = profileFactory.createProfile(); + + // get the signing time + signingTime = request.getDateTime(); + + // verify the signature + CMSSignatureVerificationModule module = + CMSSignatureVerificationModuleFactory.getInstance(); + + module.setLog(new IaikLog(loggingCtx.getNodeID())); + + module.init( + signature, + signedContent, + profile, + new TransactionId(context.getTransactionID())); + input = module.getInputStream(); + + while (input.read(buf) > 0); + results = module.verifySignature(signingTime); + + + } catch (IAIKException e) { + MOAException moaException = IaikExceptionMapper.getInstance().map(e); + throw moaException; + } catch (IAIKRuntimeException e) { + MOAException moaException = IaikExceptionMapper.getInstance().map(e); + throw moaException; + } catch (IOException e) { + throw new MOAApplicationException("2244", null, e); + } catch (MOAException e) + { + throw e; + } + finally + { + try + { + if (signedContent != null) signedContent.close(); + } + catch (Throwable t) + { + // Intentionally do nothing here + } + } + + QCSSCDResult qcsscdresult = new QCSSCDResult(); + + // build the response: for each signatory add the result to the response + signatories = request.getSignatories(); + if (signatories == VerifyCMSSignatureRequest.ALL_SIGNATORIES) { + Iterator resultIter; + + for (resultIter = results.iterator(); resultIter.hasNext();) { + result = (CMSSignatureVerificationResult) resultIter.next(); + String issuerCountryCode = null; + // QC/SSCD check + List list = result.getCertificateValidationResult().getCertificateChain(); + if (list != null) { + X509Certificate[] chain = new X509Certificate[list.size()]; + + Iterator it = list.iterator(); + int i = 0; + while(it.hasNext()) { + chain[i] = (X509Certificate)it.next(); + i++; + } + + + qcsscdresult = CertificateUtils.checkQCSSCD(chain, trustProfile.isTSLEnabled()); + + // get signer certificate issuer country code + issuerCountryCode = CertificateUtils.getIssuerCountry((X509Certificate)list.get(0)); + + } + + responseBuilder.addResult(result, trustProfile, qcsscdresult.isQC(), qcsscdresult.isQCSourceTSL(), qcsscdresult.isSSCD(), qcsscdresult.isSSCDSourceTSL(), issuerCountryCode); + } + } else { + int i; + + for (i = 0; i < signatories.length; i++) { + int sigIndex = signatories[i] - 1; + + try { + result = + (CMSSignatureVerificationResult) results.get(signatories[i] - 1); + + String issuerCountryCode = null; + // QC/SSCD check + List list = result.getCertificateValidationResult().getCertificateChain(); + if (list != null) { + X509Certificate[] chain = new X509Certificate[list.size()]; + + Iterator it = list.iterator(); + int j = 0; + while(it.hasNext()) { + chain[j] = (X509Certificate)it.next(); + j++; + } + + + qcsscdresult = CertificateUtils.checkQCSSCD(chain, trustProfile.isTSLEnabled()); + + issuerCountryCode = CertificateUtils.getIssuerCountry((X509Certificate)list.get(0)); + } + + responseBuilder.addResult(result, trustProfile, qcsscdresult.isQC(), qcsscdresult.isQCSourceTSL(), qcsscdresult.isSSCD(), qcsscdresult.isSSCDSourceTSL(), issuerCountryCode); + } catch (IndexOutOfBoundsException e) { + throw new MOAApplicationException( + "2249", + new Object[] { new Integer(sigIndex)}); + } + } + } + + return responseBuilder.getResponse(); + } + + + /** + * Get the signed content contained either in the request itself or given as a + * reference to external data. + * + * @param request The <code>VerifyCMSSignatureRequest</code> containing the + * signed content (or the reference to the signed content). + * @return InputStream A stream providing the signed content data, or + * <code>null</code> if no signed content was provided with the request. + * @throws MOAApplicationException An error occurred building the stream. + */ + private InputStream getSignedContent(VerifyCMSSignatureRequest request) + throws MOAApplicationException { + + InputStream is = null; + CMSDataObject dataObj; + CMSContent content; + + // select the Content element + dataObj = request.getDataObject(); + if (dataObj == null) { + return null; + } + content = dataObj.getContent(); + + // build the content data + switch (content.getContentType()) { + case CMSContent.EXPLICIT_CONTENT : + is = ((CMSContentExcplicit) content).getBinaryContent(); + is = excludeByteRange(is, request); + return is; + case CMSContent.REFERENCE_CONTENT : + String reference = ((CMSContentReference) content).getReference(); + if (!"".equals(reference)) { + ExternalURIResolver resolver = new ExternalURIResolver(); + is = resolver.resolve(reference); + is = excludeByteRange(is, request); + return is; + } else { + return null; + } + default : + return null; + } + + + + } + + private InputStream excludeByteRange(InputStream contentIs, VerifyCMSSignatureRequest request) throws MOAApplicationException { + + int byteRead; + + ByteArrayOutputStream contentOs = new ByteArrayOutputStream(); + + CMSDataObject dataobject = request.getDataObject(); + BigDecimal from = dataobject.getExcludeByteRangeFrom(); + BigDecimal to = dataobject.getExcludeByteRangeTo(); + + if ( (from == null) || (to == null)) + return contentIs; + + BigDecimal counter = new BigDecimal("0"); + BigDecimal one = new BigDecimal("1"); + + try { + while ((byteRead=contentIs.read()) >= 0) { + + if (inRange(counter, dataobject)) { + // if byte is in byte range, set byte to 0x00 + contentOs.write(0); + } + else + contentOs.write(byteRead); + + counter = counter.add(one); + } + + InputStream is = new ByteArrayInputStream(contentOs.toByteArray()); + + return is; + + + } catch (IOException e) { + throw new MOAApplicationException("2301", null, e); + } + + } + + + private boolean inRange(BigDecimal counter, CMSDataObject dataobject) { + BigDecimal from = dataobject.getExcludeByteRangeFrom(); + BigDecimal to = dataobject.getExcludeByteRangeTo(); + + if ( (from == null) || (to == null)) + return false; + + int compare = counter.compareTo(from); + if (compare == -1) + return false; + else { + compare = counter.compareTo(to); + if (compare == 1) + return false; + else + return true; + } + + + + } + +} |