I also reported this problem to Bouncy Castle. David Hook has investigated and come up with what sounds like the same conclusion:

On 09/07/2008, at 7:25 PM, David Hook wrote:

I'm guessing that one of the certificates in the chain is actually
fetched from another PKCS12 file. What's happening is that for some
reason the svn parser seems to think that if it finds a particular
attribute on a certificate it should find a private key for it as well.
I've no idea why they have done it this way, however it is something
I've been able to fix on our end - the attribute is meaningless in that context (as far as I know...) so I have changed the store to remove it.


This solves the problem for me, but still it would be best to make PKCS12_parse() more robust.

Cheers,
Paul.

On 10/07/2008, at 1:14 AM, Joe Orton wrote:

On Tue, Jul 08, 2008 at 12:03:15PM +1000, Paul Cuthbert wrote:
Subversion 1.5.0 (and probably earlier) is unable to handle client
PKCS#12 files that are generated using the Bouncy Castle cryptographic
toolkit (Java version 139, see
http://www.bouncycastle.org/latest_releases.html). These P12 files can
be handled fine by Microsoft CAPI, Firefox and OS-X Keychain.
...
An example P12 file is attached, with certificate.  The password is
'password'. To reproduce this issue, use this P12 to try and access any
svn repository with client SSL enabled.  You do not need to set up CA
certificates, etc. because the issue occurs when svn tries to parse the
P12.

I think this is a bug in OpenSSL's PKCS12_parse().  Paul's cert is
attached and has a private key, a client cert, and a CA cert.
PKCS12_parse() is returning the private key and the CA cert as the
supposedly-matching client cert.

For the three times parse_bag is invoked, the parameters are set like
this on entry:

1. keymatch = 0, *keyid = NULL
2. keymatch = MATCH_KEY, *keyid = KeyID for keypair,
3. keymatch = MATCH_ALL, *keyid = KeyID for keypair

The third invocation is for the bag containing the CA cert; the real
keypair have already been found and set up as *pkey and *cert at this
point.  The CA cert and has a different KeyID to the real keypair, as
you'd expect.  The expression:

       if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) {

evaluates to false, so lkey stays non-NULL, and the code falls through
to then pass back the CA cert as *cert rather than pushing it onto the
*ca stack.

e.g. the patch below fixes it for me.  I can't see how this code would
cope correctly with a PKCS#12 file if the bag order was, e.g.

CA cert
EE cert
EE key

even if the keyID's were set appropriately. I think a correct algorithm
would be to iterate through and find the pkey, then iterate again
looking for the matching cert and collecting any non-matching certs in
the CA stack.

--- p12_kiss.c~ 2005-05-11 04:45:31.000000000 +0100
+++ p12_kiss.c  2008-07-09 16:01:18.000000000 +0100
@@ -273,7 +273,7 @@
                }


-               if (lkey) {
+               if ((*keymatch & MATCH_CERT) == 0) {
                        *keymatch |= MATCH_CERT;
                        if (cert) *cert = x509;
                        else X509_free(x509);

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to