I knew this question was too hard for F5 support team, so in my first email I said
If it is not a known issue on VE BIGIP-11.3.0.2806.0, can you please ask your technical team to have a look?
I also knew there was no fast track for me to the right person in F5, the only thing I could do was WAIT and PROVIDE any data which they thought was necessary.
In the beginning, they doubted that the idp certificate registered on F5 Big-IP (by importing IDP metadata) was not right. I told them the SAML response contained a X509 certificate which was enough to verify the signature, but I agreed to check the idp certificate, actually it was identical to the X509 certificate.
Finally I got the feedback from their Engineering Service
47 days later. Typical bureaucratic in any big company I am afraid.
The feedback says,
------
Product Development has provided the way SAML Digest
value is calculated by APM;
- if reference URI in the signature element matches the
Response ID, then digest is calculated for the entire SAML response (signature
must be within response),
- if reference URI matches Assertion ID, digest is
calculated for the Assertion element only (signature must be within assertion),
- entire signature element is removed from
response/assertion,
- resulting XML is canonicalized,
- SHA1 digest is calculated for the canonicalized XML,
- the Digest value from signature element is base64
decoded and compared to calculated digest.
In your case,the "reference URI" in signature
element matches the Response ID
"_ec3a47ec7dd9e6836d3458bec3124c61b49d89fd", so the digest is
calculated for the entire SAML response.
------
Note: the data with Response ID _ec3a47ec7dd9e6836d3458bec3124c61b49d89fd was collected on 2013-04-17. It is different from the one I am going to test.
Sounds like they are not yet convinced by my research described in
Part 1. They may also question me back - how can I myself prove that my research in
Part 1 did the verification on Reference(s)?
The SAML module on F5 Big-IP was developed with C (or C++, I believe), so this time I am going to use
Apache Santuario C++ distribution.
I downloaded
Apache XML Security for C++ 1.7.0 source code onto Ubuntu 12.04, then followed its installation instruction,
untar, configure, make, make install etc.
The package has a tool called "
checksig", After building the package, we can make use of the tool straight away.
mike@ubuntu:/opt/bin$ ./checksig ~/saml02.xml
Signature verified OK!
Again, no complaint for digest value mismatch.
Now let check its source code. In checksig.cpp, around line 503, it has
if (skipRefs)
result = sig->verifySignatureOnly();
else
result = sig->verify();
Note I didn't add the option --skiprefs, which implied it verified the References as well.
Now, let us check sig->verify(), the source code is in DSIGSignature.cpp, line 1151
// First thing to do is check the references
referenceCheckResult = mp_signedInfo ->verify(m_errStr);
Let us step into this function DSIGSignedInfo::verify, we get the function SIGReference::verifyReferenceList in DSIGReference.cpp. On line 920, we have
Step into once more, we get DSIGReference::checkHash() .
Now let us debug it with gdb, set a breakpoint on this function
(gdb) break DSIGReference::checkHash
Then run it, the program break at this point. go 3 steps with n3. Now let check the values in buffer calculatedHashVal and readHashVal.
(gdb) x/20bx calculatedHashVal
0xbfffc39c: 0xc0 0x35 0xd4 0xef 0x92 0x98 0xe3 0xfc
0xbfffc3a4: 0xbb 0x27 0xbd 0x5c 0x9d 0xa2 0xeb 0xfd
0xbfffc3ac: 0xb1 0x7d 0xa0 0x30
(gdb) x/20bx readHashVal
0xbfffc41c: 0xc0 0x35 0xd4 0xef 0x92 0x98 0xe3 0xfc
0xbfffc424: 0xbb 0x27 0xbd 0x5c 0x9d 0xa2 0xeb 0xfd
0xbfffc42c: 0xb1 0x7d 0xa0 0x30
They are identical! OK, now let's check the DigestValue
wDXU75KY4/y7J71cnaLr/bF9oDA=
After doing Base64 decode, we have
c0 35 d4 ef 92 98 e3 fc bb 27 bd 5c 9d a2 eb fd b1 7d a0 30
Still have a question? I know you may want to know the actual XML content where the hash is calculated on. OK, no problem. The hash is done in TXFMSHA1.cpp, line 131,
while ((size = input->readBytes((XMLByte *) buffer, 1024)) != 0) {
#if 0
// Some useful debbugging code
FILE * f = fopen("debug.out","a+b");
fwrite(buffer, size, 1, f);
fclose(f);
#endif
mp_h->hash(buffer, size);
}
We can dump the buffer to a file (I did it by gdb append command). You can see the content in
hashon.xml. This is the canonicalized XML.
Now I wonder if F5 Big-IP has the same handling on XML signature.