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

Nikos Mavrogiannopoulos nmav at gnutls.org
Tue Sep 27 16:05:05 CEST 2005


On Tuesday 27 September 2005 11:34, Anton Altaparmakov wrote:
> 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.

Hello Anton,
 Thank you for the patch. I've changed some things since some parts of gnutls 
rely on this property of mpi_scan(). If the attached patch works for you I'll 
apply it to the cvs.

-- 
Nikos Mavrogiannopoulos
-------------- next part --------------
Index: lib/auth_dh_common.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/auth_dh_common.c,v
retrieving revision 2.16
diff -u -r2.16 auth_dh_common.c
--- lib/auth_dh_common.c	26 May 2005 15:27:13 -0000	2.16
+++ lib/auth_dh_common.c	27 Sep 2005 14:00:07 -0000
@@ -64,7 +64,7 @@
     _n_Y = n_Y;
 
     DECR_LEN(data_size, n_Y);
-    if (_gnutls_mpi_scan(&session->key->client_Y, &data[2], &_n_Y)) {
+    if (_gnutls_mpi_scan_nz(&session->key->client_Y, &data[2], &_n_Y)) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -204,16 +204,16 @@
     _n_g = n_g;
     _n_p = n_p;
 
-    if (_gnutls_mpi_scan(&session->key->client_Y, data_Y, &_n_Y) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->client_Y, data_Y, &_n_Y) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&session->key->client_g, data_g, &_n_g) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->client_g, data_g, &_n_g) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
-    if (_gnutls_mpi_scan(&session->key->client_p, data_p, &_n_p) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->client_p, data_p, &_n_p) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
Index: lib/auth_rsa_export.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/auth_rsa_export.c,v
retrieving revision 2.39
diff -u -r2.39 auth_rsa_export.c
--- lib/auth_rsa_export.c	30 Aug 2005 10:48:35 -0000	2.39
+++ lib/auth_rsa_export.c	27 Sep 2005 14:00:08 -0000
@@ -259,12 +259,12 @@
     _n_e = n_e;
     _n_m = n_m;
 
-    if (_gnutls_mpi_scan(&session->key->rsa[0], data_m, &_n_m) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->rsa[0], data_m, &_n_m) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&session->key->rsa[1], data_e, &_n_e) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->rsa[1], data_e, &_n_e) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
Index: lib/auth_srp.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/auth_srp.c,v
retrieving revision 2.7
diff -u -r2.7 auth_srp.c
--- lib/auth_srp.c	27 May 2005 01:43:57 -0000	2.7
+++ lib/auth_srp.c	27 Sep 2005 14:00:08 -0000
@@ -162,19 +162,19 @@
     }
 
     /* copy from pwd_entry to local variables (actually in session) */
