gnome-keyring r1122 - in trunk: . common pk pkcs11 ssh



Author: nnielsen
Date: Mon Mar 17 01:14:46 2008
New Revision: 1122
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1122&view=rev

Log:
	* common/gkr-crypto.c:
	* common/gkr-crypto.h:
	* pk/gkr-pkcs11-daemon-session.c:
	* pk/gkr-pkcs11-rsa.c:
	* pk/gkr-pkcs11-rsa.h: Move RSA padding functionality into a 
	more accessible location.  

	* common/gkr-buffer.c:
	* common/gkr-buffer.h:
	* pk/gkr-pk-object-manager.c:
	* pk/gkr-pk-object-manager.h:
	* pk/gkr-pk-pubkey.c:
	* ssh/gkr-ssh-daemon-ops.c:
	* ssh/gkr-ssh-private.h:
	* ssh/gkr-ssh-proto.c: Add SSH agent protocol version 1 support.
	Cleanup how session keys are managed. Fixes bug #520860



Modified:
   trunk/   (props changed)
   trunk/ChangeLog
   trunk/common/gkr-buffer.c
   trunk/common/gkr-buffer.h
   trunk/common/gkr-crypto.c
   trunk/common/gkr-crypto.h
   trunk/pk/gkr-pk-object-manager.c
   trunk/pk/gkr-pk-object-manager.h
   trunk/pk/gkr-pk-pubkey.c
   trunk/pkcs11/gkr-pkcs11-daemon-session.c
   trunk/pkcs11/gkr-pkcs11-rsa.c
   trunk/pkcs11/gkr-pkcs11-rsa.h
   trunk/ssh/gkr-ssh-daemon-ops.c
   trunk/ssh/gkr-ssh-private.h
   trunk/ssh/gkr-ssh-proto.c

Modified: trunk/common/gkr-buffer.c
==============================================================================
--- trunk/common/gkr-buffer.c	(original)
+++ trunk/common/gkr-buffer.c	Mon Mar 17 01:14:46 2008
@@ -192,14 +192,14 @@
 	return 1;
 }
 
-int
+unsigned char*
 gkr_buffer_add_empty (GkrBuffer *buffer, size_t len)
 {
+	size_t pos = buffer->len;
 	if (!gkr_buffer_reserve (buffer, buffer->len + len))
-		return 0;
-	
+		return NULL;
 	buffer->len += len;
-	return 1;
+	return buffer->buf + pos;
 }
 
 int 
@@ -240,6 +240,60 @@
 	return 1;
 }
 
+void
+gkr_buffer_encode_uint16 (unsigned char* buf, uint16_t val)
+{
+	buf[0] = (val >> 8) & 0xff;
+	buf[1] = (val >> 0) & 0xff;	
+}
+
+uint16_t
+gkr_buffer_decode_uint16 (unsigned char* buf)
+{
+	uint16_t val = buf[0] << 8 | buf[1];
+	return val;
+}
+
+int
+gkr_buffer_add_uint16 (GkrBuffer *buffer, uint16_t val)
+{
+	if (!gkr_buffer_reserve (buffer, buffer->len + 2))
+		return 0; /* failures already incremented */
+	buffer->len += 2;
+	gkr_buffer_set_uint16 (buffer, buffer->len - 2, val);
+	return 1;	
+}
+
+int
+gkr_buffer_set_uint16 (GkrBuffer *buffer, size_t offset, uint16_t val)
+{
+	unsigned char *ptr;
+	if (buffer->len < 2 || offset > buffer->len - 2) {
+		buffer->failures++;
+		return 0;
+	}
+	ptr = (unsigned char*)buffer->buf + offset;
+	gkr_buffer_encode_uint16 (ptr, val);
+	return 1;
+}
+
+int
+gkr_buffer_get_uint16 (GkrBuffer *buffer, size_t offset,
+                       size_t *next_offset, uint16_t *val)
+{
+	unsigned char *ptr;
+	if (buffer->len < 2 || offset > buffer->len - 2) {
+		buffer->failures++;
+		return 0;
+	}
+	ptr = (unsigned char*)buffer->buf + offset;
+	if (val != NULL)
+		*val = gkr_buffer_decode_uint16 (ptr);
+	if (next_offset != NULL)
+		*next_offset = offset + 2;
+	return 1;	
+}
+
 void 
 gkr_buffer_encode_uint32 (unsigned char* buf, uint32_t val)
 {
@@ -338,18 +392,13 @@
 unsigned char*
 gkr_buffer_add_byte_array_empty (GkrBuffer *buffer, size_t vlen)
 {
-	size_t pos;
 	if (vlen >= 0x7fffffff) {
 		buffer->failures++;
 		return NULL; 
 	}
 	if (!gkr_buffer_add_uint32 (buffer, vlen))
 		return NULL;
-	pos = buffer->len;
-	/* This, as any gkr_buffer_add_* can reallocate */
-	if (!gkr_buffer_add_empty (buffer, vlen))
-		return NULL;
-	return buffer->buf + pos;
+	return gkr_buffer_add_empty (buffer, vlen);
 }
 
 int

Modified: trunk/common/gkr-buffer.h
==============================================================================
--- trunk/common/gkr-buffer.h	(original)
+++ trunk/common/gkr-buffer.h	Mon Mar 17 01:14:46 2008
@@ -102,8 +102,8 @@
 						 const unsigned char *val,
 						 size_t len);
 
-int		gkr_buffer_add_empty	        (GkrBuffer *buffer,
-						 size_t len);
+unsigned char*  gkr_buffer_add_empty            (GkrBuffer *buffer,
+                                                 size_t len);
 
 int 		gkr_buffer_add_byte		(GkrBuffer *buffer,
 						 unsigned char val);
@@ -130,6 +130,23 @@
 						 size_t *next_offset,
 						 uint32_t *val);
 
+void 		gkr_buffer_encode_uint16	(unsigned char* buf, 
+						 uint16_t val);
+
+uint16_t	gkr_buffer_decode_uint16	(unsigned char* buf);
+
+int 		gkr_buffer_add_uint16		(GkrBuffer *buffer,
+						 uint16_t val);
+
+int		gkr_buffer_set_uint16		(GkrBuffer *buffer,
+						 size_t offset, 
+						 uint16_t val);
+
+int		gkr_buffer_get_uint16		(GkrBuffer *buffer,
+						 size_t offset,
+						 size_t *next_offset,
+						 uint16_t *val);
+
 int		gkr_buffer_add_byte_array	(GkrBuffer *buffer,
 						 const unsigned char *val,
 						 size_t len);
@@ -158,8 +175,8 @@
 int             gkr_buffer_get_stringv          (GkrBuffer *buffer,
                                                  size_t offset,
                                                  size_t *next_offset,
-		                                         char ***strv_ret, 
-		                                         GkrBufferAllocator allocator);
+                                                 char ***strv_ret, 
+                                                 GkrBufferAllocator allocator);
 
 int		gkr_buffer_add_uint64		(GkrBuffer *buffer,
 						 uint64_t val);

Modified: trunk/common/gkr-crypto.c
==============================================================================
--- trunk/common/gkr-crypto.c	(original)
+++ trunk/common/gkr-crypto.c	Mon Mar 17 01:14:46 2008
@@ -698,15 +698,78 @@
 	return (*mpi) ? TRUE : FALSE;
 }
 
