11/*
2- * Copyright (c) 1996, 2024 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 1996, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -303,15 +303,20 @@ public ArrayList<X509Certificate> getCertificateChain(PKCS7 block)
303303 return certList ;
304304 }
305305
306- /* Returns null if verify fails, this signerInfo if
307- verify succeeds. */
308- SignerInfo verify (PKCS7 block , byte [] data )
309- throws NoSuchAlgorithmException , SignatureException {
306+ /**
307+ * Verify this signerInfo in a PKCS7 block.
308+ *
309+ * @param block the PKCS7 object
310+ * @param data the content to verify against; read from block if null
311+ * @param cert certificate to verify with; read from block if null
312+ * @return null if verify fails, this signerInfo if verify succeeds.
313+ */
314+ SignerInfo verify (PKCS7 block , byte [] data , X509Certificate cert )
315+ throws NoSuchAlgorithmException , SignatureException {
310316
311317 try {
312- Timestamp timestamp = null ;
313318 try {
314- timestamp = getTimestamp ();
319+ getTimestamp ();
315320 } catch (Exception e ) {
316321 // Log exception and continue. This allows for the case
317322 // where, if there are no other errors, the code is
@@ -356,22 +361,19 @@ SignerInfo verify(PKCS7 block, byte[] data)
356361 return null ;
357362
358363 byte [] computedMessageDigest ;
359- if (digestAlgName .equals ("SHAKE256" )
360- || digestAlgName .equals ("SHAKE256-LEN" )) {
361- if (digestAlgName .equals ("SHAKE256-LEN" )) {
362- // RFC8419: for EdDSA in CMS, the id-shake256-len
363- // algorithm id must contain parameter value 512
364- // encoded as a positive integer value
365- byte [] params = digestAlgorithmId .getEncodedParams ();
366- if (params == null ) {
367- throw new SignatureException (
368- "id-shake256-len oid missing length" );
369- }
370- int v = new DerValue (params ).getInteger ();
371- if (v != 512 ) {
372- throw new SignatureException (
373- "Unsupported id-shake256-" + v );
374- }
364+ if (digestAlgName .equals ("SHAKE256-LEN" )) {
365+ // RFC8419: for EdDSA in CMS, the id-shake256-len
366+ // algorithm id must contain parameter value 512
367+ // encoded as a positive integer value
368+ byte [] params = digestAlgorithmId .getEncodedParams ();
369+ if (params == null ) {
370+ throw new SignatureException (
371+ "id-shake256-len oid missing length" );
372+ }
373+ int v = new DerValue (params ).getInteger ();
374+ if (v != 512 ) {
375+ throw new SignatureException (
376+ "Unsupported id-shake256-" + v );
375377 }
376378 var md = new SHAKE256 (64 );
377379 md .update (data , 0 , data .length );
@@ -410,9 +412,11 @@ SignerInfo verify(PKCS7 block, byte[] data)
410412 "SignerInfo digestEncryptionAlgorithm field" , true ));
411413 }
412414
413- X509Certificate cert = getCertificate (block );
414415 if (cert == null ) {
415- return null ;
416+ cert = getCertificate (block );
417+ if (cert == null ) {
418+ return null ;
419+ }
416420 }
417421 PublicKey key = cert .getPublicKey ();
418422
@@ -503,29 +507,59 @@ private static void algorithmsConformanceCheck(
503507 }
504508
505509 if (!AlgorithmId .get (spec .getDigestAlgorithm ()).equals (digAlgId )) {
506- throw new NoSuchAlgorithmException ("Incompatible digest algorithm" );
510+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
507511 }
508512 break ;
509513 case "Ed25519" :
510- if (!digAlgId .equals ( SignatureUtil . EdDSADigestAlgHolder . sha512 )) {
511- throw new NoSuchAlgorithmException ("Incompatible digest algorithm" );
514+ if (!digAlgId .equalsOID ( AlgorithmId . SHA512_oid )) {
515+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
512516 }
513517 break ;
514518 case "Ed448" :
515519 if (directSign ) {
516- if (!digAlgId .equals ( SignatureUtil . EdDSADigestAlgHolder . shake256 )) {
517- throw new NoSuchAlgorithmException ("Incompatible digest algorithm" );
520+ if (!digAlgId .equalsOID ( AlgorithmId . SHAKE256_512_oid )) {
521+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
518522 }
519523 } else {
520- if (!digAlgId .equals (SignatureUtil .EdDSADigestAlgHolder . shake256$512 )) {
521- throw new NoSuchAlgorithmException ("Incompatible digest algorithm" );
524+ if (!digAlgId .equals (SignatureUtil .DigestAlgHolder . shake256lenWith512 )) {
525+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
522526 }
523527 }
524528 break ;
525529 case "HSS/LMS" :
526530 // RFC 8708 requires the same hash algorithm used as in the HSS/LMS algorithm
527- if (!digAlgId .equals (AlgorithmId .get (KeyUtil .hashAlgFromHSS (key )))) {
528- throw new NoSuchAlgorithmException ("Incompatible digest algorithm" );
531+ if (!digAlgId .equalsOID (KeyUtil .hashAlgFromHSS (key ))) {
532+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
533+ }
534+ break ;
535+ case "ML-DSA-44" :
536+ // Following 3 from Table 1 inside
537+ // https://datatracker.ietf.org/doc/html/rfc9882#name-signerinfo-content
538+ if (!digAlgId .equalsOID (AlgorithmId .SHA256_oid )
539+ && !digAlgId .equalsOID (AlgorithmId .SHA384_oid )
540+ && !digAlgId .equalsOID (AlgorithmId .SHA512_oid )
541+ && !digAlgId .equalsOID (AlgorithmId .SHA3_256_oid )
542+ && !digAlgId .equalsOID (AlgorithmId .SHA3_384_oid )
543+ && !digAlgId .equalsOID (AlgorithmId .SHA3_512_oid )
544+ && !digAlgId .equalsOID (AlgorithmId .SHAKE128_256_oid )
545+ && !digAlgId .equalsOID (AlgorithmId .SHAKE256_512_oid )) {
546+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
547+ }
548+ break ;
549+ case "ML-DSA-65" :
550+ if (!digAlgId .equalsOID (AlgorithmId .SHA384_oid )
551+ && !digAlgId .equalsOID (AlgorithmId .SHA512_oid )
552+ && !digAlgId .equalsOID (AlgorithmId .SHA3_384_oid )
553+ && !digAlgId .equalsOID (AlgorithmId .SHA3_512_oid )
554+ && !digAlgId .equalsOID (AlgorithmId .SHAKE256_512_oid )) {
555+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
556+ }
557+ break ;
558+ case "ML-DSA-87" :
559+ if (!digAlgId .equalsOID (AlgorithmId .SHA512_oid )
560+ && !digAlgId .equalsOID (AlgorithmId .SHA3_512_oid )
561+ && !digAlgId .equalsOID (AlgorithmId .SHAKE256_512_oid )) {
562+ throw new NoSuchAlgorithmException ("Incompatible digest algorithm " + digAlgId );
529563 }
530564 break ;
531565 }
@@ -538,9 +572,9 @@ private static void algorithmsConformanceCheck(
538572 * The digest algorithm is in the form "DIG", and the encryption
539573 * algorithm can be in any of the 3 forms:
540574 *
541- * 1. Old style key algorithm like RSA, DSA, EC, this method returns
575+ * 1. Simple key algorithm like RSA, DSA, EC, this method returns
542576 * DIGwithKEY.
543- * 2. New style signature algorithm in the form of HASHwithKEY, this
577+ * 2. Traditional signature algorithm in the form of HASHwithKEY, this
544578 * method returns DIGwithKEY. Please note this is not HASHwithKEY.
545579 * 3. Modern signature algorithm like RSASSA-PSS and EdDSA, this method
546580 * returns the signature algorithm itself.
@@ -550,40 +584,26 @@ private static void algorithmsConformanceCheck(
550584 */
551585 public static String makeSigAlg (AlgorithmId digAlgId , AlgorithmId encAlgId ) {
552586 String encAlg = encAlgId .getName ();
553- switch (encAlg ) {
554- case "RSASSA-PSS" :
555- case "Ed25519" :
556- case "Ed448" :
557- case "HSS/LMS" :
558- return encAlg ;
559- default :
560- String digAlg = digAlgId .getName ();
561- String keyAlg = SignatureUtil .extractKeyAlgFromDwithE (encAlg );
562- if (keyAlg == null ) {
563- // The encAlg used to be only the key alg
564- keyAlg = encAlg ;
565- }
566- if (digAlg .startsWith ("SHA-" )) {
567- digAlg = "SHA" + digAlg .substring (4 );
568- }
569- if (keyAlg .equals ("EC" )) keyAlg = "ECDSA" ;
570- String sigAlg = digAlg + "with" + keyAlg ;
571- try {
572- Signature .getInstance (sigAlg );
573- return sigAlg ;
574- } catch (NoSuchAlgorithmException e ) {
575- // Possibly an unknown modern signature algorithm,
576- // in this case, encAlg should already be a signature
577- // algorithm.
578- return encAlg ;
579- }
587+ String keyAlg = SignatureUtil .extractKeyAlgFromDwithE (encAlg );
588+ if (keyAlg == null ) { // No "WITH" inside
589+ if (encAlg .equals ("RSA" ) || encAlg .equals ("DSA" ) || encAlg .equals ("EC" )) {
590+ keyAlg = encAlg ; // Sometimes encAlgId is just the enc alg
591+ } else {
592+ return encAlg ; // Must be a modern algorithm like EdDSA or ML-DSA
593+ }
594+ }
595+ String digAlg = digAlgId .getName ();
596+ if (digAlg .startsWith ("SHA-" )) {
597+ digAlg = "SHA" + digAlg .substring (4 );
580598 }
599+ if (keyAlg .equals ("EC" )) keyAlg = "ECDSA" ;
600+ return digAlg + "with" + keyAlg ;
581601 }
582602
583603 /* Verify the content of the pkcs7 block. */
584604 SignerInfo verify (PKCS7 block )
585605 throws NoSuchAlgorithmException , SignatureException {
586- return verify (block , null );
606+ return verify (block , null , null );
587607 }
588608
589609 public BigInteger getVersion () {
0 commit comments