diff options
author | Stefan Walter <stefw@src.gnome.org> | 2008-03-17 01:14:46 +0000 |
---|---|---|
committer | Stefan Walter <stefw@src.gnome.org> | 2008-03-17 01:14:46 +0000 |
commit | f3413460f5a2cb4d8c09f2973d92fb33c5b2ac98 (patch) | |
tree | 4cd568bd04b62ceb66715e4ba0bb2ec1a4c1fc86 /common | |
parent | 7d18018e42f4306c19d61d9a4eacf089a5f870a2 (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.c | 69 | ||||
-rw-r--r-- | common/gkr-buffer.h | 25 | ||||
-rw-r--r-- | common/gkr-crypto.c | 258 | ||||
-rw-r--r-- | common/gkr-crypto.h | 28 |
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_*/ |