+static gboolean
+print_mpi_aligned (gcry_mpi_t mpi, guchar *block, gsize n_block)
+{
+	gcry_error_t gcry;
+	gsize offset, len;
+	
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
+	g_return_val_if_fail (gcry == 0, FALSE);
+
+	if (n_block < len)
+		return FALSE;
+	
+	offset = n_block - len;
+	memset (block, 0, offset);
+	
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, block + offset, len, &len, mpi);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	g_return_val_if_fail (len == n_block - offset, FALSE);
+	
+	return TRUE;
+}
+
+guchar*
+gkr_crypto_sexp_extract_mpi_padded (gcry_sexp_t sexp, guint bits, gsize *n_data, 
+                                    GkrCryptoPadding padfunc, ...)
+{
+	gcry_sexp_t at = NULL;
+	gcry_mpi_t mpi;
+	va_list va;
+	guchar *padded, *data;
+	gsize n_padded;
+	
+	g_assert (sexp);
+	g_assert (n_data);
+	g_assert (padfunc);
+	g_assert (bits);
+	
+	va_start (va, padfunc);
+	at = sexp_get_childv (sexp, va);
+	va_end (va);
+	
+	if (!at)
+		return NULL;
+
+	/* Parse out the MPI */
+	mpi = gcry_sexp_nth_mpi (at ? at : sexp, 1, GCRYMPI_FMT_USG);
+	gcry_sexp_release (at);
+	
+	if (!mpi)
+		return NULL;
+	
+	/* Do we need to unpad the data? */
+	n_padded = (bits + 7) / 8;
+	data = NULL;
+	
+	/* Extract it aligned into this buffer */
+	padded = g_malloc0 (n_padded);
+	if (print_mpi_aligned (mpi, padded, n_padded))
+		data = (padfunc) (bits, padded, n_padded, n_data);
+	g_free (padded);
+	
+	gcry_mpi_release (mpi);
+	return data;	
+}
+
 gboolean
 gkr_crypto_sexp_extract_mpi_aligned (gcry_sexp_t sexp, guchar* block, gsize n_block, ...)
 {
 	gcry_sexp_t at = NULL;
-	gcry_error_t gcry;
 	gboolean ret;
 	gcry_mpi_t mpi;
 	va_list va;
-	gsize len;
 	
 	g_assert (sexp);
 	g_assert (block);
@@ -725,27 +788,8 @@
 	
 	if (!mpi)
 		return FALSE;
-	
-	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
-	g_return_val_if_fail (gcry == 0, FALSE);
-	
-	ret = FALSE;
-	
-	/* Is it too long? */
-	if (len <= n_block) {
-		gcry = gcry_mpi_print (GCRYMPI_FMT_USG, block, n_block, &len, mpi);
-		g_return_val_if_fail (gcry == 0, FALSE);
-		g_return_val_if_fail (len <= n_block, FALSE);
-		
-		/* Now align it if necessary */
-		if (len < n_block) {
-			memmove (block + (n_block - len), block, len);
-			memset (block, 0, (n_block - len));
-		}
-		
-		ret = TRUE;
-	}
-	
+
+	ret = print_mpi_aligned (mpi, block, n_block);
 	gcry_mpi_release (mpi);
 	return ret;
 }
@@ -920,3 +964,171 @@
 	gcry_sexp_release (numbers);
 	return *pubkey ? TRUE : FALSE;
 }
+
+/* -------------------------------------------------------------------
+ * RSA PADDING
+ */
+
+guchar*
+gkr_crypto_rsa_pad_raw (guint n_modulus, const guchar* raw,
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x00 0x00 ... 0x?? 0x?? 0x?? ...
+         *   padding               data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - n_raw;
+	if (n_pad < 0) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	memset (padded, 0x00, n_pad);
+	memcpy (padded + n_pad, raw, n_raw);
+	
+	*n_padded = total;
+	return padded;
+}
+
+guchar*
+gkr_crypto_rsa_pad_one (guint n_modulus, const guchar* raw, 
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x01 0xFF 0xFF ... 0x00 0x?? 0x?? 0x?? ...
+         *      type  padding              data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - 3 - n_raw;
+	if (n_pad < 8) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	padded[1] = 1; /* Block type */
+	memset (padded + 2, 0xff, n_pad);
+	memcpy (padded + 3 + n_pad, raw, n_raw); 
+	
+	*n_padded = total;
+	return padded;
+}
+
+static void
+fill_random_nonzero (guchar *data, gsize n_data)
+{
+	guchar *rnd;
+	guint n_zero, i, j;
+	
+	gcry_randomize (data, n_data, GCRY_STRONG_RANDOM);
+
+	/* Find any zeros in random data */
+	n_zero = 0;
+	for (i = 0; i < n_data; ++i) {
+		if (data[i] == 0x00)
+			++n_zero;
+	}
+
+	while (n_zero > 0) {
+		rnd = gcry_random_bytes (n_zero, GCRY_STRONG_RANDOM);
+		n_zero = 0;
+		for (i = 0, j = 0; i < n_data; ++i) {
+			if (data[i] != 0x00)
+				continue;
+				
+			/* Use some of the replacement data */
+			data[i] = rnd[j];
+			++j;
+			
+			/* It's zero again :( */
+			if (data[i] == 0x00)
+				n_zero++;
+		}
+		
+		gcry_free (rnd);
+	}
+}
+
+guchar*
+gkr_crypto_rsa_pad_two (guint n_modulus, const guchar* raw, 
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x01 0x?? 0x?? ... 0x00 0x?? 0x?? 0x?? ...
+         *      type  padding              data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - 3 - n_raw;
+	if (n_pad < 8) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	padded[1] = 2; /* Block type */
+	fill_random_nonzero (padded + 2, n_pad);
+	memcpy (padded + 3 + n_pad, raw, n_raw); 
+	
+	*n_padded = total;
+	return padded;
+}
+
+static guchar*
+unpad_rsa_pkcs1 (guchar bt, guint n_modulus, const guchar* padded,
+                 gsize n_padded, gsize *n_raw)
+{ 
+	const guchar *at;
+	guchar *raw;
+	
+	/* The absolute minimum size including padding */
+	g_return_val_if_fail (n_modulus / 8 >= 3 + 8, NULL);
+	
+	if (n_padded != n_modulus / 8)
+		return NULL;
+		
+	/* Check the header */
+	if (padded[0] != 0x00 || padded[1] != bt)
+		return NULL;
+	
+	/* The first zero byte after the header */
+	at = memchr (padded + 2, 0x00, n_padded - 2);
+	if (!at)
+		return NULL;
+		
+	++at;
+	*n_raw = n_padded - (at - padded);
+	raw = g_new0 (guchar, *n_raw);
+	memcpy (raw, at, *n_raw);
+	return raw;
+}
+
+guchar*
+gkr_crypto_rsa_unpad_pkcs1 (guint bits, const guchar *padded,
+                            gsize n_padded, gsize *n_raw)
+{
+	/* Further checks are done later */
+	g_return_val_if_fail (n_padded > 2, NULL);
+	return unpad_rsa_pkcs1 (padded[1], bits, padded, n_padded, n_raw);
+}
+
+guchar* 
+gkr_crypto_rsa_unpad_one (guint bits, const guchar *padded, 
+                          gsize n_padded, gsize *n_raw)
+{
+	return unpad_rsa_pkcs1 (0x01, bits, padded, n_padded, n_raw);
+}
+
+guchar* 
+gkr_crypto_rsa_unpad_two (guint bits, const guchar *padded, 
+                          gsize n_padded, gsize *n_raw)
+{
+	return unpad_rsa_pkcs1 (0x02, bits, padded, n_padded, n_raw);
+}

Modified: trunk/common/gkr-crypto.h
==============================================================================
--- trunk/common/gkr-crypto.h	(original)
+++ trunk/common/gkr-crypto.h	Mon Mar 17 01:14:46 2008
@@ -29,6 +29,10 @@
 
 #include "gkr-id.h"
 
