summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ojluni/src/main/java/sun/security/pkcs/ContentInfo.java8
-rw-r--r--ojluni/src/main/java/sun/security/pkcs/PKCS7.java237
-rw-r--r--ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java19
3 files changed, 231 insertions, 33 deletions
diff --git a/ojluni/src/main/java/sun/security/pkcs/ContentInfo.java b/ojluni/src/main/java/sun/security/pkcs/ContentInfo.java
index 2eb1b03f36..bc78d0f1c0 100644
--- a/ojluni/src/main/java/sun/security/pkcs/ContentInfo.java
+++ b/ojluni/src/main/java/sun/security/pkcs/ContentInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,9 +163,9 @@ public class ContentInfo {
}
public byte[] getData() throws IOException {
- if (contentType.equals(DATA_OID) ||
- contentType.equals(OLD_DATA_OID) ||
- contentType.equals(TIMESTAMP_TOKEN_INFO_OID)) {
+ if (contentType.equals((Object)DATA_OID) ||
+ contentType.equals((Object)OLD_DATA_OID) ||
+ contentType.equals((Object)TIMESTAMP_TOKEN_INFO_OID)) {
if (content == null)
return null;
else
diff --git a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
index 5fb23ea945..c9973aa24f 100644
--- a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
+++ b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@ package sun.security.pkcs;
import java.io.*;
import java.math.BigInteger;
+import java.net.URI;
import java.util.*;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
@@ -40,11 +41,12 @@ import java.security.cert.CRLException;
import java.security.cert.CertificateFactory;
import java.security.*;
+import sun.security.timestamp.*;
+
import javax.security.auth.x500.X500Principal;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
-import sun.security.x509.CertificateIssuerName;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509CRLImpl;
@@ -75,6 +77,36 @@ public class PKCS7 {
private Principal[] certIssuerNames;
+ /* BEGIN ANDROID-REMOVED: unused in Android
+ /*
+ * Random number generator for creating nonce values
+ * (Lazy initialization)
+ *
+ private static class SecureRandomHolder {
+ static final SecureRandom RANDOM;
+ static {
+ SecureRandom tmp = null;
+ try {
+ tmp = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e) {
+ // should not happen
+ }
+ RANDOM = tmp;
+ }
+ }
+
+ /*
+ * Object identifier for the timestamping key purpose.
+ *
+ private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
+
+ /*
+ * Object identifier for extendedKeyUsage extension
+ *
+ private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
+
+ END ANDROID-REMOVED */
+
/**
* Unmarshals a PKCS7 block from its encoded form, parsing the
* encoded bytes from the InputStream.
@@ -161,12 +193,13 @@ public class PKCS7 {
contentType = contentInfo.contentType;
DerValue content = contentInfo.getContent();
- if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) {
+ if (contentType.equals((Object)ContentInfo.SIGNED_DATA_OID)) {
parseSignedData(content);
- } else if (contentType.equals(ContentInfo.OLD_SIGNED_DATA_OID)) {
+ } else if (contentType.equals((Object)ContentInfo.OLD_SIGNED_DATA_OID)) {
// This is for backwards compatibility with JDK 1.1.x
parseOldSignedData(content);
- } else if (contentType.equals(ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){
+ } else if (contentType.equals((Object)
+ ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){
parseNetscapeCertChain(content);
} else {
throw new ParsingException("content type " + contentType +
@@ -498,9 +531,7 @@ public class PKCS7 {
byte[] encoded = certificates[i].getEncoded();
implCerts[i] = new X509CertImpl(encoded);
} catch (CertificateException ce) {
- IOException ie = new IOException(ce.getMessage());
- ie.initCause(ce);
- throw ie;
+ throw new IOException(ce);
}
}
}
@@ -522,9 +553,7 @@ public class PKCS7 {
byte[] encoded = crl.getEncoded();
implCRLs.add(new X509CRLImpl(encoded));
} catch (CRLException ce) {
- IOException ie = new IOException(ce.getMessage());
- ie.initCause(ce);
- throw ie;
+ throw new IOException(ce);
}
}
}
@@ -597,7 +626,7 @@ public class PKCS7 {
intResult.addElement(signerInfo);
}
}
- if (intResult.size() != 0) {
+ if (!intResult.isEmpty()) {
SignerInfo[] result = new SignerInfo[intResult.size()];
intResult.copyInto(result);
@@ -721,8 +750,8 @@ public class PKCS7 {
X509CertInfo tbsCert =
new X509CertInfo(cert.getTBSCertificate());
certIssuerName = (Principal)
- tbsCert.get(CertificateIssuerName.NAME + "." +
- CertificateIssuerName.DN_NAME);
+ tbsCert.get(X509CertInfo.ISSUER + "." +
+ X509CertInfo.DN_NAME);
} catch (Exception e) {
// error generating X500Name object from the cert's
// issuer DN, leave name as is.
@@ -772,6 +801,7 @@ public class PKCS7 {
return this.oldStyle;
}
+ // BEGIN ANDROID-ADDED
/**
* For legacy reasons we need to return exactly the original encoded certificate bytes, instead
* of letting the underlying implementation have a shot at re-encoding the data.
@@ -963,4 +993,183 @@ public class PKCS7 {
wrapped.verify(key, sigProvider);
}
}
+ // END ANDROID-ADDED
+
+ // BEGIN ANDROID-REMOVED: unused in Android
+ /**
+ * Assembles a PKCS #7 signed data message that optionally includes a
+ * signature timestamp.
+ *
+ * @param signature the signature bytes
+ * @param signerChain the signer's X.509 certificate chain
+ * @param content the content that is signed; specify null to not include
+ * it in the PKCS7 data
+ * @param signatureAlgorithm the name of the signature algorithm
+ * @param tsaURI the URI of the Timestamping Authority; or null if no
+ * timestamp is requested
+ * @param tSAPolicyID the TSAPolicyID of the Timestamping Authority as a
+ * numerical object identifier; or null if we leave the TSA server
+ * to choose one. This argument is only used when tsaURI is provided
+ * @return the bytes of the encoded PKCS #7 signed data message
+ * @throws NoSuchAlgorithmException The exception is thrown if the signature
+ * algorithm is unrecognised.
+ * @throws CertificateException The exception is thrown if an error occurs
+ * while processing the signer's certificate or the TSA's
+ * certificate.
+ * @throws IOException The exception is thrown if an error occurs while
+ * generating the signature timestamp or while generating the signed
+ * data message.
+ *
+ public static byte[] generateSignedData(byte[] signature,
+ X509Certificate[] signerChain,
+ byte[] content,
+ String signatureAlgorithm,
+ URI tsaURI,
+ String tSAPolicyID)
+ throws CertificateException, IOException, NoSuchAlgorithmException
+ {
+
+ // Generate the timestamp token
+ PKCS9Attributes unauthAttrs = null;
+ if (tsaURI != null) {
+ // Timestamp the signature
+ HttpTimestamper tsa = new HttpTimestamper(tsaURI);
+ byte[] tsToken = generateTimestampToken(tsa, tSAPolicyID, signature);
+
+ // Insert the timestamp token into the PKCS #7 signer info element
+ // (as an unsigned attribute)
+ unauthAttrs =
+ new PKCS9Attributes(new PKCS9Attribute[]{
+ new PKCS9Attribute(
+ PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR,
+ tsToken)});
+ }
+
+ // Create the SignerInfo
+ X500Name issuerName =
+ X500Name.asX500Name(signerChain[0].getIssuerX500Principal());
+ BigInteger serialNumber = signerChain[0].getSerialNumber();
+ String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
+ String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
+ SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber,
+ AlgorithmId.get(digAlg), null,
+ AlgorithmId.get(encAlg),
+ signature, unauthAttrs);
+
+ // Create the PKCS #7 signed data message
+ SignerInfo[] signerInfos = {signerInfo};
+ AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()};
+ // Include or exclude content
+ ContentInfo contentInfo = (content == null)
+ ? new ContentInfo(ContentInfo.DATA_OID, null)
+ : new ContentInfo(content);
+ PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo,
+ signerChain, signerInfos);
+ ByteArrayOutputStream p7out = new ByteArrayOutputStream();
+ pkcs7.encodeSignedData(p7out);
+
+ return p7out.toByteArray();
+ }
+
+ /**
+ * Requests, processes and validates a timestamp token from a TSA using
+ * common defaults. Uses the following defaults in the timestamp request:
+ * SHA-1 for the hash algorithm, a 64-bit nonce, and request certificate
+ * set to true.
+ *
+ * @param tsa the timestamping authority to use
+ * @param tSAPolicyID the TSAPolicyID of the Timestamping Authority as a
+ * numerical object identifier; or null if we leave the TSA server
+ * to choose one
+ * @param toBeTimestamped the token that is to be timestamped
+ * @return the encoded timestamp token
+ * @throws IOException The exception is thrown if an error occurs while
+ * communicating with the TSA, or a non-null
+ * TSAPolicyID is specified in the request but it
+ * does not match the one in the reply
+ * @throws CertificateException The exception is thrown if the TSA's
+ * certificate is not permitted for timestamping.
+ *
+ private static byte[] generateTimestampToken(Timestamper tsa,
+ String tSAPolicyID,
+ byte[] toBeTimestamped)
+ throws IOException, CertificateException
+ {
+ // Generate a timestamp
+ MessageDigest messageDigest = null;
+ TSRequest tsQuery = null;
+ try {
+ // SHA-1 is always used.
+ messageDigest = MessageDigest.getInstance("SHA-1");
+ tsQuery = new TSRequest(tSAPolicyID, toBeTimestamped, messageDigest);
+ } catch (NoSuchAlgorithmException e) {
+ // ignore
+ }
+
+ // Generate a nonce
+ BigInteger nonce = null;
+ if (SecureRandomHolder.RANDOM != null) {
+ nonce = new BigInteger(64, SecureRandomHolder.RANDOM);
+ tsQuery.setNonce(nonce);
+ }
+ tsQuery.requestCertificate(true);
+
+ TSResponse tsReply = tsa.generateTimestamp(tsQuery);
+ int status = tsReply.getStatusCode();
+ // Handle TSP error
+ if (status != 0 && status != 1) {
+ throw new IOException("Error generating timestamp: " +
+ tsReply.getStatusCodeAsText() + " " +
+ tsReply.getFailureCodeAsText());
+ }
+
+ if (tSAPolicyID != null &&
+ !tSAPolicyID.equals(tsReply.getTimestampToken().getPolicyID())) {
+ throw new IOException("TSAPolicyID changed in "
+ + "timestamp token");
+ }
+ PKCS7 tsToken = tsReply.getToken();
+
+ TimestampToken tst = tsReply.getTimestampToken();
+ if (!tst.getHashAlgorithm().getName().equals("SHA-1")) {
+ throw new IOException("Digest algorithm not SHA-1 in "
+ + "timestamp token");
+ }
+ if (!MessageDigest.isEqual(tst.getHashedMessage(),
+ tsQuery.getHashedMessage())) {
+ throw new IOException("Digest octets changed in timestamp token");
+ }
+
+ BigInteger replyNonce = tst.getNonce();
+ if (replyNonce == null && nonce != null) {
+ throw new IOException("Nonce missing in timestamp token");
+ }
+ if (replyNonce != null && !replyNonce.equals(nonce)) {
+ throw new IOException("Nonce changed in timestamp token");
+ }
+
+ // Examine the TSA's certificate (if present)
+ for (SignerInfo si: tsToken.getSignerInfos()) {
+ X509Certificate cert = si.getCertificate(tsToken);
+ if (cert == null) {
+ // Error, we've already set tsRequestCertificate = true
+ throw new CertificateException(
+ "Certificate not included in timestamp token");
+ } else {
+ if (!cert.getCriticalExtensionOIDs().contains(
+ EXTENDED_KEY_USAGE_OID)) {
+ throw new CertificateException(
+ "Certificate is not valid for timestamping");
+ }
+ List<String> keyPurposes = cert.getExtendedKeyUsage();
+ if (keyPurposes == null ||
+ !keyPurposes.contains(KP_TIMESTAMPING_OID)) {
+ throw new CertificateException(
+ "Certificate is not valid for timestamping");
+ }
+ }
+ }
+ return tsReply.getEncodedToken();
+ }
+ END ANDROID-REMOVED */
}
diff --git a/ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java b/ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java
index 6405c9fc93..59512f11b6 100644
--- a/ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java
+++ b/ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -208,7 +208,7 @@ public class PKCS8Key implements PrivateKey {
throw new InstantiationException();
}
- Class keyClass = null;
+ Class<?> keyClass = null;
try {
keyClass = Class.forName(classname);
} catch (ClassNotFoundException e) {
@@ -304,17 +304,6 @@ public class PKCS8Key implements PrivateKey {
return encodedKey.clone();
}
- /*
- * Returns a printable representation of the key
- */
- public String toString ()
- {
- HexDumpEncoder encoder = new HexDumpEncoder ();
-
- return "algorithm = " + algid.toString ()
- + ", unparsed keybits = \n" + encoder.encodeBuffer (key);
- }
-
/**
* Initialize an PKCS8Key object from an input stream. The data
* on that input stream must be encoded using DER, obeying the
@@ -342,9 +331,9 @@ public class PKCS8Key implements PrivateKey {
BigInteger version = val.data.getBigInteger();
- if (!version.equals(this.version)) {
+ if (!version.equals(PKCS8Key.version)) {
throw new IOException("version mismatch: (supported: " +
- Debug.toHexString(this.version) +
+ Debug.toHexString(PKCS8Key.version) +
", parsed: " +
Debug.toHexString(version));
}