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 majordomo@openssl.org