+typedef guchar* (*GkrCryptoPadding) (guint n_modulus, const guchar* raw, 
+                                     gsize n_raw, gsize *n_padded);
+
+
 void               gkr_crypto_setup                     (void);
 
 gboolean           gkr_crypto_hex_encode                (const guchar *data, gsize n_data, 
@@ -63,7 +67,11 @@
 gboolean           gkr_crypto_sexp_extract_mpi          (gcry_sexp_t sexp, gcry_mpi_t *mpi, ...)
                                                          G_GNUC_NULL_TERMINATED;
 
-gboolean           gkr_crypto_sexp_extract_mpi_aligned  (gcry_sexp_t sexp, guchar* block, gsize n_block, ...)
+guchar*            gkr_crypto_sexp_extract_mpi_padded   (gcry_sexp_t sexp, guint bits, gsize *n_data, 
+                                                         GkrCryptoPadding padfunc, ...) 
+                                                         G_GNUC_NULL_TERMINATED;
+
+gboolean           gkr_crypto_sexp_extract_mpi_aligned  (gcry_sexp_t sexp, guchar* block, gsize n_block, ...) 
                                                          G_GNUC_NULL_TERMINATED;
 
 void               gkr_crypto_sexp_dump                 (gcry_sexp_t sexp);
@@ -75,4 +83,22 @@
 
 gboolean           gkr_crypto_skey_private_to_public    (gcry_sexp_t privkey, gcry_sexp_t *pubkey);
 
+guchar*	           gkr_crypto_rsa_pad_raw               (guint bits, const guchar* raw,
+                                                         gsize n_raw, gsize *n_padded);
+
+guchar*            gkr_crypto_rsa_pad_one               (guint bits, const guchar* raw, 
+                                                         gsize n_raw, gsize *n_padded);
+
+guchar*            gkr_crypto_rsa_pad_two               (guint bits, const guchar* raw, 
+                                                         gsize n_raw, gsize *n_padded);
+
+guchar*            gkr_crypto_rsa_unpad_pkcs1           (guint bits, const guchar *padded,
+                                                         gsize n_padded, gsize *n_raw);
+
+guchar*            gkr_crypto_rsa_unpad_one             (guint bits, const guchar *padded, 
+                                                         gsize n_padded, gsize *n_raw);
+
+guchar*            gkr_crypto_rsa_unpad_two             (guint bits, const guchar* padded, 
+                                                         gsize n_padded, gsize *n_raw);
+
 #endif /*GKRCRYPTO_H_*/

Modified: trunk/pk/gkr-pk-object-manager.c
==============================================================================
--- trunk/pk/gkr-pk-object-manager.c	(original)
+++ trunk/pk/gkr-pk-object-manager.c	Mon Mar 17 01:14:46 2008
@@ -224,6 +224,12 @@
 }
 
 GkrPkObjectManager*