-    if (_gnutls_mpi_scan(&G, pwd_entry->g.data, &pwd_entry->g.size) < 0) {
+    if (_gnutls_mpi_scan_nz(&G, pwd_entry->g.data, &pwd_entry->g.size) < 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     tmp_size = pwd_entry->n.size;
-    if (_gnutls_mpi_scan(&N, pwd_entry->n.data, &tmp_size) < 0) {
+    if (_gnutls_mpi_scan_nz(&N, pwd_entry->n.data, &tmp_size) < 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     tmp_size = pwd_entry->v.size;
-    if (_gnutls_mpi_scan(&V, pwd_entry->v.data, &tmp_size) < 0) {
+    if (_gnutls_mpi_scan_nz(&V, pwd_entry->v.data, &tmp_size) < 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -356,7 +356,7 @@
     _n_A = _gnutls_read_uint16(&data[0]);
 
     DECR_LEN(data_size, _n_A);
-    if (_gnutls_mpi_scan(&A, &data[2], &_n_A) || A == NULL) {
+    if (_gnutls_mpi_scan_nz(&A, &data[2], &_n_A) || A == NULL) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -725,17 +725,17 @@
     _n_n = n_n;
     _n_b = n_b;
 
-    if (_gnutls_mpi_scan(&N, data_n, &_n_n) != 0) {
+    if (_gnutls_mpi_scan_nz(&N, data_n, &_n_n) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&G, data_g, &_n_g) != 0) {
+    if (_gnutls_mpi_scan_nz(&G, data_g, &_n_g) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&B, data_b, &_n_b) != 0) {
+    if (_gnutls_mpi_scan_nz(&B, data_b, &_n_b) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -771,7 +771,7 @@
 	return ret;
     }
 
-    if (_gnutls_mpi_scan(&session->key->x, hd, &_n_g) != 0) {
+    if (_gnutls_mpi_scan_nz(&session->key->x, hd, &_n_g) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
Index: lib/gnutls_dh_primes.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_dh_primes.c,v
retrieving revision 2.64
diff -u -r2.64 gnutls_dh_primes.c
--- lib/gnutls_dh_primes.c	26 May 2005 15:27:14 -0000	2.64
+++ lib/gnutls_dh_primes.c	27 Sep 2005 14:00:08 -0000
@@ -148,13 +148,13 @@
     size_t siz;
 
     siz = prime->size;
-    if (_gnutls_mpi_scan(&tmp_prime, prime->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&tmp_prime, prime->data, &siz)) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = generator->size;
-    if (_gnutls_mpi_scan(&tmp_g, generator->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&tmp_g, generator->data, &siz)) {
 	_gnutls_mpi_release(&tmp_prime);
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
Index: lib/gnutls_mpi.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_mpi.c,v
retrieving revision 2.31
diff -u -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 14:00:08 -0000
@@ -53,6 +53,20 @@
     if (ret)
 	return GNUTLS_E_MPI_SCAN_FAILED;
 
+    return 0;
+}
+
+/* returns zero on success. Fails if the number is zero.
+ */
+int _gnutls_mpi_scan_nz(mpi_t * ret_mpi, const opaque * buffer,
+		     size_t * nbytes)
+{
+    int ret;
+
+    ret = gcry_mpi_scan(ret_mpi, GCRYMPI_FMT_USG, buffer, *nbytes, nbytes);
+    if (ret)
+	return GNUTLS_E_MPI_SCAN_FAILED;
+
     /* MPIs with 0 bits are illegal
      */
     if (_gnutls_mpi_get_nbits(*ret_mpi) == 0) {
Index: lib/gnutls_mpi.h
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_mpi.h,v
retrieving revision 2.31
diff -u -r2.31 gnutls_mpi.h
--- lib/gnutls_mpi.h	26 May 2005 15:27:14 -0000	2.31
+++ lib/gnutls_mpi.h	27 Sep 2005 14:00:08 -0000
@@ -61,6 +61,8 @@
 
 void _gnutls_mpi_release(mpi_t * x);
 
+int _gnutls_mpi_scan_nz(mpi_t * ret_mpi, const opaque * buffer,
+		     size_t * nbytes);
 int _gnutls_mpi_scan(mpi_t * ret_mpi, const opaque * buffer,
 		     size_t * nbytes);
 int _gnutls_mpi_scan_pgp(mpi_t * ret_mpi, const opaque * buffer,
Index: lib/gnutls_pk.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_pk.c,v
retrieving revision 1.78
diff -u -r1.78 gnutls_pk.c
--- lib/gnutls_pk.c	30 Aug 2005 10:48:35 -0000	1.78
+++ lib/gnutls_pk.c	27 Sep 2005 14:00:08 -0000
@@ -131,7 +131,7 @@
     ps[psize] = 0;
     memcpy(&ps[psize + 1], plaintext->data, plaintext->size);
 
-    if (_gnutls_mpi_scan(&m, edata, &k) != 0) {
+    if (_gnutls_mpi_scan_nz(&m, edata, &k) != 0) {
 	gnutls_assert();
 	gnutls_afree(edata);
 	return GNUTLS_E_MPI_SCAN_FAILED;
@@ -209,7 +209,7 @@
 	return GNUTLS_E_PK_DECRYPTION_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&c, ciphertext->data, &esize) != 0) {
+    if (_gnutls_mpi_scan_nz(&c, ciphertext->data, &esize) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -395,7 +395,7 @@
 	return GNUTLS_E_PK_SIGN_FAILED;
     }
 
-    if (_gnutls_mpi_scan(&mdata, hash->data, &k) != 0) {
+    if (_gnutls_mpi_scan_nz(&mdata, hash->data, &k) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -490,7 +490,7 @@
     }
 
     k = vdata->size;
-    if (_gnutls_mpi_scan(&mdata, vdata->data, &k) != 0) {
+    if (_gnutls_mpi_scan_nz(&mdata, vdata->data, &k) != 0) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
Index: lib/gnutls_srp.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/gnutls_srp.c,v
retrieving revision 2.51
diff -u -r2.51 gnutls_srp.c
--- lib/gnutls_srp.c	26 May 2005 15:27:14 -0000	2.51
+++ lib/gnutls_srp.c	27 Sep 2005 14:00:08 -0000
@@ -45,7 +45,7 @@
     mpi_t x, e;
     size_t result_size;
 
-    if (_gnutls_mpi_scan(&x, text, &textsize)) {
+    if (_gnutls_mpi_scan_nz(&x, text, &textsize)) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
@@ -195,7 +195,7 @@
     /* convert the bytes of hd to integer
      */
     hash_size = 20;		/* SHA */
-    ret = _gnutls_mpi_scan(&res, hd, &hash_size);
+    ret = _gnutls_mpi_scan_nz(&res, hd, &hash_size);
     gnutls_free(holder);
 
     if (ret < 0) {
@@ -676,13 +676,13 @@
     }
 
     size = prime->size;
-    if (_gnutls_mpi_scan(&_n, prime->data, &size)) {
+    if (_gnutls_mpi_scan_nz(&_n, prime->data, &size)) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     size = generator->size;
-    if (_gnutls_mpi_scan(&_g, generator->data, &size)) {
+    if (_gnutls_mpi_scan_nz(&_g, generator->data, &size)) {
 	gnutls_assert();
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
Index: lib/x509/pkcs12.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/x509/pkcs12.c,v
retrieving revision 1.39
diff -u -r1.39 pkcs12.c
--- lib/x509/pkcs12.c	30 Aug 2005 10:46:08 -0000	1.39
+++ lib/x509/pkcs12.c	27 Sep 2005 14:00:08 -0000
@@ -940,7 +940,7 @@
     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 -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 14:00:08 -0000
@@ -87,12 +87,15 @@
     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);
@@ -104,7 +107,7 @@
 	    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.c
===================================================================
RCS file: /cvs/gnutls/gnutls/lib/x509/privkey.c,v
retrieving revision 1.48
diff -u -r1.48 privkey.c
--- lib/x509/privkey.c	16 Jul 2005 10:48:15 -0000	1.48
+++ lib/x509/privkey.c	27 Sep 2005 14:00:08 -0000
@@ -457,35 +457,35 @@
     }
 
     siz = m->size;
-    if (_gnutls_mpi_scan(&key->params[0], m->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[0], m->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = e->size;
-    if (_gnutls_mpi_scan(&key->params[1], e->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[1], e->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = d->size;
-    if (_gnutls_mpi_scan(&key->params[2], d->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[2], d->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = p->size;
-    if (_gnutls_mpi_scan(&key->params[3], p->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[3], p->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = q->size;
-    if (_gnutls_mpi_scan(&key->params[4], q->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[4], q->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
@@ -504,7 +504,7 @@
     _gnutls_mpi_invm(key->params[5], key->params[3], key->params[4]);
 #else
     siz = u->size;
-    if (_gnutls_mpi_scan(&key->params[5], u->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[5], u->data, &siz)) {
 	gnutls_assert();
 	FREE_RSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
@@ -553,35 +553,35 @@
     }
 
     siz = p->size;
-    if (_gnutls_mpi_scan(&key->params[0], p->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[0], p->data, &siz)) {
 	gnutls_assert();
 	FREE_DSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = q->size;
-    if (_gnutls_mpi_scan(&key->params[1], q->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[1], q->data, &siz)) {
 	gnutls_assert();
 	FREE_DSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = g->size;
-    if (_gnutls_mpi_scan(&key->params[2], g->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[2], g->data, &siz)) {
 	gnutls_assert();
 	FREE_DSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = y->size;
-    if (_gnutls_mpi_scan(&key->params[3], y->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[3], y->data, &siz)) {
 	gnutls_assert();
 	FREE_DSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
     siz = x->size;
-    if (_gnutls_mpi_scan(&key->params[4], x->data, &siz)) {
+    if (_gnutls_mpi_scan_nz(&key->params[4], x->data, &siz)) {
 	gnutls_assert();
 	FREE_DSA_PRIVATE_PARAMS;
 	return GNUTLS_E_MPI_SCAN_FAILED;


More information about the Gnutls-devel mailing list