< prev index next >

src/share/classes/sun/security/pkcs/SignerInfo.java

Print this page


   1 /*
   2  * Copyright (c) 1996, 2016, 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.pkcs;
  27 
  28 import java.io.OutputStream;
  29 import java.io.IOException;
  30 import java.math.BigInteger;
  31 import java.security.CryptoPrimitive;
  32 import java.security.InvalidKeyException;
  33 import java.security.MessageDigest;
  34 import java.security.NoSuchAlgorithmException;
  35 import java.security.Principal;
  36 import java.security.PublicKey;
  37 import java.security.Signature;
  38 import java.security.SignatureException;
  39 import java.security.Timestamp;

  40 import java.security.cert.CertificateException;
  41 import java.security.cert.CertificateFactory;
  42 import java.security.cert.CertPath;
  43 import java.security.cert.X509Certificate;
  44 import java.util.ArrayList;
  45 import java.util.Arrays;
  46 import java.util.Collections;
  47 import java.util.EnumSet;
  48 import java.util.Set;
  49 
  50 import sun.misc.HexDumpEncoder;
  51 import sun.security.timestamp.TimestampToken;

  52 import sun.security.util.Debug;
  53 import sun.security.util.DerEncoder;
  54 import sun.security.util.DerInputStream;
  55 import sun.security.util.DerOutputStream;
  56 import sun.security.util.DerValue;
  57 import sun.security.util.DisabledAlgorithmConstraints;
  58 import sun.security.util.KeyUtil;
  59 import sun.security.util.ObjectIdentifier;
  60 import sun.security.x509.AlgorithmId;
  61 import sun.security.x509.X500Name;
  62 import sun.security.x509.KeyUsageExtension;
  63 
  64 /**
  65  * A SignerInfo, as defined in PKCS#7's signedData type.
  66  *
  67  * @author Benjamin Renaud
  68  */
  69 public class SignerInfo implements DerEncoder {
  70 
  71     // Digest and Signature restrictions


 192             if (derin.available() != 0
 193                 && (byte)(derin.peekByte()) == (byte)0xA1) {
 194                 unauthenticatedAttributes =
 195                     new PKCS9Attributes(derin, true);// ignore unsupported attrs
 196             }
 197         }
 198 
 199         // all done
 200         if (derin.available() != 0) {
 201             throw new ParsingException("extra data at the end");
 202         }
 203     }
 204 
 205     public void encode(DerOutputStream out) throws IOException {
 206 
 207         derEncode(out);
 208     }
 209 
 210     /**
 211      * DER encode this object onto an output stream.
 212      * Implements the <code>DerEncoder</code> interface.
 213      *
 214      * @param out
 215      * the output stream on which to write the DER encoding.
 216      *
 217      * @exception IOException on encoding error.
 218      */
 219     public void derEncode(OutputStream out) throws IOException {
 220         DerOutputStream seq = new DerOutputStream();
 221         seq.putInteger(version);
 222         DerOutputStream issuerAndSerialNumber = new DerOutputStream();
 223         issuerName.encode(issuerAndSerialNumber);
 224         issuerAndSerialNumber.putInteger(certificateSerialNumber);
 225         seq.write(DerValue.tag_Sequence, issuerAndSerialNumber);
 226 
 227         digestAlgorithmId.encode(seq);
 228 
 229         // encode authenticated attributes if there are any
 230         if (authenticatedAttributes != null)
 231             authenticatedAttributes.encode((byte)0xA0, seq);
 232 


 249     /*
 250      * Returns the (user) certificate pertaining to this SignerInfo.
 251      */
 252     public X509Certificate getCertificate(PKCS7 block)
 253         throws IOException
 254     {
 255         return block.getCertificate(certificateSerialNumber, issuerName);
 256     }
 257 
 258     /*
 259      * Returns the certificate chain pertaining to this SignerInfo.
 260      */
 261     public ArrayList<X509Certificate> getCertificateChain(PKCS7 block)
 262         throws IOException
 263     {
 264         X509Certificate userCert;
 265         userCert = block.getCertificate(certificateSerialNumber, issuerName);
 266         if (userCert == null)
 267             return null;
 268 
 269         ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
 270         certList.add(userCert);
 271 
 272         X509Certificate[] pkcsCerts = block.getCertificates();
 273         if (pkcsCerts == null
 274             || userCert.getSubjectDN().equals(userCert.getIssuerDN())) {
 275             return certList;
 276         }
 277 
 278         Principal issuer = userCert.getIssuerDN();
 279         int start = 0;
 280         while (true) {
 281             boolean match = false;
 282             int i = start;
 283             while (i < pkcsCerts.length) {
 284                 if (issuer.equals(pkcsCerts[i].getSubjectDN())) {
 285                     // next cert in chain found
 286                     certList.add(pkcsCerts[i]);
 287                     // if selected cert is self-signed, we're done
 288                     // constructing the chain
 289                     if (pkcsCerts[i].getSubjectDN().equals(


 304             }
 305             if (!match)
 306                 break;
 307         }
 308 
 309         return certList;
 310     }
 311 
 312     /* Returns null if verify fails, this signerInfo if
 313        verify succeeds. */
 314     SignerInfo verify(PKCS7 block, byte[] data)
 315     throws NoSuchAlgorithmException, SignatureException {
 316 
 317         try {
 318 
 319             ContentInfo content = block.getContentInfo();
 320             if (data == null) {
 321                 data = content.getContentBytes();
 322             }
 323 


 324             String digestAlgname = getDigestAlgorithmId().getName();
 325 
 326             byte[] dataSigned;
 327 
 328             // if there are authenticate attributes, get the message
 329             // digest and compare it with the digest of data
 330             if (authenticatedAttributes == null) {
 331                 dataSigned = data;
 332             } else {
 333 
 334                 // first, check content type
 335                 ObjectIdentifier contentType = (ObjectIdentifier)
 336                        authenticatedAttributes.getAttributeValue(
 337                          PKCS9Attribute.CONTENT_TYPE_OID);
 338                 if (contentType == null ||
 339                     !contentType.equals((Object)content.contentType))
 340                     return null;  // contentType does not match, bad SignerInfo
 341 
 342                 // now, check message digest
 343                 byte[] messageDigest = (byte[])
 344                     authenticatedAttributes.getAttributeValue(
 345                          PKCS9Attribute.MESSAGE_DIGEST_OID);
 346 
 347                 if (messageDigest == null) // fail if there is no message digest
 348                     return null;
 349 
 350                 // check that algorithm is not restricted
 351                 if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET,
 352                         digestAlgname, null)) {
 353                     throw new SignatureException("Digest check failed. " +
 354                             "Disabled algorithm used: " + digestAlgname);
 355                 }
 356 
 357                 MessageDigest md = MessageDigest.getInstance(digestAlgname);
 358                 byte[] computedMessageDigest = md.digest(data);
 359 
 360                 if (messageDigest.length != computedMessageDigest.length)
 361                     return null;
 362                 for (int i = 0; i < messageDigest.length; i++) {
 363                     if (messageDigest[i] != computedMessageDigest[i])
 364                         return null;
 365                 }
 366 
 367                 // message digest attribute matched
 368                 // digest of original data
 369 
 370                 // the data actually signed is the DER encoding of
 371                 // the authenticated attributes (tagged with
 372                 // the "SET OF" tag, not 0xA0).
 373                 dataSigned = authenticatedAttributes.getDerEncoding();
 374             }
 375 
 376             // put together digest algorithm and encryption algorithm
 377             // to form signing algorithm
 378             String encryptionAlgname =
 379                 getDigestEncryptionAlgorithmId().getName();
 380 
 381             // Workaround: sometimes the encryptionAlgname is actually
 382             // a signature name
 383             String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
 384             if (tmp != null) encryptionAlgname = tmp;
 385             String algname = AlgorithmId.makeSigAlg(
 386                     digestAlgname, encryptionAlgname);
 387 
 388             // check that algorithm is not restricted
 389             if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, algname, null)) {
 390                 throw new SignatureException("Signature check failed. " +
 391                         "Disabled algorithm used: " + algname);

 392             }
 393 
 394             X509Certificate cert = getCertificate(block);
 395             PublicKey key = cert.getPublicKey();
 396             if (cert == null) {
 397                 return null;
 398             }

 399 
 400             // check if the public key is restricted
 401             if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
 402                 throw new SignatureException("Public key check failed. " +
 403                         "Disabled key used: " +
 404                         KeyUtil.getKeySize(key) + " bit " +
 405                         key.getAlgorithm());
 406             }
 407 
 408             if (cert.hasUnsupportedCriticalExtension()) {
 409                 throw new SignatureException("Certificate has unsupported "
 410                                              + "critical extension(s)");
 411             }
 412 
 413             // Make sure that if the usage of the key in the certificate is
 414             // restricted, it can be used for digital signatures.
 415             // XXX We may want to check for additional extensions in the
 416             // future.
 417             boolean[] keyUsageBits = cert.getKeyUsage();
 418             if (keyUsageBits != null) {


 502      * Returns the timestamp PKCS7 data unverified.
 503      * @return a PKCS7 object
 504      */
 505     public PKCS7 getTsToken() throws IOException {
 506         if (unauthenticatedAttributes == null) {
 507             return null;
 508         }
 509         PKCS9Attribute tsTokenAttr =
 510                 unauthenticatedAttributes.getAttribute(
 511                         PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
 512         if (tsTokenAttr == null) {
 513             return null;
 514         }
 515         return new PKCS7((byte[])tsTokenAttr.getValue());
 516     }
 517 
 518     /*
 519      * Extracts a timestamp from a PKCS7 SignerInfo.
 520      *
 521      * Examines the signer's unsigned attributes for a
 522      * <tt>signatureTimestampToken</tt> attribute. If present,
 523      * then it is parsed to extract the date and time at which the
 524      * timestamp was generated.
 525      *
 526      * @param info A signer information element of a PKCS 7 block.
 527      *
 528      * @return A timestamp token or null if none is present.
 529      * @throws IOException if an error is encountered while parsing the
 530      *         PKCS7 data.
 531      * @throws NoSuchAlgorithmException if an error is encountered while
 532      *         verifying the PKCS7 object.
 533      * @throws SignatureException if an error is encountered while
 534      *         verifying the PKCS7 object.
 535      * @throws CertificateException if an error is encountered while generating
 536      *         the TSA's certpath.
 537      */
 538     public Timestamp getTimestamp()
 539         throws IOException, NoSuchAlgorithmException, SignatureException,
 540                CertificateException
 541     {
 542         if (timestamp != null || !hasTimestamp)


   1 /*
   2  * Copyright (c) 1996, 2017, 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.pkcs;
  27 
  28 import java.io.OutputStream;
  29 import java.io.IOException;
  30 import java.math.BigInteger;
  31 import java.security.CryptoPrimitive;
  32 import java.security.InvalidKeyException;
  33 import java.security.MessageDigest;
  34 import java.security.NoSuchAlgorithmException;
  35 import java.security.Principal;
  36 import java.security.PublicKey;
  37 import java.security.Signature;
  38 import java.security.SignatureException;
  39 import java.security.Timestamp;
  40 import java.security.cert.CertPathValidatorException;
  41 import java.security.cert.CertificateException;
  42 import java.security.cert.CertificateFactory;
  43 import java.security.cert.CertPath;
  44 import java.security.cert.X509Certificate;
  45 import java.util.ArrayList;
  46 import java.util.Arrays;
  47 import java.util.Collections;
  48 import java.util.EnumSet;
  49 import java.util.Set;
  50 
  51 import sun.misc.HexDumpEncoder;
  52 import sun.security.timestamp.TimestampToken;
  53 import sun.security.util.ConstraintsParameters;
  54 import sun.security.util.Debug;
  55 import sun.security.util.DerEncoder;
  56 import sun.security.util.DerInputStream;
  57 import sun.security.util.DerOutputStream;
  58 import sun.security.util.DerValue;
  59 import sun.security.util.DisabledAlgorithmConstraints;
  60 import sun.security.util.KeyUtil;
  61 import sun.security.util.ObjectIdentifier;
  62 import sun.security.x509.AlgorithmId;
  63 import sun.security.x509.X500Name;
  64 import sun.security.x509.KeyUsageExtension;
  65 
  66 /**
  67  * A SignerInfo, as defined in PKCS#7's signedData type.
  68  *
  69  * @author Benjamin Renaud
  70  */
  71 public class SignerInfo implements DerEncoder {
  72 
  73     // Digest and Signature restrictions


 194             if (derin.available() != 0
 195                 && (byte)(derin.peekByte()) == (byte)0xA1) {
 196                 unauthenticatedAttributes =
 197                     new PKCS9Attributes(derin, true);// ignore unsupported attrs
 198             }
 199         }
 200 
 201         // all done
 202         if (derin.available() != 0) {
 203             throw new ParsingException("extra data at the end");
 204         }
 205     }
 206 
 207     public void encode(DerOutputStream out) throws IOException {
 208 
 209         derEncode(out);
 210     }
 211 
 212     /**
 213      * DER encode this object onto an output stream.
 214      * Implements the {@code DerEncoder} interface.
 215      *
 216      * @param out
 217      * the output stream on which to write the DER encoding.
 218      *
 219      * @exception IOException on encoding error.
 220      */
 221     public void derEncode(OutputStream out) throws IOException {
 222         DerOutputStream seq = new DerOutputStream();
 223         seq.putInteger(version);
 224         DerOutputStream issuerAndSerialNumber = new DerOutputStream();
 225         issuerName.encode(issuerAndSerialNumber);
 226         issuerAndSerialNumber.putInteger(certificateSerialNumber);
 227         seq.write(DerValue.tag_Sequence, issuerAndSerialNumber);
 228 
 229         digestAlgorithmId.encode(seq);
 230 
 231         // encode authenticated attributes if there are any
 232         if (authenticatedAttributes != null)
 233             authenticatedAttributes.encode((byte)0xA0, seq);
 234 


 251     /*
 252      * Returns the (user) certificate pertaining to this SignerInfo.
 253      */
 254     public X509Certificate getCertificate(PKCS7 block)
 255         throws IOException
 256     {
 257         return block.getCertificate(certificateSerialNumber, issuerName);
 258     }
 259 
 260     /*
 261      * Returns the certificate chain pertaining to this SignerInfo.
 262      */
 263     public ArrayList<X509Certificate> getCertificateChain(PKCS7 block)
 264         throws IOException
 265     {
 266         X509Certificate userCert;
 267         userCert = block.getCertificate(certificateSerialNumber, issuerName);
 268         if (userCert == null)
 269             return null;
 270 
 271         ArrayList<X509Certificate> certList = new ArrayList<>();
 272         certList.add(userCert);
 273 
 274         X509Certificate[] pkcsCerts = block.getCertificates();
 275         if (pkcsCerts == null
 276             || userCert.getSubjectDN().equals(userCert.getIssuerDN())) {
 277             return certList;
 278         }
 279 
 280         Principal issuer = userCert.getIssuerDN();
 281         int start = 0;
 282         while (true) {
 283             boolean match = false;
 284             int i = start;
 285             while (i < pkcsCerts.length) {
 286                 if (issuer.equals(pkcsCerts[i].getSubjectDN())) {
 287                     // next cert in chain found
 288                     certList.add(pkcsCerts[i]);
 289                     // if selected cert is self-signed, we're done
 290                     // constructing the chain
 291                     if (pkcsCerts[i].getSubjectDN().equals(


 306             }
 307             if (!match)
 308                 break;
 309         }
 310 
 311         return certList;
 312     }
 313 
 314     /* Returns null if verify fails, this signerInfo if
 315        verify succeeds. */
 316     SignerInfo verify(PKCS7 block, byte[] data)
 317     throws NoSuchAlgorithmException, SignatureException {
 318 
 319         try {
 320 
 321             ContentInfo content = block.getContentInfo();
 322             if (data == null) {
 323                 data = content.getContentBytes();
 324             }
 325 
 326             ConstraintsParameters cparams =
 327                     new ConstraintsParameters(timestamp);
 328             String digestAlgname = getDigestAlgorithmId().getName();
 329 
 330             byte[] dataSigned;
 331 
 332             // if there are authenticate attributes, get the message
 333             // digest and compare it with the digest of data
 334             if (authenticatedAttributes == null) {
 335                 dataSigned = data;
 336             } else {
 337 
 338                 // first, check content type
 339                 ObjectIdentifier contentType = (ObjectIdentifier)
 340                        authenticatedAttributes.getAttributeValue(
 341                          PKCS9Attribute.CONTENT_TYPE_OID);
 342                 if (contentType == null ||
 343                     !contentType.equals((Object)content.contentType))
 344                     return null;  // contentType does not match, bad SignerInfo
 345 
 346                 // now, check message digest
 347                 byte[] messageDigest = (byte[])
 348                     authenticatedAttributes.getAttributeValue(
 349                          PKCS9Attribute.MESSAGE_DIGEST_OID);
 350 
 351                 if (messageDigest == null) // fail if there is no message digest
 352                     return null;
 353 
 354                 // check that digest algorithm is not restricted
 355                 try {
 356                     JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
 357                 } catch (CertPathValidatorException e) {
 358                     throw new SignatureException(e.getMessage(), e);
 359                 }
 360 
 361                 MessageDigest md = MessageDigest.getInstance(digestAlgname);
 362                 byte[] computedMessageDigest = md.digest(data);
 363 
 364                 if (messageDigest.length != computedMessageDigest.length)
 365                     return null;
 366                 for (int i = 0; i < messageDigest.length; i++) {
 367                     if (messageDigest[i] != computedMessageDigest[i])
 368                         return null;
 369                 }
 370 
 371                 // message digest attribute matched
 372                 // digest of original data
 373 
 374                 // the data actually signed is the DER encoding of
 375                 // the authenticated attributes (tagged with
 376                 // the "SET OF" tag, not 0xA0).
 377                 dataSigned = authenticatedAttributes.getDerEncoding();
 378             }
 379 
 380             // put together digest algorithm and encryption algorithm
 381             // to form signing algorithm
 382             String encryptionAlgname =
 383                 getDigestEncryptionAlgorithmId().getName();
 384 
 385             // Workaround: sometimes the encryptionAlgname is actually
 386             // a signature name
 387             String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
 388             if (tmp != null) encryptionAlgname = tmp;
 389             String algname = AlgorithmId.makeSigAlg(
 390                     digestAlgname, encryptionAlgname);
 391 
 392             // check that jar signature algorithm is not restricted
 393             try {
 394                 JAR_DISABLED_CHECK.permits(algname, cparams);
 395             } catch (CertPathValidatorException e) {
 396                 throw new SignatureException(e.getMessage(), e);
 397             }
 398 
 399             X509Certificate cert = getCertificate(block);

 400             if (cert == null) {
 401                 return null;
 402             }
 403             PublicKey key = cert.getPublicKey();
 404 
 405             // check if the public key is restricted
 406             if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
 407                 throw new SignatureException("Public key check failed. " +
 408                         "Disabled key used: " +
 409                         KeyUtil.getKeySize(key) + " bit " +
 410                         key.getAlgorithm());
 411             }
 412 
 413             if (cert.hasUnsupportedCriticalExtension()) {
 414                 throw new SignatureException("Certificate has unsupported "
 415                                              + "critical extension(s)");
 416             }
 417 
 418             // Make sure that if the usage of the key in the certificate is
 419             // restricted, it can be used for digital signatures.
 420             // XXX We may want to check for additional extensions in the
 421             // future.
 422             boolean[] keyUsageBits = cert.getKeyUsage();
 423             if (keyUsageBits != null) {


 507      * Returns the timestamp PKCS7 data unverified.
 508      * @return a PKCS7 object
 509      */
 510     public PKCS7 getTsToken() throws IOException {
 511         if (unauthenticatedAttributes == null) {
 512             return null;
 513         }
 514         PKCS9Attribute tsTokenAttr =
 515                 unauthenticatedAttributes.getAttribute(
 516                         PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
 517         if (tsTokenAttr == null) {
 518             return null;
 519         }
 520         return new PKCS7((byte[])tsTokenAttr.getValue());
 521     }
 522 
 523     /*
 524      * Extracts a timestamp from a PKCS7 SignerInfo.
 525      *
 526      * Examines the signer's unsigned attributes for a
 527      * {@code signatureTimestampToken} attribute. If present,
 528      * then it is parsed to extract the date and time at which the
 529      * timestamp was generated.
 530      *
 531      * @param info A signer information element of a PKCS 7 block.
 532      *
 533      * @return A timestamp token or null if none is present.
 534      * @throws IOException if an error is encountered while parsing the
 535      *         PKCS7 data.
 536      * @throws NoSuchAlgorithmException if an error is encountered while
 537      *         verifying the PKCS7 object.
 538      * @throws SignatureException if an error is encountered while
 539      *         verifying the PKCS7 object.
 540      * @throws CertificateException if an error is encountered while generating
 541      *         the TSA's certpath.
 542      */
 543     public Timestamp getTimestamp()
 544         throws IOException, NoSuchAlgorithmException, SignatureException,
 545                CertificateException
 546     {
 547         if (timestamp != null || !hasTimestamp)


< prev index next >