On 28. 11. 2010 17:24, Matej Kurpel wrote:
On 26. 11. 2010 22:20, ryan-mozdevtechcry...@sleevi.com wrote:
-----Original Message-----
Sent: Friday, November 26, 2010 3:16 PM
To: mozilla's crypto code discussion list
Subject: Certificate login in Firefox - how does it work?
Hello,
I am developing a PKCS#11 module and currently I am having problems
getting the certificate login working in Firefox.
I load a page, click on login button and then Firefox starts
communicating with my PKCS#11 module (the page wants its users to log
in using their certificates). It lets me select a certificate from a
list - well, I only have one so I select it and continue. Then, after
some more communication, C_Sign is performed. However, this fails
because I have no way of dealing with the data Firefox sends to my
PKCS#11 module (the data to sign using the C_Sign function).
Signing works properly in Thunderbird since it sends DER-encoded data
(hash algorithm OID and the hash itself) and dealing with that is
fairly straightforward.
However, Firefox sends some seemingly-random 36-byte data. If I use the
same algorithm as for Thunderbird (doesn't matter if SHA1 or MD5), the
page fails to load and says "ssl_error_decrypt_error_alert". I don't
know what should my PKCS#11 module provide for the page to accept it
correctly and continue.
Just FYI, there is a C# .NET program on the other end and trying
SignData or SignHash to compute the value to return proved
unsuccessful.
Please, could anybody enlighten this issue to me?
Please see the TLS 1.0 RFC, Section 7.4.8. Certificate Verify [1] (or
later, but TLS 1.0 is appropriate for the current release of NSS)
The handshake of a TLS 1.0 client using an RSA key is the
concatenation of the SHA-1 and MD-5 hashes of the handshake messages
exchanged since the Client Hello. If you're mapping this to CryptoAPI
types (since you mentioned C#, I'm presuming some Windows& CryptoAPI
familiarity), this is CALG_SSL3_SHAMD5 [2]. The 36 bytes comes from
the size of MD5 (16 bytes) and SHA-1 (20 bytes). For other key types
(eg: DSA, ECC), and depending on whether you're acting as a server or
a client, the signature data may differ, see the appropriate RFCs
(ie: [3])
The actual call is made as part of ssl3_SignHashes, assuming you're
using SSL 3.0/TLS 1.0. If you're using SSL 2.0, you've got more
problems than hash signing. The implementation of this method is at [4].
I don't know what the page is actually using (I don't have it under
my control). How can I determine it?
While I've not spent time hacking with PCKS#11, my understanding is
that the C_Sign function should be treating the input as raw/opaque,
dictated by the mechanism that was used to initialize. If you're
relying on the input being in a particular format, you need to ensure
that format is specified in the underlying PKCS#11 specification for
that mechanism, otherwise it sounds like you're making assumptions
that shouldn't be made.
This assumption is made by NSS and not by me. When signing e-mail in
Thunderbird, it sends DigestInfo (with DER-encoded OID and Hash
value), and when performing a SSL login, it sends raw data. The
mechanism used is always CKM_RSA_PKCS. I don't have a bulletproof way
to determine which of these two cases it is.
For SSL/TLS signatures, and for RSA keys, the mechanism passed is
CKM_RSA_PKCS [5]. According to the PKCS#11 specification, this
mechanism corresponds to computing the raw RSA signature over data,
*excluding* computing the message digest or DigestInfo structure [6].
In CryptoAPI terms, this is the option CRYPT_NOHASHOID [7]. For what
it's worth, I'm not aware of this flag being exposed by the .NET
implementation, eg:
System.Security.Cryptography.RSACryptoServiceProvider's SignHash.
You'll likely need to do some marshalling to the native APIs if
you're using C#.
Yes, I think so too. But I am not familiar with WinAPI and the source
codes in MSDN look really terrible. Also I don't use CryptoAPI, I
manage my certificates and keys myself in my C# .NET program and use
RSACryptoServiceProvider for the cryptographic operations. So I have
access to raw key and certificate data, I don't want to mess with all
the CryptoAPI things.
I think it would involve more than just marshalling, I would have to
make my own C++ dll file which would perform such operations and then
marshal data between it and my C# program. I have tried it before with
something else and it didn't work as expected...
The second thing is that the C# .NET program I am talking about is
actually .NET CF program which is run on a Windows Mobile system. The
.NET CF framework is somewhat crippled of some features so I really
don't know if the API functions described in MSDN are available.
And to save you a bit of trouble/pain: for CryptoAPI, you cannot
simply sign raw data - you can only sign previously hashed data. I
understand this to mean that you cannot write a pure PKCS#11 ->
CryptoAPI mapper, whether .NET or at the raw Win32 level, because the
CryptoAPI specifically forbids signing raw data of arbitrary length,
while PKCS#11 permits it [7]. Your best bet, and a common approach
for the specific case of TLS client authentication, is to combine
CryptCreateHash/CryptSetHashParam(HP_HASHVAL)/CryptSignHash.
Discussing that solution is veering off the topic from this list, but
with that above information and some targeted searching, you should
find a number of discussions on this approach.
I have found [1] and what I understand, I cannot sign raw data with
CryptoAPI as well since it doesn't know the "hash algorithm" the hash
was created with. Well, there was no hash algorithm, and it's no hash,
it's just raw data. I am really at loss now.
However, thank you all very much for your responses, it's really
appreciated. Any more ideas?
Hope that helps.
[1]http://www.ietf.org/rfc/rfc2246.txt
[2]http://msdn.microsoft.com/en-us/library/aa379865(VS.85).aspx
[3]http://www.ietf.org/rfc/rfc4492.txt
[4]http://mxr.mozilla.org/security/source/security/nss/lib/ssl/ssl3con.c#845
[5]http://mxr.mozilla.org/security/source/security/nss/lib/pk11wrap/pk11mech.c#1859
[6]ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf
, Section 12.1.6.
[7]http://msdn.microsoft.com/en-us/library/aa380280(VS.85).aspx
[1] http://www.ureader.com/msg/16592392.aspx
Woohooo, never mind, it works! I followed one MSDN page [1].
Found a class for marshalling on the internet [2] which needed some
customization but most of the things were there. Now I am able to login
using my certificate, it's beautiful :)
Thanks again for everyone's help.
M. Kurpel
[1] http://msdn.microsoft.com/en-us/library/aa379865%28VS.85%29.aspx
[2]
http://blogs.msdn.com/b/alejacma/archive/2007/11/23/p-invoking-cryptoapi-in-net-c-version.aspx
--
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto