summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStefan Walter <stefw@src.gnome.org>2008-03-17 01:14:46 +0000
committerStefan Walter <stefw@src.gnome.org>2008-03-17 01:14:46 +0000
commitf3413460f5a2cb4d8c09f2973d92fb33c5b2ac98 (patch)
tree4cd568bd04b62ceb66715e4ba0bb2ec1a4c1fc86 /common
parent7d18018e42f4306c19d61d9a4eacf089a5f870a2 (diff)
Move RSA padding functionality into a more accessible location.
* 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 svn path=/trunk/; revision=1122
Diffstat (limited to 'common')
-rw-r--r--common/gkr-buffer.c69
-rw-r--r--common/gkr-buffer.h25
-rw-r--r--common/gkr-crypto.c258
-rw-r--r--common/gkr-crypto.h28
4 files changed, 342 insertions, 38 deletions
diff --git a/common/gkr-buffer.c b/common/gkr-buffer.c
index b55a5bcd..4c0257e6 100644
--- a/common/gkr-buffer.c
+++ b/common/gkr-buffer.c
@@ -192,14 +192,14 @@ gkr_buffer_resize (GkrBuffer *buffer, size_t len)
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 @@ gkr_buffer_get_byte (GkrBuffer *buffer, size_t offset,
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 @@ gkr_buffer_add_byte_array (GkrBuffer *buffer, const unsigned char *val,
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
diff --git a/common/gkr-buffer.h b/common/gkr-buffer.h
index 71df5ae2..4dd72a65 100644
--- a/common/gkr-buffer.h
+++ b/common/gkr-buffer.h
@@ -102,8 +102,8 @@ int gkr_buffer_append (GkrBuffer *buffer,
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 @@ int gkr_buffer_get_uint32 (GkrBuffer *buffer,
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_add_stringv (GkrBuffer *buffer,
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);
diff --git a/common/gkr-crypto.c b/common/gkr-crypto.c
index 46d8bb32..24e76456 100644
--- a/common/gkr-crypto.c
+++ b/common/gkr-crypto.c
@@ -698,15 +698,78 @@ gkr_crypto_sexp_extract_mpi (gcry_sexp_t sexp, gcry_mpi_t *mpi, ...)
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 @@ gkr_crypto_sexp_extract_mpi_aligned (gcry_sexp_t sexp, guchar* block, gsize n_bl
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 @@ gkr_crypto_skey_private_to_public (gcry_sexp_t privkey, gcry_sexp_t *pubkey)
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);
+}
diff --git a/common/gkr-crypto.h b/common/gkr-crypto.h
index faa42eb7..4a5b78bc 100644
--- a/common/gkr-crypto.h
+++ b/common/gkr-crypto.h
@@ -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 @@ gcry_sexp_t gkr_crypto_sexp_get_child (gcry_sexp_t sexp, ...)
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 @@ gkrid gkr_crypto_skey_make_id (gcry_sexp_t s_key);
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_*/