+gkr_pk_object_manager_new (void)
+{
+	return g_object_new (GKR_TYPE_PK_OBJECT_MANAGER, NULL);
+}
+
+GkrPkObjectManager*
 gkr_pk_object_manager_for_token (void)
 {
 	if (!object_manager_for_token) {

Modified: trunk/pk/gkr-pk-object-manager.h
==============================================================================
--- trunk/pk/gkr-pk-object-manager.h	(original)
+++ trunk/pk/gkr-pk-object-manager.h	Mon Mar 17 01:14:46 2008
@@ -72,6 +72,8 @@
 
 GType                   gkr_pk_object_manager_type_from_string    (const gchar *type);
 
+GkrPkObjectManager*     gkr_pk_object_manager_new                 (void);
+
 GkrPkObjectManager*     gkr_pk_object_manager_for_token           (void);
 
 GkrPkObjectManager*     gkr_pk_object_manager_for_client          (pid_t pid);

Modified: trunk/pk/gkr-pk-pubkey.c
==============================================================================
--- trunk/pk/gkr-pk-pubkey.c	(original)
+++ trunk/pk/gkr-pk-pubkey.c	Mon Mar 17 01:14:46 2008
@@ -511,6 +511,7 @@
 	gkrid keyid;
 	
 	g_return_val_if_fail (s_key, NULL);
+	g_return_val_if_fail (GKR_IS_PK_OBJECT_MANAGER (manager), NULL);
 	
 	/* Make sure we have the keyid properly */
 	keyid = gkr_crypto_skey_make_id (s_key);

Modified: trunk/pkcs11/gkr-pkcs11-daemon-session.c
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-daemon-session.c	(original)
+++ trunk/pkcs11/gkr-pkcs11-daemon-session.c	Mon Mar 17 01:14:46 2008
@@ -32,6 +32,7 @@
 
 #include "common/gkr-async.h"
 #include "common/gkr-buffer.h"
+#include "common/gkr-crypto.h"
 #include "common/gkr-unix-credentials.h"
 
 #include "keyrings/gkr-keyring-login.h"
@@ -849,12 +850,12 @@
 	ctx = (CryptContext*)sinfo->operation_data;
 	switch (ctx->mechanism) {
 	case CKM_RSA_PKCS:
-		ret = gkr_pkcs11_rsa_encrypt (ctx->key, gkr_pkcs11_rsa_pad_two, 
+		ret = gkr_pkcs11_rsa_encrypt (ctx->key, gkr_crypto_rsa_pad_two, 
 		                              plain, n_plain, 
 	                                      &encrypted, &n_encrypted);
 		break;
 	case CKM_RSA_X_509:
-		ret = gkr_pkcs11_rsa_encrypt (ctx->key, gkr_pkcs11_rsa_pad_raw, 
+		ret = gkr_pkcs11_rsa_encrypt (ctx->key, gkr_crypto_rsa_pad_raw, 
 		                              plain, n_plain, 
 	                                      &encrypted, &n_encrypted);
 		break;
@@ -948,7 +949,7 @@
 	ctx = (CryptContext*)sinfo->operation_data;
 	switch (ctx->mechanism) {
 	case CKM_RSA_PKCS:
-		ret = gkr_pkcs11_rsa_decrypt (ctx->key, gkr_pkcs11_rsa_unpad_two, 
+		ret = gkr_pkcs11_rsa_decrypt (ctx->key, gkr_crypto_rsa_unpad_two, 
 		                              encrypted, n_encrypted, 
 	                                      &data, &n_data);
 		break;
@@ -1094,12 +1095,12 @@
 	ctx = (CryptContext*)sinfo->operation_data;
 	switch (ctx->mechanism) {
 	case CKM_RSA_PKCS:
-		ret = gkr_pkcs11_rsa_sign (ctx->key, gkr_pkcs11_rsa_pad_one, 
+		ret = gkr_pkcs11_rsa_sign (ctx->key, gkr_crypto_rsa_pad_one, 
 		                           data, n_data, 
 		                           &signature, &n_signature);
 		break;
 	case CKM_RSA_X_509:
-		ret = gkr_pkcs11_rsa_sign (ctx->key, gkr_pkcs11_rsa_pad_raw,
+		ret = gkr_pkcs11_rsa_sign (ctx->key, gkr_crypto_rsa_pad_raw,
 		                           data, n_data, 
 	                                   &signature, &n_signature);
 		break;
@@ -1216,12 +1217,12 @@
 	ctx = (CryptContext*)sinfo->operation_data;
 	switch (ctx->mechanism) {
 	case CKM_RSA_PKCS:
-		ret = gkr_pkcs11_rsa_verify (ctx->key, gkr_pkcs11_rsa_pad_one, 
+		ret = gkr_pkcs11_rsa_verify (ctx->key, gkr_crypto_rsa_pad_one, 
 		                             data, n_data, 
 	                                     signature, n_signature);
 		break;
 	case CKM_RSA_X_509:
-		ret = gkr_pkcs11_rsa_verify (ctx->key, gkr_pkcs11_rsa_pad_raw, 
+		ret = gkr_pkcs11_rsa_verify (ctx->key, gkr_crypto_rsa_pad_raw, 
 		                             data, n_data, 
 	                                     signature, n_signature);
 		break;

Modified: trunk/pkcs11/gkr-pkcs11-rsa.c
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-rsa.c	(original)
+++ trunk/pkcs11/gkr-pkcs11-rsa.c	Mon Mar 17 01:14:46 2008
@@ -30,165 +30,6 @@
 #include "pk/gkr-pk-pubkey.h"
 #include "pk/gkr-pk-privkey.h"
 
-/* -------------------------------------------------------------------
- * RSA PADDING
- */
-
-guchar*
-gkr_pkcs11_rsa_pad_raw (guint n_modulus, const guchar* raw,
-                        gsize n_raw, gsize *n_padded)
-{
-	gint total, n_pad;
-	guchar *padded;
-
-	/*
-	 * 0x00 0x00 0x00 ... 0x?? 0x?? 0x?? ...
-         *   padding               data
-         */
-
-	total = n_modulus / 8;
-	n_pad = total - n_raw;
-	if (n_pad < 0) /* minumum padding */
-		return NULL;
-
-	padded = g_new0 (guchar, total);
-	memset (padded, 0x00, n_pad);
-	memcpy (padded + n_pad, raw, n_raw);
-	
-	*n_padded = total;
-	return padded;
-}
-
-guchar*
-gkr_pkcs11_rsa_pad_one (guint n_modulus, const guchar* raw, 
-                        gsize n_raw, gsize *n_padded)
-{
-	gint total, n_pad;
-	guchar *padded;
-
-	/*
-	 * 0x00 0x01 0xFF 0xFF ... 0x00 0x?? 0x?? 0x?? ...
-         *      type  padding              data
-         */
-
-	total = n_modulus / 8;
-	n_pad = total - 3 - n_raw;
-	if (n_pad < 8) /* minumum padding */
-		return NULL;
-
-	padded = g_new0 (guchar, total);
-	padded[1] = 1; /* Block type */
-	memset (padded + 2, 0xff, n_pad);
-	memcpy (padded + 3 + n_pad, raw, n_raw); 
-	
-	*n_padded = total;
-	return padded;
-}
-
-static void
-fill_random_nonzero (guchar *data, gsize n_data)
-{
-	guchar *rnd;
-	guint n_zero, i, j;
-	
-	gcry_randomize (data, n_data, GCRY_STRONG_RANDOM);
-
-	/* Find any zeros in random data */
-	n_zero = 0;
-	for (i = 0; i < n_data; ++i) {
-		if (data[i] == 0x00)
-			++n_zero;
-	}
-
-	while (n_zero > 0) {
-		rnd = gcry_random_bytes (n_zero, GCRY_STRONG_RANDOM);
-		n_zero = 0;
-		for (i = 0, j = 0; i < n_data; ++i) {
-			if (data[i] != 0x00)
-				continue;
-				
-			/* Use some of the replacement data */
-			data[i] = rnd[j];
-			++j;
-			
-			/* It's zero again :( */
-			if (data[i] == 0x00)
-				n_zero++;
-		}
-		
-		gcry_free (rnd);
-	}
-}
-
-guchar*
-gkr_pkcs11_rsa_pad_two (guint n_modulus, const guchar* raw, 
-                        gsize n_raw, gsize *n_padded)
-{
-	gint total, n_pad;
-	guchar *padded;
-
-	/*
-	 * 0x00 0x01 0x?? 0x?? ... 0x00 0x?? 0x?? 0x?? ...
-         *      type  padding              data
-         */
-
-	total = n_modulus / 8;
-	n_pad = total - 3 - n_raw;
-	if (n_pad < 8) /* minumum padding */
-		return NULL;
-
-	padded = g_new0 (guchar, total);
-	padded[1] = 2; /* Block type */
-	fill_random_nonzero (padded + 2, n_pad);
-	memcpy (padded + 3 + n_pad, raw, n_raw); 
-	
-	*n_padded = total;
-	return padded;
-}
-
-static guchar*
-unpad_rsa_pkcs1 (guchar bt, guint n_modulus, const guchar* padded,
-                 gsize n_padded, gsize *n_raw)
-{ 
-	const guchar *at;
-	guchar *raw;
-	
-	/* The absolute minimum size including padding */
-	g_return_val_if_fail (n_modulus / 8 >= 3 + 8, NULL);
-	
-	if (n_padded != n_modulus / 8)
-		return NULL;
-		
-	/* Check the header */
-	if (padded[0] != 0x00 || padded[1] != bt)
-		return NULL;
-	
-	/* The first zero byte after the header */
-	at = memchr (padded + 2, 0x00, n_padded - 2);
-	if (!at)
-		return NULL;
-		
-	++at;
-	*n_raw = n_padded - (at - padded);
-	raw = g_new0 (guchar, *n_raw);
-	memcpy (raw, at, *n_raw);
-	return raw;
-}
-
-guchar* 
-gkr_pkcs11_rsa_unpad_one (guint n_modulus, const guchar *raw, 
-                          gsize n_raw, gsize *n_padded)
-{
-	return unpad_rsa_pkcs1 (0x01, n_modulus, raw, n_raw, n_padded);
-}
-
-guchar* 
-gkr_pkcs11_rsa_unpad_two (guint n_modulus, const guchar *raw, 
-                          gsize n_raw, gsize *n_padded)
-{
-	return unpad_rsa_pkcs1 (0x02, n_modulus, raw, n_raw, n_padded);
-}
-
 static CK_RV
 object_to_public_key (GkrPkObject *object, gcry_sexp_t *s_key)
 {
@@ -236,7 +77,7 @@
 }
 
 static CK_RV
-data_to_sexp (const gchar *format, guint nbits, GkrPkcs11RsaPadding padfunc, 
+data_to_sexp (const gchar *format, guint nbits, GkrCryptoPadding padfunc, 
               const guchar *data, gsize n_data, gcry_sexp_t *sexp)
 {
 	guchar *padded = NULL;
@@ -274,46 +115,24 @@
 
 static CK_RV
 sexp_to_data (const gchar* format1, const gchar *format2, const gchar *format3,
-              guint nbits, GkrPkcs11RsaPadding padfunc, gcry_sexp_t sexp, 
+              guint nbits, GkrCryptoPadding padfunc, gcry_sexp_t sexp, 
               guchar **data, gsize *n_data)
 {
-	guchar *raw;
-	gsize n_raw;
-	gboolean res;
-	
 	g_assert (format1);
 	g_assert (sexp);
 	g_assert (data);
 	g_assert (n_data);
 
-	*n_data = nbits / 8;
-	*data = g_malloc0 (*n_data);
-	
 	/* Now extract and send it back out */
-	res = gkr_crypto_sexp_extract_mpi_aligned (sexp, *data, *n_data, 
-	                                           format1, format2, format3, NULL);
-	g_return_val_if_fail (res, CKR_GENERAL_ERROR);
+	*data = gkr_crypto_sexp_extract_mpi_padded (sexp, nbits, n_data, padfunc,
+	                                            format1, format2, format3, NULL);
+	g_return_val_if_fail (*data, CKR_GENERAL_ERROR);
 
-	/* Now we unpad it if necessary */
-	if (padfunc) {
-		raw = (padfunc) (nbits, *data, *n_data, &n_raw);
-		
-		/* 
-		 * If the unpadding failed, then it's probably 
-		 * invalid data sent for decryption. Ignore.
-		 */
-		if (raw) {
-			g_free (*data); 
-			*data = raw;
-			*n_data = n_raw;
-		}
-	}
-	
 	return CKR_OK;  
 } 
 
 CK_RV
-gkr_pkcs11_rsa_encrypt (GkrPkObject *key, GkrPkcs11RsaPadding padfunc,
+gkr_pkcs11_rsa_encrypt (GkrPkObject *key, GkrCryptoPadding padfunc,
                         const guchar *plain, gsize n_plain, 
                         guchar **encrypted, gsize *n_encrypted)
 {
@@ -360,7 +179,7 @@
 }
 
 CK_RV
-gkr_pkcs11_rsa_decrypt (GkrPkObject *object, GkrPkcs11RsaPadding padfunc, 
+gkr_pkcs11_rsa_decrypt (GkrPkObject *object, GkrCryptoPadding padfunc, 
                         const guchar *encrypted, gsize n_encrypted, 
                         guchar **plain, gsize *n_plain)
 {
@@ -412,7 +231,7 @@
 }
 
 CK_RV
-gkr_pkcs11_rsa_sign (GkrPkObject *object, GkrPkcs11RsaPadding padfunc, 
+gkr_pkcs11_rsa_sign (GkrPkObject *object, GkrCryptoPadding padfunc, 
                      const guchar *input, gsize n_input, 
                      guchar **signature, gsize *n_signature)
 {
@@ -459,7 +278,7 @@
 }
 
 CK_RV
-gkr_pkcs11_rsa_verify (GkrPkObject *object, GkrPkcs11RsaPadding padfunc, 
+gkr_pkcs11_rsa_verify (GkrPkObject *object, GkrCryptoPadding padfunc, 
                        const guchar *data, gsize n_data, 
                        const guchar *signature, gsize n_signature)
 {

Modified: trunk/pkcs11/gkr-pkcs11-rsa.h
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-rsa.h	(original)
+++ trunk/pkcs11/gkr-pkcs11-rsa.h	Mon Mar 17 01:14:46 2008
@@ -27,38 +27,21 @@
 #include "pkcs11.h"
 
 #include "pk/gkr-pk-object.h"
+#include "common/gkr-crypto.h"
 
-typedef guchar* (*GkrPkcs11RsaPadding) (guint n_modulus, const guchar* raw, 
-                                        gsize n_raw, gsize *n_padded);
-
-guchar*	              gkr_pkcs11_rsa_pad_raw                (guint n_modulus, const guchar* raw,
-                                                             gsize n_raw, gsize *n_padded);
-
-guchar*               gkr_pkcs11_rsa_pad_one                (guint n_modulus, const guchar* raw, 
-                                                             gsize n_raw, gsize *n_padded);
-
-guchar*               gkr_pkcs11_rsa_pad_two                (guint n_modulus, const guchar* raw, 
-                                                             gsize n_raw, gsize *n_padded);
-
-guchar*               gkr_pkcs11_rsa_unpad_one              (guint n_modulus, const guchar* padded, 
-                                                             gsize n_padded, gsize *n_raw);
-
-guchar*               gkr_pkcs11_rsa_unpad_two              (guint n_modulus, const guchar* padded, 
-                                                             gsize n_padded, gsize *n_raw);
-
-CK_RV                 gkr_pkcs11_rsa_encrypt                (GkrPkObject *key, GkrPkcs11RsaPadding padfunc,
+CK_RV                 gkr_pkcs11_rsa_encrypt                (GkrPkObject *key, GkrCryptoPadding padfunc,
                                                              const guchar *plain, gsize n_plain, 
                                                              guchar **encrypted, gsize *n_encrypted);
 
-CK_RV                 gkr_pkcs11_rsa_decrypt                (GkrPkObject *key, GkrPkcs11RsaPadding padfunc,
+CK_RV                 gkr_pkcs11_rsa_decrypt                (GkrPkObject *key, GkrCryptoPadding padfunc,
                                                              const guchar *encrypted, gsize n_encrypted, 
                                                              guchar **plain, gsize *n_plain);
 
-CK_RV                 gkr_pkcs11_rsa_sign                  (GkrPkObject *key, GkrPkcs11RsaPadding padfunc,
+CK_RV                 gkr_pkcs11_rsa_sign                  (GkrPkObject *key, GkrCryptoPadding padfunc,
                                                             const guchar *data, gsize n_data, 
                                                             guchar **signature, gsize *n_signature);
 
-CK_RV                 gkr_pkcs11_rsa_verify                 (GkrPkObject *key, GkrPkcs11RsaPadding padfunc,
+CK_RV                 gkr_pkcs11_rsa_verify                 (GkrPkObject *key, GkrCryptoPadding padfunc,
                                                              const guchar *data, gsize n_data, 
                                                              const guchar *signature, gsize n_signature);
 

Modified: trunk/ssh/gkr-ssh-daemon-ops.c
==============================================================================
--- trunk/ssh/gkr-ssh-daemon-ops.c	(original)
+++ trunk/ssh/gkr-ssh-daemon-ops.c	Mon Mar 17 01:14:46 2008
@@ -48,101 +48,125 @@
  * SESSION KEYS
  */
 
-static gboolean had_session_keys = FALSE;
-static GList *ssh_session_keys = NULL;
+static GkrPkObjectManager *session_manager = NULL;
 
 static void
-cleanup_session_keys (gpointer unused)
+mark_v1_key (GkrPkPrivkey *key)
 {
-	GList *l;
-	for (l = ssh_session_keys; l; l = g_list_next (l))
-		g_object_unref (l->data);
-	g_list_free (ssh_session_keys);
-	ssh_session_keys = NULL;	
+	/* Track the version of the SSH protocol that this came in on */
+	g_object_set_data (G_OBJECT (key), "ssh-protocol-version", GUINT_TO_POINTER (1));
+}
+
+static gboolean
+check_v1_key (GkrPkPrivkey *key)
+{
+	return g_object_get_data (G_OBJECT (key), "ssh-protocol-version") == GUINT_TO_POINTER (1);
+}
+
+static void
+cleanup_session_manager (gpointer unused)
+{
+	g_return_if_fail (session_manager);
+	g_object_unref (session_manager);
+	session_manager = NULL;
 }
 
 static GkrPkPrivkey*
-find_private_key (gcry_sexp_t s_key, gboolean manager)
+find_private_key_in_manager (GkrPkObjectManager *manager, const gkrid keyid, guint version)
 {
 	GkrPkPrivkey *key = NULL;
-	gkrid keyid;
+	GList *l, *objects;
 	const guchar *data;
 	gsize n_data;
-	GList *l, *objects;
-	
-	keyid = gkr_crypto_skey_make_id (s_key);
-	g_return_val_if_fail (keyid != NULL, NULL);
+
+	data = gkr_id_get_raw (keyid, &n_data);
+	g_assert (data && n_data);
+
+	objects = gkr_pk_object_manager_findv (manager, GKR_TYPE_PK_PRIVKEY, 
+	                                       CKA_ID, data, n_data, NULL);
 	
-	for (l = ssh_session_keys; l; l = g_list_next (l)) {
-		key = GKR_PK_PRIVKEY (l->data);
-		if (gkr_id_equals (keyid, gkr_pk_privkey_get_keyid (key)))
-			break;
+	for (l = objects; l; l = g_list_next (l)) {
+		key = GKR_PK_PRIVKEY (objects->data);
+		if ((version == 1) != check_v1_key (key))
+			continue;
+		break;
 	}
+
+	g_list_free (objects);
 	
 	if (l == NULL)
 		key = NULL;
+
+	return key;
+}
+
+static GkrPkPrivkey*
+find_private_key (gcry_sexp_t skey, gboolean global, guint version)
+{
+	GkrPkPrivkey *key = NULL;
+	gkrid keyid;
 	
-	if (!key && manager) {
-		data = gkr_id_get_raw (keyid, &n_data);
-		g_assert (data && n_data);
-		
-		objects = gkr_pk_object_manager_findv (gkr_pk_object_manager_for_token (), GKR_TYPE_PK_PRIVKEY, 
-		                                       CKA_ID, data, n_data, NULL);
-		if (objects) {
-			key = GKR_PK_PRIVKEY (objects->data);
-			g_list_free (objects);
-		}
-	}
+	keyid = gkr_crypto_skey_make_id (skey);
+	g_return_val_if_fail (keyid != NULL, NULL);
 
-	gkr_id_free (keyid);
+	/* Search through the  session keys */
+	if (session_manager)
+		key = find_private_key_in_manager (session_manager, keyid, version);
+		
+	/* Search through the global keys */
+	if (!key && global) 
+		key = find_private_key_in_manager (gkr_pk_object_manager_for_token (), keyid, version);
 	
+	gkr_id_free (keyid);
 	return key;
 }
 
 static void
 remove_session_key (GkrPkPrivkey *key)
 {
-	GList *link = g_list_find (ssh_session_keys, key);
-	if (!link)
-		return;
-	ssh_session_keys = g_list_remove_link (ssh_session_keys, link);
-	g_object_unref (key);
-	g_list_free_1 (link);
+	if (session_manager)
+		gkr_pk_object_manager_unregister (session_manager, GKR_PK_OBJECT (key));
 }
 
 static void
-add_session_key (gcry_sexp_t s_key, const gchar *comment)
+add_session_key (gcry_sexp_t skey, const gchar *comment, guint version)
 {
 	GkrPkPrivkey *key, *prev;
+
+	if (!session_manager) {
+		session_manager = gkr_pk_object_manager_new ();
+		gkr_cleanup_register (cleanup_session_manager, NULL);
+	}
+
+	prev = find_private_key (skey, FALSE, version);
+	if (prev)
+		remove_session_key (prev);
 	
-	key = GKR_PK_PRIVKEY (gkr_pk_privkey_new (NULL, 0, s_key));
+	key = GKR_PK_PRIVKEY (gkr_pk_privkey_new (session_manager, 0, skey));
 	g_return_if_fail (key != NULL);
 	
 	if (comment)
 		g_object_set (key, "label", comment, NULL);
 	
-	prev = find_private_key (s_key, FALSE);
-	if (prev)
-		remove_session_key (prev);
-		
-	ssh_session_keys = g_list_prepend (ssh_session_keys, key);
-	
-	if (!had_session_keys) {
-		had_session_keys = TRUE;
-		gkr_cleanup_register (cleanup_session_keys, NULL);
-	}
+	if (version == 1)
+		mark_v1_key (key);
 }
 
 static void
-get_public_keys (GList *privates, GList** publics) 
+get_public_keys (GList *objects, GList** publics, guint version) 
 {
 	GkrPkPrivkey *key;
 	GkrPkPubkey *pub;
 	
-	for (; privates; privates = g_list_next (privates)) {
+	for (; objects; objects = g_list_next (objects)) {
 		
-		key = GKR_PK_PRIVKEY (privates->data);
-		g_return_if_fail (GKR_IS_PK_PRIVKEY (key));
+		if (!GKR_IS_PK_PRIVKEY (objects->data))
+			continue;
+		key = GKR_PK_PRIVKEY (objects->data);
+		
+		/* When getting version one keys skip over any that aren't marked that way. */
+		if ((version == 1) != check_v1_key (key))
+			continue;
 		
 		pub = GKR_PK_PUBKEY (gkr_pk_privkey_get_public (key));
 		if (!pub) {
@@ -205,7 +229,7 @@
 		return FALSE;
 	}
 		
-	add_session_key (key, comment);
+	add_session_key (key, comment, 2);
 	g_free (comment);
 	
 	gkr_buffer_add_byte (resp, GKR_SSH_RES_SUCCESS);
@@ -213,9 +237,31 @@
 }
 
 static gboolean
+op_v1_add_identity (GkrBuffer *req, GkrBuffer *resp)
+{
+	gcry_sexp_t key;
+	gboolean ret;
+	gsize offset = 5;	
+	guint32 unused;
+	
+	if (!gkr_buffer_get_uint32 (req, offset, &offset, &unused))
+		return FALSE;
+	
+	ret = gkr_ssh_proto_read_private_v1 (req, &offset, &key);
+	if (!ret || !key) {
+		g_warning ("couldn't read incoming SSH private key");
+		return FALSE;		
+	}
+	
+	add_session_key (key, "SSH1 RSA key", 1);
+	
+	gkr_buffer_add_byte (resp, GKR_SSH_RES_SUCCESS);
+	return TRUE;	
+}
+
+static gboolean
 op_request_identities (GkrBuffer *req, GkrBuffer *resp)
 {
-	gboolean ret = TRUE;
 	GList *objects, *pubkeys, *l;
 	GkrPkPubkey *pub;
 	const gchar *label;
@@ -225,8 +271,9 @@
 	                                       CKA_GNOME_PURPOSE_SSH_AUTH, CK_TRUE, 0, NULL);
 	
 	pubkeys = NULL;
-	get_public_keys (ssh_session_keys, &pubkeys);
-	get_public_keys (objects, &pubkeys);
+	if (session_manager)
+		get_public_keys (session_manager->objects, &pubkeys, 2);
+	get_public_keys (objects, &pubkeys, 2);
 	
 	g_list_free (objects);
 	
@@ -249,7 +296,37 @@
 	
 	g_list_free (pubkeys);
 	
-	return ret;
+	return TRUE;
+}
+
+static gboolean
+op_v1_request_identities (GkrBuffer *req, GkrBuffer *resp)
+{
+	GList *l, *pubkeys = NULL;
+	GkrPkPubkey *pub;
+	const gchar *label;
+	
+	if (session_manager)
+		get_public_keys (session_manager->objects, &pubkeys, 1);
+	
+	gkr_buffer_add_byte (resp, GKR_SSH_RES_RSA_IDENTITIES_ANSWER);
+	gkr_buffer_add_uint32 (resp, g_list_length (pubkeys));
+	      
+	for (l = pubkeys; l; l = g_list_next (l)) {
+		
+		pub = GKR_PK_PUBKEY (l->data);
+		g_return_val_if_fail (GKR_IS_PK_PUBKEY (pub), FALSE);
+		
+		if (!gkr_ssh_proto_write_public_v1 (resp, gkr_pk_pubkey_get_key (pub)))
+			return FALSE;
+		
+		/* And now a per key comment */
+		label = gkr_pk_object_get_label (GKR_PK_OBJECT (pub));
+		gkr_buffer_add_string (resp, label ? label : "");
+	}
+	
+	g_list_free (pubkeys);
+	return TRUE;
 }
 
 static gboolean
@@ -326,7 +403,7 @@
 	}
 
 	/* Lookup the key */
-	key = find_private_key (s_key, TRUE);
+	key = find_private_key (s_key, TRUE, 2);
 	gcry_sexp_release (s_key);
 	
 	if (!key) {
@@ -358,8 +435,9 @@
 		
 	s_key = gkr_pk_privkey_get_key (key);
 	if (!s_key) {
-		g_warning ("couldn't get private signing key");
-		return FALSE;
+		g_message ("couldn't get private signing key");
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		return TRUE;
 	}
 		
 	/* Do the magic */
@@ -404,6 +482,145 @@
 	return TRUE; 
 }
 
+static gboolean
+make_decrypt_sexp (gcry_mpi_t mpi, gcry_sexp_t *sexp)
+{
+	gcry_error_t gcry;
+	
+	gcry = gcry_sexp_build (sexp, NULL, "(enc-val (flags) (rsa (a %m)))", mpi);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	
+	return TRUE;
+}
+
+static gboolean 
+op_v1_challenge (GkrBuffer *req, GkrBuffer *resp)
+{
+	guchar session_id[16];
+	gcry_error_t gcry;
+	gcry_md_hd_t hd = NULL;
+	gcry_sexp_t skey;
+	gcry_sexp_t splain = NULL;
+	gcry_sexp_t sdata = NULL;
+	GkrPkPrivkey *key;
+	const guchar *hash;
+	gcry_mpi_t challenge = NULL;
+	guchar *raw = NULL;
+	gsize offset, n_raw;
+	guint32 resp_type;
+	gboolean ret;
+	guint i, bits;
+	guchar b;
+	
+	ret = FALSE;
+	offset = 5;
+	
+	if (!gkr_ssh_proto_read_public_v1 (req, &offset, &skey))
+		return FALSE;
+	
+	/* Lookup the key */
+	key = find_private_key (skey, TRUE, 1);
+	gcry_sexp_release (skey);
+	
+	/* Read the entire challenge */
+	if (!gkr_ssh_proto_read_mpi_v1 (req, &offset, &challenge))
+		goto cleanup;
+	
+	/* Only protocol 1.1 is supported */
+	if (req->len <= offset) {
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		ret = TRUE;
+		goto cleanup;
+	}
+		
+	/* Read out the session id, raw, unbounded */
+	for (i = 0; i < 16; ++i) {
+		if (!gkr_buffer_get_byte (req, offset, &offset, &b))
+			goto cleanup;
+		session_id[i] = b;
+	}
+		
+	/* And the response type */
+	if (!gkr_buffer_get_uint32 (req, offset, &offset, &resp_type))
+		goto cleanup;
+	
+	/* Not supported request type */
+	if (resp_type != 1) {
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		ret = TRUE;
+		goto cleanup;
+	}	
+
+	/* Didn't find a key earlier */
+	if (!key) {
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		ret = TRUE;
+		goto cleanup;
+	}
+
+	skey = gkr_pk_privkey_get_key (key);
+	if (!skey) {
+		g_message ("couldn't get private decryption key");
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		ret = TRUE;
+		goto cleanup;
+	}
+	
+	/* Make our data sexpression */
+	if (!make_decrypt_sexp (challenge, &sdata))
+		return FALSE;
+
+gkr_crypto_sexp_dump (sdata);
+
+	/* Do the magic */
+	gcry = gcry_pk_decrypt (&splain, sdata, skey);
+
+	if (gcry) {
+		g_warning ("decryption of the data failed: %s", gcry_strerror (gcry));
+		gkr_buffer_add_byte (resp, GKR_SSH_RES_FAILURE);
+		ret = TRUE;
+		goto cleanup;
+	}
+	
+gkr_crypto_sexp_dump (splain);
+
+	/* Number of bits in the key */
+	bits = gcry_pk_get_nbits (skey);
+	g_return_val_if_fail (bits, FALSE);
+
+	/* Get out the value */
+	raw = gkr_crypto_sexp_extract_mpi_padded (splain, bits, &n_raw, 
+	                                          gkr_crypto_rsa_unpad_pkcs1, "value", NULL);
+	g_return_val_if_fail (raw, FALSE);
+
+	/* Now build up a hash of this and the session_id */
+	gcry = gcry_md_open (&hd, GCRY_MD_MD5, 0);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	gcry_md_write (hd, raw, n_raw);
+	gcry_md_write (hd, session_id, sizeof (session_id));
+	hash = gcry_md_read (hd, 0);
+	g_return_val_if_fail (hash, FALSE);
+	
+	gkr_buffer_add_byte (resp, GKR_SSH_RES_RSA_RESPONSE);
+	gkr_buffer_append (resp, hash, 16);
+	
+	ret = TRUE;
+	
+cleanup:
+	if (hd)
+		gcry_md_close (hd);
+	if (challenge)
+		gcry_mpi_release (challenge);
+	if (sdata)
+		gcry_sexp_release (sdata);
+	if (splain)
+		gcry_sexp_release (splain);
+	if (raw)
+		g_free (raw);
+	
+	return ret;
+}
+
 static gboolean 
 op_remove_identity (GkrBuffer *req, GkrBuffer *resp)
 {
@@ -415,7 +632,7 @@
 	if (!gkr_ssh_proto_read_public (req, &offset, &skey, NULL))
 		return FALSE;
 	
-	key = find_private_key (skey, FALSE);
+	key = find_private_key (skey, FALSE, 2);
 	gcry_sexp_release (skey);
 
 	if (key)
@@ -426,14 +643,68 @@
 }
 
 static gboolean 
-op_remove_all_identities (GkrBuffer *req, GkrBuffer *resp)
+op_v1_remove_identity (GkrBuffer *req, GkrBuffer *resp)
 {
 	GkrPkPrivkey *key;
+	gcry_sexp_t skey;
+	gsize offset;
+	
+	offset = 5;
+	if (!gkr_ssh_proto_read_public_v1 (req, &offset, &skey))
+		return FALSE;
 	
-	while (ssh_session_keys != NULL) {
-		key = GKR_PK_PRIVKEY (ssh_session_keys->data);
-		g_assert (GKR_IS_PK_PRIVKEY (key));	
+	key = find_private_key (skey, FALSE, 1);
+	gcry_sexp_release (skey);
+
+	if (key)
 		remove_session_key (key);
+	gkr_buffer_add_byte (resp, GKR_SSH_RES_SUCCESS);
+
+	return TRUE;	
+}
+
+static gboolean 
+op_remove_all_identities (GkrBuffer *req, GkrBuffer *resp)
+{
+	GkrPkPrivkey *key;
+	GList *l, *removes = NULL;
+	
+	if (session_manager) {
+		for (l = session_manager->objects; l; l = g_list_next (l)) {
+			if (!GKR_IS_PK_PRIVKEY (l->data))
+				continue;
+			key = GKR_PK_PRIVKEY (l->data);
+			if (!check_v1_key (key))
+				removes = g_list_prepend (removes, key);
+		}
+
+		for (l = removes; l; l = g_list_next (l))
+			remove_session_key (GKR_PK_PRIVKEY (l->data));
+		g_list_free (removes);
+	}
+	
+	gkr_buffer_add_byte (resp, GKR_SSH_RES_SUCCESS);
+	return TRUE;
+}
+
+static gboolean 
+op_v1_remove_all_identities (GkrBuffer *req, GkrBuffer *resp)
+{
+	GkrPkPrivkey *key;
+	GList *l, *removes = NULL;
+	
+	if (session_manager) {
+		for (l = session_manager->objects; l; l = g_list_next (l)) {
+			if (!GKR_IS_PK_PRIVKEY (l->data))
+				continue;
+			key = GKR_PK_PRIVKEY (l->data);
+			if (check_v1_key (key))
+				removes = g_list_prepend (removes, key);
+		}
+		
+		for (l = removes; l; l = g_list_next (l))
+			remove_session_key (GKR_PK_PRIVKEY (l->data));
+		g_list_free (removes);
 	}
 	
 	gkr_buffer_add_byte (resp, GKR_SSH_RES_SUCCESS);
@@ -464,15 +735,15 @@
 
 const GkrSshOperation gkr_ssh_operations[GKR_SSH_OP_MAX] = {
      op_invalid,                                 /* 0 */
-     op_not_implemented_failure,                 /* GKR_SSH_OP_REQUEST_RSA_IDENTITIES */
+     op_v1_request_identities,                   /* GKR_SSH_OP_REQUEST_RSA_IDENTITIES */
      op_invalid,                                 /* 2 */
-     op_not_implemented_failure,                 /* GKR_SSH_OP_RSA_CHALLENGE */
+     op_v1_challenge,                            /* GKR_SSH_OP_RSA_CHALLENGE */
      op_invalid,                                 /* 4 */
      op_invalid,                                 /* 5 */
      op_invalid,                                 /* 6 */
-     op_not_implemented_failure,                 /* GKR_SSH_OP_ADD_RSA_IDENTITY */
-     op_not_implemented_failure,                 /* GKR_SSH_OP_REMOVE_RSA_IDENTITY */
-     op_not_implemented_success,                 /* GKR_SSH_OP_REMOVE_ALL_RSA_IDENTITIES */
+     op_v1_add_identity,                         /* GKR_SSH_OP_ADD_RSA_IDENTITY */
+     op_v1_remove_identity,                      /* GKR_SSH_OP_REMOVE_RSA_IDENTITY */
+     op_v1_remove_all_identities,                /* GKR_SSH_OP_REMOVE_ALL_RSA_IDENTITIES */
      op_invalid,                                 /* 10 */     
      op_request_identities,                      /* GKR_SSH_OP_REQUEST_IDENTITIES */
      op_invalid,                                 /* 12 */
@@ -487,7 +758,7 @@
      op_not_implemented_failure,                 /* GKR_SSH_OP_REMOVE_SMARTCARD_KEY */
      op_not_implemented_success,                 /* GKR_SSH_OP_LOCK */
      op_not_implemented_success,                 /* GKR_SSH_OP_UNLOCK */
-     op_not_implemented_failure,                 /* GKR_SSH_OP_ADD_RSA_ID_CONSTRAINED */
+     op_v1_add_identity,                         /* GKR_SSH_OP_ADD_RSA_ID_CONSTRAINED */
      op_not_implemented_failure,                 /* GKR_SSH_OP_ADD_ID_CONSTRAINED */
      op_not_implemented_failure,                 /* GKR_SSH_OP_ADD_SMARTCARD_KEY_CONSTRAINED */
 };

Modified: trunk/ssh/gkr-ssh-private.h
==============================================================================
--- trunk/ssh/gkr-ssh-private.h	(original)
+++ trunk/ssh/gkr-ssh-private.h	Mon Mar 17 01:14:46 2008
@@ -88,24 +88,34 @@
 
 gboolean              gkr_ssh_proto_read_mpi                  (GkrBuffer *req, gsize *offset, gcry_mpi_t *mpi);
 
+gboolean              gkr_ssh_proto_read_mpi_v1               (GkrBuffer *req, gsize *offset, gcry_mpi_t *mpi);
+
 gboolean              gkr_ssh_proto_write_mpi                 (GkrBuffer *resp, gcry_mpi_t mpi, int format);
 
+gboolean              gkr_ssh_proto_write_mpi_v1              (GkrBuffer *resp, gcry_mpi_t mpi);
+
 gboolean              gkr_ssh_proto_read_public               (GkrBuffer *req, gsize *offset, gcry_sexp_t *key, int *algo);
 
 gboolean              gkr_ssh_proto_read_public_rsa           (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
 
 gboolean              gkr_ssh_proto_read_public_dsa           (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
 
+gboolean              gkr_ssh_proto_read_public_v1            (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
+
 gboolean              gkr_ssh_proto_read_private_rsa          (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
 
 gboolean              gkr_ssh_proto_read_private_dsa          (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
 
+gboolean              gkr_ssh_proto_read_private_v1           (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp);
+
 gboolean              gkr_ssh_proto_write_public              (GkrBuffer *resp, int algorithm, gcry_sexp_t key);
 
 gboolean              gkr_ssh_proto_write_public_rsa          (GkrBuffer *resp, gcry_sexp_t key);
 
 gboolean              gkr_ssh_proto_write_public_dsa          (GkrBuffer *resp, gcry_sexp_t key);
 
+gboolean              gkr_ssh_proto_write_public_v1           (GkrBuffer *resp, gcry_sexp_t key);
+
 gboolean              gkr_ssh_proto_write_signature_rsa       (GkrBuffer *resp, gcry_sexp_t ssig);
 
 gboolean              gkr_ssh_proto_write_signature_dsa       (GkrBuffer *resp, gcry_sexp_t ssig); 

Modified: trunk/ssh/gkr-ssh-proto.c
==============================================================================
--- trunk/ssh/gkr-ssh-proto.c	(original)
+++ trunk/ssh/gkr-ssh-proto.c	Mon Mar 17 01:14:46 2008
@@ -71,6 +71,36 @@
 }
 
 gboolean
+gkr_ssh_proto_read_mpi_v1 (GkrBuffer *req, gsize *offset, gcry_mpi_t *mpi)
+{
+	const guchar *data;
+	gsize bytes;
+	gcry_error_t gcry;
+	guint16 bits;
+	
+	/* Get the number of bits */
+	if (!gkr_buffer_get_uint16 (req, *offset, offset, &bits))
+		return FALSE;
+	
+	/* Figure out the number of binary bytes following */
+	bytes = (bits + 7) / 8;
+	if (bytes > 8 * 1024)
+		return FALSE;
+	
+	/* Pull these out directly */
+	if (req->len < *offset + bytes)
+		return FALSE;
+	data = req->buf + *offset;
+	*offset += bytes;
+	
+	gcry = gcry_mpi_scan (mpi, GCRYMPI_FMT_USG, data, bytes, NULL);
+	if (gcry)
+		return FALSE;
+		
+	return TRUE;
+}
+
+gboolean
 gkr_ssh_proto_write_mpi (GkrBuffer *resp, gcry_mpi_t mpi, int format)
 {
 	guchar *buf;
@@ -94,6 +124,39 @@
 }
 
 gboolean
+gkr_ssh_proto_write_mpi_v1 (GkrBuffer *resp, gcry_mpi_t mpi)
+{
+  	gcry_error_t gcry;
+	guchar *buf;
+	gsize bits;
+	gsize bytes, len;
+	
+	bits = gcry_mpi_get_nbits (mpi);
+	g_return_val_if_fail (bits <= G_MAXUSHORT, FALSE);
+
+	bytes = (bits + 7) / 8;
+	
+	/* Get the size */
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
+	g_return_val_if_fail (gcry == 0, FALSE);
+	g_return_val_if_fail (bytes == len, FALSE);
+	
+	if (!gkr_buffer_add_uint16 (resp, bits))
+		return FALSE;
+	
+	/* Make a space for it in the buffer */
+	buf = gkr_buffer_add_empty (resp, len);
+	if (!buf)
+		return FALSE;
+	
+	/* Write in directly to buffer */
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, buf, bytes, &len, mpi);	
+	g_return_val_if_fail (gcry == 0, FALSE);
+
+	return TRUE;
+}
+
+gboolean
 gkr_ssh_proto_read_public (GkrBuffer *req, gsize *offset, gcry_sexp_t *key, int *algo)
 {
 	gboolean ret;
@@ -191,6 +254,48 @@
 	return TRUE;
 }
 
+gboolean
+gkr_ssh_proto_read_private_v1 (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp)
+{
+	gcry_mpi_t n, e, d, p, q, u;
+	gcry_mpi_t tmp;
+	int gcry;
+	
+	if (!gkr_ssh_proto_read_mpi_v1 (req, offset, &n) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &e) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &d) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &u) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &p) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &q))
+	    	return FALSE;
+	
+	/* Fix up the incoming key so gcrypt likes it */    	
+	if (gcry_mpi_cmp (p, q) > 0) {
+		/* P shall be smaller then Q!  Swap primes.  iqmp becomes u.  */
+		tmp = p;
+		p = q;
+		q = tmp;
+	} else {
+    		/* U needs to be recomputed.  */
+		gcry_mpi_invm (u, p, q);
+	}
+
+	gcry = gcry_sexp_build (sexp, NULL, SEXP_PRIVATE_RSA, n, e, d, p, q, u);
+	if (gcry) {
+		g_warning ("couldn't parse incoming private RSA key: %s", gcry_strerror (gcry));
+		return FALSE;
+	}
+
+	gcry_mpi_release (n);
+	gcry_mpi_release (e);
+	gcry_mpi_release (d);
+	gcry_mpi_release (p);
+	gcry_mpi_release (q);
+	gcry_mpi_release (u);
+		
+	return TRUE;
+}
+
 #define SEXP_PUBLIC_RSA  \
 	"(public-key"    \
 	"  (rsa"         \
@@ -219,6 +324,32 @@
 	return TRUE;
 }
 
+gboolean
+gkr_ssh_proto_read_public_v1 (GkrBuffer *req, gsize *offset, gcry_sexp_t *sexp)
+{
+	gcry_mpi_t n, e;
+	guint32 bits;
+	int gcry;
+	
+	if (!gkr_buffer_get_uint32 (req, *offset, offset, &bits))
+		return FALSE;
+	
+	if (!gkr_ssh_proto_read_mpi_v1 (req, offset, &e) ||
+	    !gkr_ssh_proto_read_mpi_v1 (req, offset, &n))
+	    	return FALSE;
+
+	gcry = gcry_sexp_build (sexp, NULL, SEXP_PUBLIC_RSA, n, e);
+	if (gcry) {
+		g_warning ("couldn't parse incoming public RSA key: %s", gcry_strerror (gcry));
+		return FALSE;
+	}
+
+	gcry_mpi_release (n);
+	gcry_mpi_release (e);
+	
+	return TRUE;	
+}
+
 #define SEXP_PRIVATE_DSA \
 	"(private-key"   \
 	"  (dsa"         \
@@ -392,6 +523,38 @@
 }
 
 gboolean
+gkr_ssh_proto_write_public_v1 (GkrBuffer *resp, gcry_sexp_t key)
+{
+	gboolean ret = FALSE;
+	gcry_mpi_t mpi;
+	unsigned int bits;
+	
+	/* This is always an RSA key. */
+	
+	/* Write out the number of bits of the key */
+	bits = gcry_pk_get_nbits (key);
+	g_return_val_if_fail (bits > 0, FALSE);
+	gkr_buffer_add_uint32 (resp, bits);
+
+	/* Write out the exponent */
+	ret = gkr_crypto_sexp_extract_mpi (key, &mpi, "rsa", "e", NULL);
+	g_return_val_if_fail (ret, FALSE);
+	ret = gkr_ssh_proto_write_mpi_v1 (resp, mpi);
+	gcry_mpi_release (mpi);
+	
+	if (!ret)
+		return ret;
+
+	/* Write out the public value */
+	ret = gkr_crypto_sexp_extract_mpi (key, &mpi, "rsa", "n", NULL);
+	g_return_val_if_fail (ret, FALSE);
+	ret = gkr_ssh_proto_write_mpi_v1 (resp, mpi);
+	gcry_mpi_release (mpi);
+	
+	return ret;
+}
+
+gboolean
 gkr_ssh_proto_write_signature_rsa (GkrBuffer *resp, gcry_sexp_t ssig)
 {
 	gboolean ret;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]