[gnutls-dev] [gnutls-cvs PATCH] Fix handling of PKCS#12 and contents without apassphrase

Anton Altaparmakov aia21 at cam.ac.uk
Tue Sep 27 11:34:25 CEST 2005


Hi,

Gnutls has bugs when handling PKCS#12 files and their contents when 
they do not have a passphrase.

OpenSSL's "openssl pkcs12" utility worked fine to load and dump those 
PKCS#12 files which made me look into the gnutls source code and I managed 
to find out what was going on after a log of debugging.  For example 
gnutls didn't allow a 0 MPI which is perfectly valid.  Also it had no 
concept of empty passwords (it assumed password = NULL means not encrypted 
which is wrong) and finally it did not understand the difference between 
password = NULL and password = "".

The below patch fixes all the above problems.  It is against the current 
gnutls cvs (generated using "cvs diff").  Please apply.

Let me know if you need more info about anything...

Without this patch ntfsdecrypt (from linux-ntfs project, ntfsprogs cvs) 
cannot load PKCS#12 files generated by Windows when the user generating 
them used an empty passphrase.  With the patch both older style and newer 
style PKCS#12 files can be loaded.  (The difference between the two is 
that one uses password = NULL and the other password = "".  It switched 
between Windows XP SP1 and SP2 IIRC or it might have been between XP and 
XP SP1, doesn't really matter as I have example PKCS#12 files I always 
use for testing...)

Best regards,

	Anton
-- 
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/ & http://www-stu.christs.cam.ac.uk/~aia21/

Index: lib/gnutls_mpi.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_mpi.c,v
retrieving revision 2.31
diff -u -p -r2.31 gnutls_mpi.c
--- lib/gnutls_mpi.c	26 May 2005 15:27:14 -0000	2.31
+++ lib/gnutls_mpi.c	27 Sep 2005 09:03:56 -0000
@@ -53,13 +53,6 @@ int _gnutls_mpi_scan(mpi_t * ret_mpi, co
     if (ret)
 	return GNUTLS_E_MPI_SCAN_FAILED;
 
-    /* MPIs with 0 bits are illegal
-     */
-    if (_gnutls_mpi_get_nbits(*ret_mpi) == 0) {
-	_gnutls_mpi_release(ret_mpi);
-	return GNUTLS_E_MPI_SCAN_FAILED;
-    }
-
     return 0;
 }
 
Index: lib/x509/pkcs12.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/x509/pkcs12.c,v
retrieving revision 1.39
diff -u -p -r1.39 pkcs12.c
--- lib/x509/pkcs12.c	30 Aug 2005 10:46:08 -0000	1.39
+++ lib/x509/pkcs12.c	27 Sep 2005 09:03:56 -0000
@@ -940,7 +940,7 @@ int gnutls_pkcs12_verify_mac(gnutls_pkcs
     opaque sha_mac[20];
     opaque sha_mac_orig[20];
 
-    if (pkcs12 == NULL || pass == NULL) {
+    if (pkcs12 == NULL) {
 	gnutls_assert();
 	return GNUTLS_E_INVALID_REQUEST;
     }
Index: lib/x509/pkcs12_encr.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/x509/pkcs12_encr.c,v
retrieving revision 1.21
diff -u -p -r1.21 pkcs12_encr.c
--- lib/x509/pkcs12_encr.c	26 May 2005 15:27:24 -0000	1.21
+++ lib/x509/pkcs12_encr.c	27 Sep 2005 09:03:56 -0000
@@ -87,13 +87,15 @@ _pkcs12_string_to_key(unsigned int id, c
     p = buf_i;
     for (i = 0; i < 64; i++)
 	*p++ = salt[i % salt_size];
-    for (i = j = 0; i < 64; i += 2) {
-	*p++ = 0;
-	*p++ = pw[j];
-	if (++j > pwlen)	/* Note, that we include the trailing zero */
-	    j = 0;
-    }
-
+    if (pw) {
+	for (i = j = 0; i < 64; i += 2) {
+	   *p++ = 0;
+	   *p++ = pw[j];
+	   if (++j > pwlen)	/* Note, that we include the trailing zero */
+	       j = 0;
+	}
+    } else
+	memset(p, 0, 64);
     for (;;) {
 	rc = gc_hash_open(GC_SHA1, 0, &md);
 	if (rc) {
@@ -104,7 +106,7 @@ _pkcs12_string_to_key(unsigned int id, c
 	    unsigned char lid = id & 0xFF;
 	    gc_hash_write(md, 1, &lid);
 	}
-	gc_hash_write(md, 128, buf_i);
+	gc_hash_write(md, pw ? 128 : 64, buf_i);
 	memcpy(hash, gc_hash_read(md), 20);
 	gc_hash_close(md);
 	for (i = 1; i < iter; i++)
Index: lib/x509/privkey_pkcs8.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/x509/privkey_pkcs8.c,v
retrieving revision 1.49
diff -u -p -r1.49 privkey_pkcs8.c
--- lib/x509/privkey_pkcs8.c	30 Aug 2005 10:46:08 -0000	1.49
+++ lib/x509/privkey_pkcs8.c	27 Sep 2005 09:03:56 -0000
@@ -810,7 +810,7 @@ int decode_private_key_info(const gnutls
   * @data: The DER or PEM encoded key.
   * @format: One of DER or PEM
   * @password: the password to decrypt the key (if it is encrypted).
-  * @flags: use 0.
+  * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted.
   *
   * This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key
   * to the native gnutls_x509_privkey_t format. The output will be stored in @key.
@@ -880,7 +880,7 @@ int gnutls_x509_privkey_import_pkcs8(gnu
 	need_free = 1;
     }
 
-    if (flags & GNUTLS_PKCS_PLAIN || password == NULL) {
+    if (flags & GNUTLS_PKCS_PLAIN) {
 	result = decode_private_key_info(&_data, key, &key->key);
     } else {			/* encrypted. */
 	result = decode_pkcs8_key(&_data, password, key, &key->key);



More information about the Gnutls-dev mailing list