jdk/src/share/classes/sun/security/pkcs/PKCS7.java
changeset 9365 469cd39a25de
parent 9248 44d129a2adfa
child 10336 0bb1999251f8
equal deleted inserted replaced
9307:f4298bc3f4b6 9365:469cd39a25de
    36 import java.security.*;
    36 import java.security.*;
    37 
    37 
    38 import sun.security.util.*;
    38 import sun.security.util.*;
    39 import sun.security.x509.AlgorithmId;
    39 import sun.security.x509.AlgorithmId;
    40 import sun.security.x509.CertificateIssuerName;
    40 import sun.security.x509.CertificateIssuerName;
    41 import sun.security.x509.KeyUsageExtension;
       
    42 import sun.security.x509.X509CertImpl;
    41 import sun.security.x509.X509CertImpl;
    43 import sun.security.x509.X509CertInfo;
    42 import sun.security.x509.X509CertInfo;
    44 import sun.security.x509.X509CRLImpl;
    43 import sun.security.x509.X509CRLImpl;
    45 import sun.security.x509.X500Name;
    44 import sun.security.x509.X500Name;
    46 
    45 
   491         }
   490         }
   492 
   491 
   493         // CRLs (optional)
   492         // CRLs (optional)
   494         if (crls != null && crls.length != 0) {
   493         if (crls != null && crls.length != 0) {
   495             // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder
   494             // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder
   496             Set<X509CRLImpl> implCRLs = new HashSet<>(crls.length);
   495             Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length);
   497             for (X509CRL crl: crls) {
   496             for (X509CRL crl: crls) {
   498                 if (crl instanceof X509CRLImpl)
   497                 if (crl instanceof X509CRLImpl)
   499                     implCRLs.add((X509CRLImpl) crl);
   498                     implCRLs.add((X509CRLImpl) crl);
   500                 else {
   499                 else {
   501                     try {
   500                     try {
   529         // writing out the contentInfo sequence
   528         // writing out the contentInfo sequence
   530         block.encode(out);
   529         block.encode(out);
   531     }
   530     }
   532 
   531 
   533     /**
   532     /**
   534      * Verifying signed data using an external chunked data source.
       
   535      */
       
   536     public static class PKCS7Verifier {
       
   537 
       
   538         private final SignerInfo si;          // Signer to verify
       
   539         private final MessageDigest md;       // MessageDigest object for chunks
       
   540         private final Signature sig;          // Signature object for chunks
       
   541 
       
   542         private PKCS7Verifier(SignerInfo si, MessageDigest md, Signature sig) {
       
   543             this.si = si;
       
   544             this.md = md;
       
   545             this.sig = sig;
       
   546         }
       
   547 
       
   548         public static PKCS7Verifier from(PKCS7 block, SignerInfo si) throws
       
   549                 SignatureException, NoSuchAlgorithmException {
       
   550 
       
   551             try {
       
   552                 MessageDigest md = null;
       
   553                 Signature sig;
       
   554 
       
   555                 ContentInfo content = block.getContentInfo();
       
   556                 String digestAlgname = si.getDigestAlgorithmId().getName();
       
   557 
       
   558                 // if there are authenticate attributes, feed data chunks to
       
   559                 // the message digest. In this case, pv.md is not null
       
   560                 if (si.authenticatedAttributes != null) {
       
   561                     // first, check content type
       
   562                     ObjectIdentifier contentType = (ObjectIdentifier)
       
   563                            si.authenticatedAttributes.getAttributeValue(
       
   564                              PKCS9Attribute.CONTENT_TYPE_OID);
       
   565                     if (contentType == null ||
       
   566                         !contentType.equals(content.contentType))
       
   567                         return null;  // contentType does not match, bad SignerInfo
       
   568 
       
   569                     // now, check message digest
       
   570                     byte[] messageDigest = (byte[])
       
   571                         si.authenticatedAttributes.getAttributeValue(
       
   572                              PKCS9Attribute.MESSAGE_DIGEST_OID);
       
   573 
       
   574                     if (messageDigest == null) // fail if there is no message digest
       
   575                         return null;
       
   576 
       
   577                     md = MessageDigest.getInstance(digestAlgname);
       
   578                 }
       
   579 
       
   580                 // put together digest algorithm and encryption algorithm
       
   581                 // to form signing algorithm
       
   582                 String encryptionAlgname =
       
   583                     si.getDigestEncryptionAlgorithmId().getName();
       
   584 
       
   585                 // Workaround: sometimes the encryptionAlgname is actually
       
   586                 // a signature name
       
   587                 String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
       
   588                 if (tmp != null) encryptionAlgname = tmp;
       
   589                 String algname = AlgorithmId.makeSigAlg(
       
   590                         digestAlgname, encryptionAlgname);
       
   591 
       
   592                 sig = Signature.getInstance(algname);
       
   593                 X509Certificate cert = si.getCertificate(block);
       
   594 
       
   595                 if (cert == null) {
       
   596                     return null;
       
   597                 }
       
   598                 if (cert.hasUnsupportedCriticalExtension()) {
       
   599                     throw new SignatureException("Certificate has unsupported "
       
   600                                                  + "critical extension(s)");
       
   601                 }
       
   602 
       
   603                 // Make sure that if the usage of the key in the certificate is
       
   604                 // restricted, it can be used for digital signatures.
       
   605                 // XXX We may want to check for additional extensions in the
       
   606                 // future.
       
   607                 boolean[] keyUsageBits = cert.getKeyUsage();
       
   608                 if (keyUsageBits != null) {
       
   609                     KeyUsageExtension keyUsage;
       
   610                     try {
       
   611                         // We don't care whether or not this extension was marked
       
   612                         // critical in the certificate.
       
   613                         // We're interested only in its value (i.e., the bits set)
       
   614                         // and treat the extension as critical.
       
   615                         keyUsage = new KeyUsageExtension(keyUsageBits);
       
   616                     } catch (IOException ioe) {
       
   617                         throw new SignatureException("Failed to parse keyUsage "
       
   618                                                      + "extension");
       
   619                     }
       
   620 
       
   621                     boolean digSigAllowed = ((Boolean)keyUsage.get(
       
   622                             KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue();
       
   623 
       
   624                     boolean nonRepuAllowed = ((Boolean)keyUsage.get(
       
   625                             KeyUsageExtension.NON_REPUDIATION)).booleanValue();
       
   626 
       
   627                     if (!digSigAllowed && !nonRepuAllowed) {
       
   628                         throw new SignatureException("Key usage restricted: "
       
   629                                                      + "cannot be used for "
       
   630                                                      + "digital signatures");
       
   631                     }
       
   632                 }
       
   633 
       
   634                 PublicKey key = cert.getPublicKey();
       
   635                 sig.initVerify(key);
       
   636                 return new PKCS7Verifier(si, md, sig);
       
   637             } catch (IOException e) {
       
   638                 throw new SignatureException("IO error verifying signature:\n" +
       
   639                                              e.getMessage());
       
   640 
       
   641             } catch (InvalidKeyException e) {
       
   642                 throw new SignatureException("InvalidKey: " + e.getMessage());
       
   643 
       
   644             }
       
   645         }
       
   646 
       
   647         public void update(byte[] data, int off, int end)
       
   648                 throws SignatureException {
       
   649             if (md != null) {
       
   650                 md.update(data, off, end-off);
       
   651             } else {
       
   652                 sig.update(data, off, end-off);
       
   653             }
       
   654         }
       
   655 
       
   656         public SignerInfo verify() throws SignatureException {
       
   657             try {
       
   658                 // if there are authenticate attributes, get the message
       
   659                 // digest and compare it with the digest of data
       
   660                 if (md != null) {
       
   661                     // now, check message digest
       
   662                     byte[] messageDigest = (byte[])
       
   663                         si.authenticatedAttributes.getAttributeValue(
       
   664                              PKCS9Attribute.MESSAGE_DIGEST_OID);
       
   665 
       
   666                     byte[] computedMessageDigest = md.digest();
       
   667 
       
   668                     if (!MessageDigest.isEqual(
       
   669                             messageDigest, computedMessageDigest)) {
       
   670                         return null;
       
   671                     }
       
   672 
       
   673                     // message digest attribute matched
       
   674                     // digest of original data
       
   675 
       
   676                     // the data actually signed is the DER encoding of
       
   677                     // the authenticated attributes (tagged with
       
   678                     // the "SET OF" tag, not 0xA0).
       
   679                     byte[] dataSigned = si.authenticatedAttributes.getDerEncoding();
       
   680                     sig.update(dataSigned);
       
   681                 }
       
   682 
       
   683                 if (sig.verify(si.getEncryptedDigest())) {
       
   684                     return si;
       
   685                 }
       
   686 
       
   687             } catch (IOException e) {
       
   688                 throw new SignatureException("IO error verifying signature:\n" +
       
   689                                              e.getMessage());
       
   690             }
       
   691             return null;
       
   692         }
       
   693     }
       
   694 
       
   695     /**
       
   696      * This verifies a given SignerInfo.
   533      * This verifies a given SignerInfo.
   697      *
   534      *
   698      * @param info the signer information.
   535      * @param info the signer information.
   699      * @param bytes the DER encoded content information.
   536      * @param bytes the DER encoded content information.
   700      *
   537      *
   715      * @exception SignatureException on signature handling errors.
   552      * @exception SignatureException on signature handling errors.
   716      */
   553      */
   717     public SignerInfo[] verify(byte[] bytes)
   554     public SignerInfo[] verify(byte[] bytes)
   718     throws NoSuchAlgorithmException, SignatureException {
   555     throws NoSuchAlgorithmException, SignatureException {
   719 
   556 
   720         List<SignerInfo> intResult = new ArrayList<>();
   557         Vector<SignerInfo> intResult = new Vector<SignerInfo>();
   721         for (int i = 0; i < signerInfos.length; i++) {
   558         for (int i = 0; i < signerInfos.length; i++) {
   722 
   559 
   723             SignerInfo signerInfo = verify(signerInfos[i], bytes);
   560             SignerInfo signerInfo = verify(signerInfos[i], bytes);
   724             if (signerInfo != null) {
   561             if (signerInfo != null) {
   725                 intResult.add(signerInfo);
   562                 intResult.addElement(signerInfo);
   726             }
   563             }
   727         }
   564         }
   728         if (!intResult.isEmpty()) {
   565         if (intResult.size() != 0) {
   729             return intResult.toArray(new SignerInfo[intResult.size()]);
   566 
       
   567             SignerInfo[] result = new SignerInfo[intResult.size()];
       
   568             intResult.copyInto(result);
       
   569             return result;
   730         }
   570         }
   731         return null;
   571         return null;
   732     }
   572     }
   733 
   573 
   734     /**
   574     /**