We are currently implementing file time stamping for our invoices and we are using a time stamping service that implements RFC3161, Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP), over HTTP.
Three days ago I started looking at the openssl as a possible solution for a TSP client. It wasn't a smooth ride, not by a long shot. First, by default, openssl doesn't include support for time stamping, and you have to compile it from sources with a TS patch applied. But the last patch was for version 0.9.8c and it is almost 3 years old. So, I downloaded, 0.9.8c sources, patched them, compiled them, and then I was able to use openssl ts to generate a sign request. But when I tried to use tsget to send the request to the time stamping service, all hell broke loose. First, I tried to run it, and I received a lot of errors like: Bareword "CURLOPT_VERBOSE" not allowed while "strict subs" in use at ./tsget line 43. Bareword "CURLOPT_FAILONERROR" not allowed while "strict subs" in use at ./tsget line 44. Bareword "CURLOPT_USERAGENT" not allowed while "strict subs" in use at ./tsget line 45. Bareword "CURLOPT_UPLOAD" not allowed while "strict subs" in use at ./tsget line 48. So I had to remove the "use strict;" line from the script. I tried again, but I received this error: Undefined subroutine &WWW::Curl::easy::new called at ./tsget line 39. The problem is that it should use WWW::Curl::Easy, not WWW::Curl::easy. So I had to replace easy with Easy everywhere in the file. After trying again, I received this error: /root/test.tsq: fatal error: could not get timestamp, http code: 400, curl code: 22 (The requested URL returned error: 400) After using tcpdump and Wireshark to figure out what was wrong, I found out that curl has the questionable habit of using "Expect: 100-continue" headers in the HTTP post requests, a header that is not implemented, or not implemented properly by many HTTP servers. So I had to disable the 100-continue header by adding an empty "Expect: " header, like this: $curl->setopt(CURLOPT_HTTPHEADER, ["Content-Type: application/timestamp-query", "Accept: application/timestamp-reply", "Expect: "]); Finally, I was able to get a response from the TS server. Now, all that was left was to validate the response against the certificate of the TS service. However, it didn't work, I received this error trying to validate it: Verification: FAILED 12855:error:2107C080:PKCS7 routines:PKCS7_get0_signers:signer certificate not found:pk7_smime.c:365: I googled it, all I could found were some references to UTF-8 in the certificate, but it didn't seem to be the case for me. Then I tried to use gdb (and I really hate command line debuggers), to determine what was wrong. But by default openssl is not compiled with debugging symbols so I had to recompile it. But I couldn't find how to compile it with debugging support. ./config --help doesn't tell you what the options mean, and anyway the -d option was not documented. I found it in the INSTALL file. But it didn't work: Operating system: x86_64-whatever-linux2 This system (debug-linux-x86_64) is not supported. See file INSTALL for details. But I just came from the INSTALL file, and it only said: On some systems, you can include debugging information as follows: $ ./config -d [options] But it didn't tell me how can I include debugging information on OTHER systems. After googling about an hour, I found another not documented option: -g . This worked. But only with gdb, I wasn't able to find what is going on. Then I tried to use emacs as a front-end to GDB, but the GDB-UI didn't work properly. Then I tried download and compile a more recent version of emacs, but it refused to compile on my system. Then I installed Eclipse to use it as a debugger. After a few hours of tweaking Eclipse settings, I was able to set breakpoints and do step by step execution through the PKCS7_get0_signers function. I wasn't able to find much either. The debugger jumped like crazy up and down when during step by step execution, and it didn't display the values of some variables, but apparently the function is called with the p7 parameter referencing a object, the certs parameter is null, and the flags set to 0. Then X509_find_by_issuer_and_serial (p7->d.sign->cert, ias->issuer, ias->serial) returns null, causing the error. I was starting to think that there is a problem with the certificate even though MS Windows thinks the certificate is OK after adding it to the "Trusted Root Certification Authorities", so I tried to validate it with openssl verify, and I received this errors: /root/tsa.cer: /CN=certSIGN Test TimeStamping Authority error 32 at 0 depth lookup:key usage does not include certificate signing /CN=certSIGN Test TimeStamping Authority error 32 at 0 depth lookup:key usage does not include certificate signing /CN=certSIGN Test TimeStamping Authority error 32 at 0 depth lookup:key usage does not include certificate signing /CN=certSIGN Test TimeStamping Authority error 32 at 0 depth lookup:key usage does not include certificate signing /CN=certSIGN Test TimeStamping Authority error 20 at 0 depth lookup:unable to get local issuer certificate It seems self signed certificates having only timestamp purpose cannot be verified, because they don't' have certificate signing purpose. Because then I tried to validate a root VeriSign certificate that came with MS Windows, and can be used for "All" purposes, and it validated OK. [Later Edit] Now we received a new certificate for the time stamping service, complete with a trust chain, and it validated OK, so it appears the problem only occurs for self signed certificates having only timestamp purpose. Thanks, Vladimir Nicolici Application Development Manager Telemobil SA Splaiul Independentei Nr. 319, Sector 6, 060044 Bucuresti, Romania Mobil: +40 78 810 10 08 Tel: +40 21 402 33 33 Fax: +40 21 402 32 02 Website: www.zapp.ro <http://www.zapp.ro/> Daca nu este neaparata nevoie, nu da print acestui mail! Sustine www.copaculdehartie.ro <http://www.copaculdehartie.ro>
<<image001.gif>>