santuario-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 44335] - can't validate after invalid validation
Date Tue, 05 Feb 2008 00:34:15 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=44335>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=44335





------- Additional Comments From putmanb@georgetown.edu  2008-02-04 16:34 -------
I spent some time debugging this, as it sounded similar to bug reported for our
project.  I don't think the two are related, but here is what I learned.

This bug is happening when an exception is thrown in
XMLSignature#checkSignatureValue(Key), between the time that
SignatureAlgorithm#initVerify(Key) is called and
SignatureAlgorithm#verify(byte[]) is called, obviously resulting in the latter
never being called.

Because the verify operation is not performed, the (thread local) cached
java.security.Signature instance held in the SignatureAlgorithm instancesVerify
Map is left in a state (in this particular case) with updated data in the
buffer, that is never cleared/reset by a verify operation.

Ordinarily this wouldn't be a problem, because on the next verify op in the same
thread, the java.security.Signature instance would be reinitialized ultimately
with java.security.Signature#initVerify(PublicKey), via a call to
SignatureAlgorithmSpi.  However, due to the optimization that's being done in
SignatureAlgorithm#initVerify(Key), if the key used for the next verify op for
that algorithm in that thread is the *same* key as the previous (failed)
operation, it doesn't call the underlying
SignatureAlgorithmSpi#engineInitVerify(Key).

So the bug is that this optimization implicitly assumes that the previous op
with that key always ran to completion, which is not true in this case.

In the subsequent verification, the data over which the signature is calculated
is *added* to whatever data is in the buffer from the previous failed op,
resulting in a failed verification on an otherwise valid signature.

In this particular test case, the exception is being thrown here:

         //retrieve the byte[] from the stored signature
         byte sigBytes[] = this.getSignatureValue(); 

because the way the invalidly signed test case control document is being
invalidated is by modifying the ds:SignatureValue data, but with what is
syntactically invalid Base64-encoded data - it's not a multiple of 4 bytes and
also has an illegal character.  I suppose it could be argued that this is pretty
unlikely to happen in the real world, but IMHO it seems the library probably
ought to handle it more gracefully. Especially because I think you could get a
similar bug case if for example the code below that writes the signed data into
the SignatureAlgorithm were to throw an exception after having written some data
to the java.security.Signature buffer.


         // Get the canonicalized (normalized) SignedInfo
         SignerOutputStream so=new SignerOutputStream(sa);
         OutputStream bos=new UnsyncBufferedOutputStream(so);
         si.signInOctectStream(bos);
         try {
			bos.close();
		} catch (IOException e) {
			//Imposible
		}



I don't see a clean fix.  Perhaps ideally the SignatureAlgorithm class would
expose a method that could be called from the exception catch block and which
caused the cached algorithm -> key mapping in the keysVerify Map to be removed
or the key reference set to null.  This would ensure that
SignatureAlgorithmSpi#engineVerifyInit would be called in initVerify(Key) on the
next verification, regardless of what the most recently used key was.

An ugly workaround is to ensure that SignatureAlgorithm#verify(byte[]) is always
called.  For example, this "fixes" the problem in this test case by verifying
some dummy bytes before rethrowing the exception:

         //retrieve the byte[] from the stored signature
         byte sigBytes[] = null;
         try {
        	 sigBytes = this.getSignatureValue();
         } catch (XMLSignatureException e) {
        	 sa.verify("dummy-data".getBytes());
        	 throw new XMLSignatureException("empty", e);
         }


Also, I haven't looked at it in detail, but I would think that the signing side
of things might have a similar bug, since it essentially uses the same
optimizations in SignatureAlgorithm as to caching java.security.Signature
instances and conditional re-initialization of those based on the most recently
used Key.

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

Mime
View raw message