summaryrefslogtreecommitdiffstats
path: root/crypto/j2me/org/bouncycastle/tsp/TSPUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/j2me/org/bouncycastle/tsp/TSPUtil.java')
-rw-r--r--crypto/j2me/org/bouncycastle/tsp/TSPUtil.java233
1 files changed, 233 insertions, 0 deletions
diff --git a/crypto/j2me/org/bouncycastle/tsp/TSPUtil.java b/crypto/j2me/org/bouncycastle/tsp/TSPUtil.java
new file mode 100644
index 000000000..daa51cdbb
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/tsp/TSPUtil.java
@@ -0,0 +1,233 @@
+package org.bouncycastle.tsp;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.cms.Attribute;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.ExtensionsGenerator;
+import org.bouncycastle.asn1.x509.KeyPurposeId;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.Arrays;
+
+public class TSPUtil
+{
+ private static Set EMPTY_SET = Collections.unmodifiableSet(new HashSet());
+ private static List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
+
+ private static final Map digestLengths = new HashMap();
+ private static final Map digestNames = new HashMap();
+
+ static
+ {
+ digestLengths.put(PKCSObjectIdentifiers.md5.getId(), new Integer(16));
+ digestLengths.put(OIWObjectIdentifiers.idSHA1.getId(), new Integer(20));
+ digestLengths.put(NISTObjectIdentifiers.id_sha224.getId(), new Integer(28));
+ digestLengths.put(NISTObjectIdentifiers.id_sha256.getId(), new Integer(32));
+ digestLengths.put(NISTObjectIdentifiers.id_sha384.getId(), new Integer(48));
+ digestLengths.put(NISTObjectIdentifiers.id_sha512.getId(), new Integer(64));
+ digestLengths.put(TeleTrusTObjectIdentifiers.ripemd128.getId(), new Integer(16));
+ digestLengths.put(TeleTrusTObjectIdentifiers.ripemd160.getId(), new Integer(20));
+ digestLengths.put(TeleTrusTObjectIdentifiers.ripemd256.getId(), new Integer(32));
+ digestLengths.put(CryptoProObjectIdentifiers.gostR3411.getId(), new Integer(32));
+
+ digestNames.put(PKCSObjectIdentifiers.md5.getId(), "MD5");
+ digestNames.put(OIWObjectIdentifiers.idSHA1.getId(), "SHA1");
+ digestNames.put(NISTObjectIdentifiers.id_sha224.getId(), "SHA224");
+ digestNames.put(NISTObjectIdentifiers.id_sha256.getId(), "SHA256");
+ digestNames.put(NISTObjectIdentifiers.id_sha384.getId(), "SHA384");
+ digestNames.put(NISTObjectIdentifiers.id_sha512.getId(), "SHA512");
+ digestNames.put(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId(), "SHA1");
+ digestNames.put(PKCSObjectIdentifiers.sha224WithRSAEncryption.getId(), "SHA224");
+ digestNames.put(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), "SHA256");
+ digestNames.put(PKCSObjectIdentifiers.sha384WithRSAEncryption.getId(), "SHA384");
+ digestNames.put(PKCSObjectIdentifiers.sha512WithRSAEncryption.getId(), "SHA512");
+ digestNames.put(TeleTrusTObjectIdentifiers.ripemd128.getId(), "RIPEMD128");
+ digestNames.put(TeleTrusTObjectIdentifiers.ripemd160.getId(), "RIPEMD160");
+ digestNames.put(TeleTrusTObjectIdentifiers.ripemd256.getId(), "RIPEMD256");
+ digestNames.put(CryptoProObjectIdentifiers.gostR3411.getId(), "GOST3411");
+ }
+
+ /**
+ * Fetches the signature time-stamp attributes from a SignerInformation object.
+ * Checks that the MessageImprint for each time-stamp matches the signature field.
+ * (see RFC 3161 Appendix A).
+ *
+ * @param signerInfo a SignerInformation to search for time-stamps
+ * @param digCalcProvider provider for digest calculators
+ * @return a collection of TimeStampToken objects
+ * @throws TSPValidationException
+ */
+ public static Collection getSignatureTimestamps(SignerInformation signerInfo, DigestCalculatorProvider digCalcProvider)
+ throws TSPValidationException
+ {
+ List timestamps = new ArrayList();
+
+ AttributeTable unsignedAttrs = signerInfo.getUnsignedAttributes();
+ if (unsignedAttrs != null)
+ {
+ ASN1EncodableVector allTSAttrs = unsignedAttrs.getAll(
+ PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
+ for (int i = 0; i < allTSAttrs.size(); ++i)
+ {
+ Attribute tsAttr = (Attribute)allTSAttrs.get(i);
+ ASN1Set tsAttrValues = tsAttr.getAttrValues();
+ for (int j = 0; j < tsAttrValues.size(); ++j)
+ {
+ try
+ {
+ ContentInfo contentInfo = ContentInfo.getInstance(tsAttrValues.getObjectAt(j));
+ TimeStampToken timeStampToken = new TimeStampToken(contentInfo);
+ TimeStampTokenInfo tstInfo = timeStampToken.getTimeStampInfo();
+
+ DigestCalculator digCalc = digCalcProvider.get(tstInfo.getHashAlgorithm());
+
+ OutputStream dOut = digCalc.getOutputStream();
+
+ dOut.write(signerInfo.getSignature());
+ dOut.close();
+
+ byte[] expectedDigest = digCalc.getDigest();
+
+ if (!Arrays.constantTimeAreEqual(expectedDigest, tstInfo.getMessageImprintDigest()))
+ {
+ throw new TSPValidationException("Incorrect digest in message imprint");
+ }
+
+ timestamps.add(timeStampToken);
+ }
+ catch (OperatorCreationException e)
+ {
+ throw new TSPValidationException("Unknown hash algorithm specified in timestamp");
+ }
+ catch (Exception e)
+ {
+ throw new TSPValidationException("Timestamp could not be parsed");
+ }
+ }
+ }
+ }
+
+ return timestamps;
+ }
+
+ /**
+ * Validate the passed in certificate as being of the correct type to be used
+ * for time stamping. To be valid it must have an ExtendedKeyUsage extension
+ * which has a key purpose identifier of id-kp-timeStamping.
+ *
+ * @param cert the certificate of interest.
+ * @throws TSPValidationException if the certicate fails on one of the check points.
+ */
+ public static void validateCertificate(
+ X509CertificateHolder cert)
+ throws TSPValidationException
+ {
+ if (cert.toASN1Structure().getVersionNumber() != 3)
+ {
+ throw new IllegalArgumentException("Certificate must have an ExtendedKeyUsage extension.");
+ }
+
+ Extension ext = cert.getExtension(Extension.extendedKeyUsage);
+ if (ext == null)
+ {
+ throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension.");
+ }
+
+ if (!ext.isCritical())
+ {
+ throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical.");
+ }
+
+ ExtendedKeyUsage extKey = ExtendedKeyUsage.getInstance(ext.getParsedValue());
+
+ if (!extKey.hasKeyPurposeId(KeyPurposeId.id_kp_timeStamping) || extKey.size() != 1)
+ {
+ throw new TSPValidationException("ExtendedKeyUsage not solely time stamping.");
+ }
+ }
+
+ /*
+ * Return the digest algorithm using one of the standard JCA string
+ * representations rather than the algorithm identifier (if possible).
+ */
+ static String getDigestAlgName(
+ String digestAlgOID)
+ {
+ String digestName = (String)digestNames.get(digestAlgOID);
+
+ if (digestName != null)
+ {
+ return digestName;
+ }
+
+ return digestAlgOID;
+ }
+
+ static int getDigestLength(
+ String digestAlgOID)
+ throws TSPException
+ {
+ Integer length = (Integer)digestLengths.get(digestAlgOID);
+
+ if (length != null)
+ {
+ return length.intValue();
+ }
+
+ throw new TSPException("digest algorithm cannot be found.");
+ }
+
+ static List getExtensionOIDs(Extensions extensions)
+ {
+ if (extensions == null)
+ {
+ return EMPTY_LIST;
+ }
+
+ return Collections.unmodifiableList(java.util.Arrays.asList(extensions.getExtensionOIDs()));
+ }
+
+ static void addExtension(ExtensionsGenerator extGenerator, ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)
+ throws TSPIOException
+ {
+ try
+ {
+ extGenerator.addExtension(oid, isCritical, value);
+ }
+ catch (IOException e)
+ {
+ throw new TSPIOException("cannot encode extension: " + e.getMessage(), e);
+ }
+ }
+}