Re: Certificate login in Firefox - how does it work?
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
Re: Certificate login in Firefox - how does it work?
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
RE: Certificate login in Firefox - how does it work?
-Original Message- From: dev-tech-crypto-bounces+ryan- mozdevtechcrypto=sleevi@lists.mozilla.org [mailto:dev-tech-crypto- bounces+ryan-mozdevtechcrypto=sleevi@lists.mozilla.org] On Behalf Of Matej Kurpel Sent: Sunday, November 28, 2010 11:24 AM To: mozilla's crypto code discussion list Subject: Re: Certificate login in Firefox - how does it work? [snip] On 26. 11. 2010 22:20, ryan-mozdevtechcry...@sleevi.com wrote: 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. What I meant to say is that your attempt to interpret the data being sent in is an assumption: that the data is meaningful. According to the PKCS#11 specification, you are just supposed to sign the data as provided, provided it meets the constraints inposed (l = k-11). You're correct that, in the case of Thunderbird, it will send a full DigestInfo structure to be signed [1], while in the case of TLS client auth, it only sends the hashes [2]. In an ideal world, your PKCS#11 module should not ascribe any meaning to that data. Please consider reviewing the PKCS#11 specification again [3]. For CKM_RSA_PKCS, it reads This mechanism corresponds only to the part of PKCS #1 v1.5 that involves RSA; it does not compute a message digest or a DigestInfo encoding as specified for the md2withRSAEncryption and md5withRSAEncryption algorithms in PKCS #1 v1.5 . The actual specification for PKCS #1 v1.5 is at [4]. Section 10.1 details how signatures are computed, and includes this: The signature process consists of four steps: message digesting, data encoding, RSA encryption, and octet-string-to-bit-string conversion. When combined with what the PKCS#11 specification says for how the CKM_RSA_PKCS method behaves, it becomes clear that the mechanism should only apply the last two steps: RSA encryption, and octet-string-to-bit-string conversion. The PKCS #1 v1.5 specification details the RSA encryption portion of signatures in section 10.1.3, which states that it should be computed using the behaviour described in Section 8.1 with a block type of 01 and a private key as described in Section 7. Ignoring the private key format as unrelated to this discussion, Section 8.1 describes the Encryption behaviour. While not intending to quote the whole thing, the format is described as: A block type BT, a padding string PS, and the data D shall be formatted into an octet string EB, the encryption block. EB = 00 || BT || PS || 00 || D . (1) Putting it all together, when PK11_Sign/C_Sign is called with CKM_RSA_PKCS, what you are provided as input is D. It may be a DigestInfo, where the caller has computed the hash of the original message M, and then encoded both it and the hash mechanism OID into the structure, as Thunderbird does and as specified by PKCS #7. But it may also be a bare hash, as described in TLS v1.0, where the DigestInfo is omitted and D is the concatenation of both the MD5 and SHA-1 hashes. Or it may be neither - simply raw data that should be encrypted, perhaps by using some new method that accommodates some weakness in the PKCS #1 v1.5 encryption/signature method. [5] In terms of conceptualizing the relationship between PKCS#11's CKM_RSA_PKCS and the PKCS #1 v1.5 specification, PK11_Sign is better thought of as PK11_Encrypt - the behaviour of the mechanism is specified by Section 8.1, Encryption, rather than Section 10.1, Signatures. As I mentioned, CryptoAPI does not expose this raw functionality - it only allows encryption of previously computed hashes, and it will compute the DigestInfo for you before encrypting. However, as I mentioned, you can suppress the computing the DigestInfo by passing CRYPT_NOHASHOID. Further, you can import the hash, generated via NSS, into CryptoAPI, by using CALG_SSL3_SHAMD5 and using CryptSetHashParam(HP_HASHVAL). This works because your input data, D, is 36 bytes, the same length as CALG_SSL3_SHAMD5, and presumably the CSP allows you to set HP_HASHVAL. The net result of this is the behaviour you desire. The reason why this is important is that lets say another application wishes to use your PKCS #11 module. Rather than implementing PKCS #7 or TLS 1.0, it implements the vendor-specific Sleevinet protocol (The future of the Intertubes). The Frooble message of the