[gnome-keyring/dbus-api] [pkcs11] Factor out padding functionality, and add pkcs7 padding.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-keyring/dbus-api] [pkcs11] Factor out padding functionality, and add pkcs7 padding.
- Date: Thu, 19 Nov 2009 18:13:46 +0000 (UTC)
commit 28f2ff8044477d2e3fe9e5b7b0269217c47eb925
Author: Stef Walter <stef memberwebs com>
Date: Wed Nov 18 21:14:40 2009 +0000
[pkcs11] Factor out padding functionality, and add pkcs7 padding.
Factor out the padding stuff into its own file gck-padding.[ch]
and implement pkcs7 padding which we'll need shortly.
pkcs11/gck/Makefile.am | 1 +
pkcs11/gck/gck-crypto.c | 46 ++++---
pkcs11/gck/gck-crypto.h | 9 +-
pkcs11/gck/gck-mechanism-rsa.c | 175 +----------------------
pkcs11/gck/gck-mechanism-rsa.h | 33 +----
pkcs11/gck/gck-padding.c | 296 +++++++++++++++++++++++++++++++++++++++
pkcs11/gck/gck-padding.h | 86 +++++++++++
pkcs11/gck/tests/Makefile.am | 1 +
pkcs11/gck/tests/test-padding.c | 182 ++++++++++++++++++++++++
tests/gtest-helpers.h | 5 +
10 files changed, 608 insertions(+), 226 deletions(-)
---
diff --git a/pkcs11/gck/Makefile.am b/pkcs11/gck/Makefile.am
index fc9f983..9802eae 100644
--- a/pkcs11/gck/Makefile.am
+++ b/pkcs11/gck/Makefile.am
@@ -41,6 +41,7 @@ libgck_la_SOURCES = \
gck-memory-store.c gck-memory-store.h \
gck-module.c gck-module.h gck-module-ep.h \
gck-object.c gck-object.h \
+ gck-padding.c gck-padding.h \
gck-private-xsa-key.c gck-private-xsa-key.h \
gck-public-xsa-key.c gck-public-xsa-key.h \
gck-secret.c gck-secret.h \
diff --git a/pkcs11/gck/gck-crypto.c b/pkcs11/gck/gck-crypto.c
index db139fd..1d2a9c3 100644
--- a/pkcs11/gck/gck-crypto.c
+++ b/pkcs11/gck/gck-crypto.c
@@ -38,28 +38,32 @@
*/
CK_RV
-gck_crypto_data_to_sexp (const gchar *format, guint nbits, GckCryptoPadding padding,
+gck_crypto_data_to_sexp (const gchar *format, guint nbits, GckPadding padding,
CK_BYTE_PTR data, CK_ULONG n_data, gcry_sexp_t *sexp)
{
- guchar *padded = NULL;
+ gpointer padded = NULL;
gcry_error_t gcry;
gcry_mpi_t mpi;
gsize n_padded;
+ gsize block;
g_assert (format);
g_assert (sexp);
g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+ block = (nbits + 7) / 8;
+ if (n_data > block)
+ return CKR_DATA_LEN_RANGE;
+
if (padding) {
- padded = (padding) (nbits, data, n_data, &n_padded);
- if (!padded)
+ if (!(padding) (g_realloc, block, data, n_data, &padded, &n_padded))
return CKR_DATA_LEN_RANGE;
}
/* Prepare the input s expression */
gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG,
- padded ? padded : data,
+ padded ? padded : data,
padded ? n_padded : n_data, NULL);
g_free (padded);
@@ -76,15 +80,17 @@ gck_crypto_data_to_sexp (const gchar *format, guint nbits, GckCryptoPadding padd
CK_RV
gck_crypto_sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data,
- CK_ULONG *n_data, GckCryptoPadding padding, ...)
+ CK_ULONG *n_data, GckPadding padding, ...)
{
gcry_sexp_t at = NULL;
gsize n_block, offset, len;
gcry_mpi_t mpi = NULL;
+ gpointer padded;
guchar *block;
va_list va;
+ gboolean ret;
gcry_error_t gcry;
-
+
g_assert (sexp);
g_assert (data);
g_assert (n_data);
@@ -102,7 +108,7 @@ gck_crypto_sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data,
mpi = gcry_sexp_nth_mpi (at, 1, GCRYMPI_FMT_USG);
g_return_val_if_fail (at != NULL, CKR_GENERAL_ERROR);
gcry_sexp_release (at);
-
+
/* Print out the MPI into the end of a temporary buffer */
n_block = (bits + 7) / 8;
gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
@@ -115,16 +121,16 @@ gck_crypto_sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data,
g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
g_return_val_if_fail (len == n_block - offset, CKR_GENERAL_ERROR);
gcry_mpi_release (mpi);
-
+
/* Pad it properly if necessary */
if (padding != NULL) {
- guchar *padded = (padding) (bits, block, n_block, &n_block);
+ ret = (padding) (g_realloc, n_block, block, n_block, &padded, &n_block);
g_free (block);
- if (!padded)
+ if (ret == FALSE)
return CKR_DATA_LEN_RANGE;
block = padded;
}
-
+
/* Now stuff it into the output buffer */
if (n_block > *n_data)
return CKR_BUFFER_TOO_SMALL;
@@ -132,7 +138,7 @@ gck_crypto_sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data,
memcpy (data, block, n_block);
*n_data = n_block;
g_free (block);
-
+
return CKR_OK;
}
@@ -177,11 +183,11 @@ gck_crypto_encrypt_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR da
switch (mech) {
case CKM_RSA_PKCS:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_encrypt (sexp, gck_mechanism_rsa_pad_two, data, n_data, encrypted, n_encrypted);
+ rv = gck_mechanism_rsa_encrypt (sexp, gck_padding_pkcs1_pad_02, data, n_data, encrypted, n_encrypted);
break;
case CKM_RSA_X_509:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_encrypt (sexp, gck_mechanism_rsa_pad_raw, data, n_data, encrypted, n_encrypted);
+ rv = gck_mechanism_rsa_encrypt (sexp, gck_padding_zero_pad, data, n_data, encrypted, n_encrypted);
break;
default:
/* Again shouldn't be reached */
@@ -231,7 +237,7 @@ gck_crypto_decrypt_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR en
switch (mech) {
case CKM_RSA_PKCS:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_decrypt (sexp, gck_mechanism_rsa_unpad_two, encrypted, n_encrypted, data, n_data);
+ rv = gck_mechanism_rsa_decrypt (sexp, gck_padding_pkcs1_unpad_02, encrypted, n_encrypted, data, n_data);
break;
case CKM_RSA_X_509:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
@@ -286,11 +292,11 @@ gck_crypto_sign_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
switch (mech) {
case CKM_RSA_PKCS:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_sign (sexp, gck_mechanism_rsa_pad_one, data, n_data, signature, n_signature);
+ rv = gck_mechanism_rsa_sign (sexp, gck_padding_pkcs1_pad_01, data, n_data, signature, n_signature);
break;
case CKM_RSA_X_509:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_sign (sexp, gck_mechanism_rsa_pad_raw, data, n_data, signature, n_signature);
+ rv = gck_mechanism_rsa_sign (sexp, gck_padding_zero_pad, data, n_data, signature, n_signature);
break;
case CKM_DSA:
g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
@@ -345,11 +351,11 @@ gck_crypto_verify_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR dat
switch (mech) {
case CKM_RSA_PKCS:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_verify (sexp, gck_mechanism_rsa_pad_one, data, n_data, signature, n_signature);
+ rv = gck_mechanism_rsa_verify (sexp, gck_padding_pkcs1_pad_01, data, n_data, signature, n_signature);
break;
case CKM_RSA_X_509:
g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
- rv = gck_mechanism_rsa_verify (sexp, gck_mechanism_rsa_pad_raw, data, n_data, signature, n_signature);
+ rv = gck_mechanism_rsa_verify (sexp, gck_padding_zero_pad, data, n_data, signature, n_signature);
break;
case CKM_DSA:
g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
diff --git a/pkcs11/gck/gck-crypto.h b/pkcs11/gck/gck-crypto.h
index a32a95e..b4c40d3 100644
--- a/pkcs11/gck/gck-crypto.h
+++ b/pkcs11/gck/gck-crypto.h
@@ -22,6 +22,7 @@
#ifndef GCKCRYPTO_H_
#define GCKCRYPTO_H_
+#include "gck-padding.h"
#include "gck-types.h"
#include "pkcs11/pkcs11.h"
@@ -30,10 +31,6 @@
#include <gcrypt.h>
-typedef guchar* (*GckCryptoPadding) (guint n_modulus, const guchar* raw,
- gsize n_raw, gsize *n_padded);
-
-
void gck_crypto_initialize (void);
CK_RV gck_crypto_prepare (GckSession *session,
@@ -112,12 +109,12 @@ CK_RV gck_crypto_sexp_to_data (gcry_sex
guint bits,
CK_BYTE_PTR data,
CK_ULONG *n_data,
- GckCryptoPadding padding,
+ GckPadding padding,
...) G_GNUC_NULL_TERMINATED;
CK_RV gck_crypto_data_to_sexp (const gchar *format,
guint nbits,
- GckCryptoPadding padding,
+ GckPadding padding,
CK_BYTE_PTR data,
CK_ULONG n_data,
gcry_sexp_t *sexp);
diff --git a/pkcs11/gck/gck-mechanism-rsa.c b/pkcs11/gck/gck-mechanism-rsa.c
index fea02f7..2d3a253 100644
--- a/pkcs11/gck/gck-mechanism-rsa.c
+++ b/pkcs11/gck/gck-mechanism-rsa.c
@@ -28,82 +28,11 @@
#include "egg/egg-secure-memory.h"
/* ----------------------------------------------------------------------------
- * INTERNAL
- */
-
-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);
- }
-}
-
-static guchar*
-unpad_rsa_pkcs1 (guchar bt, guint n_modulus, const guchar* padded,
- gsize n_padded, gsize *n_raw)
-{
- const guchar *at;
- guint check;
- guchar *raw;
-
- check = (n_modulus + 7) / 8;
-
- /* The absolute minimum size including padding */
- g_return_val_if_fail (check >= 3 + 8, NULL);
-
- if (n_padded != check)
- 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;
-}
-
-/* ----------------------------------------------------------------------------
* PUBLIC
*/
CK_RV
-gck_mechanism_rsa_encrypt (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data,
+gck_mechanism_rsa_encrypt (gcry_sexp_t sexp, GckPadding padding, CK_BYTE_PTR data,
CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted)
{
gcry_sexp_t splain, sdata;
@@ -149,7 +78,7 @@ gck_mechanism_rsa_encrypt (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_P
}
CK_RV
-gck_mechanism_rsa_decrypt (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR encrypted,
+gck_mechanism_rsa_decrypt (gcry_sexp_t sexp, GckPadding padding, CK_BYTE_PTR encrypted,
CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data)
{
gcry_sexp_t splain, sdata;
@@ -197,7 +126,7 @@ gck_mechanism_rsa_decrypt (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_P
}
CK_RV
-gck_mechanism_rsa_sign (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data,
+gck_mechanism_rsa_sign (gcry_sexp_t sexp, GckPadding padding, CK_BYTE_PTR data,
CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
{
gcry_sexp_t ssig, sdata;
@@ -242,7 +171,7 @@ gck_mechanism_rsa_sign (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR
}
CK_RV
-gck_mechanism_rsa_verify (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data,
+gck_mechanism_rsa_verify (gcry_sexp_t sexp, GckPadding padding, CK_BYTE_PTR data,
CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature)
{
gcry_sexp_t ssig, sdata;
@@ -289,99 +218,3 @@ gck_mechanism_rsa_verify (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PT
return CKR_OK;
}
-
-/* ----------------------------------------------------------------------------
- * PADDING FUNCTIONS
- */
-
-
-guchar*
-gck_mechanism_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 + 7) / 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*
-gck_mechanism_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 + 7) / 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;
-}
-
-guchar*
-gck_mechanism_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 + 7) / 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;
-}
-
-guchar*
-gck_mechanism_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*
-gck_mechanism_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/pkcs11/gck/gck-mechanism-rsa.h b/pkcs11/gck/gck-mechanism-rsa.h
index b263a57..fd8e7e0 100644
--- a/pkcs11/gck/gck-mechanism-rsa.h
+++ b/pkcs11/gck/gck-mechanism-rsa.h
@@ -37,56 +37,31 @@ static const CK_MECHANISM_TYPE GCK_CRYPTO_RSA_MECHANISMS[] = {
};
CK_RV gck_mechanism_rsa_encrypt (gcry_sexp_t sexp,
- GckCryptoPadding padding,
+ GckPadding padding,
CK_BYTE_PTR data,
CK_ULONG n_data,
CK_BYTE_PTR encrypted,
CK_ULONG_PTR n_encrypted);
CK_RV gck_mechanism_rsa_decrypt (gcry_sexp_t sexp,
- GckCryptoPadding padding,
+ GckPadding padding,
CK_BYTE_PTR encrypted,
CK_ULONG n_encrypted,
CK_BYTE_PTR data,
CK_ULONG_PTR n_data);
CK_RV gck_mechanism_rsa_sign (gcry_sexp_t sexp,
- GckCryptoPadding padding,
+ GckPadding padding,
CK_BYTE_PTR data,
CK_ULONG n_data,
CK_BYTE_PTR signature,
CK_ULONG_PTR n_signature);
CK_RV gck_mechanism_rsa_verify (gcry_sexp_t sexp,
- GckCryptoPadding padding,
+ GckPadding padding,
CK_BYTE_PTR data,
CK_ULONG n_data,
CK_BYTE_PTR signature,
CK_ULONG n_signature);
-guchar* gck_mechanism_rsa_pad_raw (guint bits,
- const guchar* raw,
- gsize n_raw,
- gsize *n_padded);
-
-guchar* gck_mechanism_rsa_pad_one (guint bits,
- const guchar* raw,
- gsize n_raw,
- gsize *n_padded);
-
-guchar* gck_mechanism_rsa_pad_two (guint bits,
- const guchar* raw,
- gsize n_raw,
- gsize *n_padded);
-
-guchar* gck_mechanism_rsa_unpad_one (guint bits,
- const guchar *padded,
- gsize n_padded,
- gsize *n_raw);
-
-guchar* gck_mechanism_rsa_unpad_two (guint bits,
- const guchar* padded,
- gsize n_padded,
- gsize *n_raw);
-
#endif /* GCK_MECHANISM_RSA_H_ */
diff --git a/pkcs11/gck/gck-padding.c b/pkcs11/gck/gck-padding.c
new file mode 100644
index 0000000..094eda2
--- /dev/null
+++ b/pkcs11/gck/gck-padding.c
@@ -0,0 +1,296 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gck-padding.h"
+#include "gck-sexp.h"
+
+#include "egg/egg-libgcrypt.h"
+#include "egg/egg-secure-memory.h"
+
+/* ----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+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);
+ }
+}
+
+static gboolean
+unpad_pkcs1 (guchar bt, GckAllocator alloc, gsize block, const guchar* padded,
+ gsize n_padded, gpointer *raw, gsize *n_raw)
+{
+ const guchar *at;
+
+ if (block && n_padded % block != 0)
+ return FALSE;
+
+ /* Check the header */
+ if (padded[0] != 0x00 || padded[1] != bt)
+ return FALSE;
+
+ /* The first zero byte after the header */
+ at = memchr (padded + 2, 0x00, n_padded - 2);
+ if (!at)
+ return FALSE;
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ ++at;
+ *n_raw = n_padded - (at - padded);
+ if (raw) {
+ *raw = (alloc) (NULL, MAX (*n_raw, 1));
+ if (*raw == NULL)
+ return FALSE;
+ memcpy (*raw, at, *n_raw);
+ }
+
+ return TRUE;
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+gboolean
+gck_padding_zero_pad (GckAllocator alloc, gsize block, gconstpointer raw,
+ gsize n_raw, gpointer *padded, gsize *n_padded)
+{
+ guchar *pad;
+ gsize n_pad;
+
+ /*
+ * 0x00 0x00 0x00 ... 0x?? 0x?? 0x?? ...
+ * padding data
+ */
+
+ g_return_val_if_fail (block != 0, FALSE);
+
+ *n_padded = ((n_raw + (block - 1)) / block) * block;
+ g_assert (n_raw <= *n_padded);
+ n_pad = *n_padded - n_raw;
+ g_assert (n_pad < block);
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ if (padded) {
+ *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
+ if (pad == NULL)
+ return FALSE;
+ memset (pad, 0x00, n_pad);
+ memcpy (pad + n_pad, raw, n_raw);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gck_padding_pkcs1_pad_01 (GckAllocator alloc, gsize block, gconstpointer raw,
+ gsize n_raw, gpointer *padded, gsize *n_padded)
+{
+ guchar *pad;
+ gsize n_pad;
+
+ /*
+ * 0x00 0x01 0xFF 0xFF ... 0x00 0x?? 0x?? 0x?? ...
+ * type padding data
+ */
+
+ g_return_val_if_fail (block != 0, FALSE);
+ g_return_val_if_fail (block > 3, FALSE);
+
+ *n_padded = ((n_raw + 3 + (block - 1)) / block) * block;
+ g_assert (n_raw <= *n_padded);
+ n_pad = *n_padded - n_raw;
+ g_assert (n_pad <= block);
+ g_assert (n_pad >= 3);
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ if (padded) {
+ *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
+ if (pad == NULL)
+ return FALSE;
+ pad[0] = 0; /* Prefix */
+ pad[1] = 1; /* Block type */
+ memset (pad + 2, 0xFF, n_pad - 3);
+ pad[n_pad - 1] = 0;
+ memcpy (pad + n_pad, raw, n_raw);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gck_padding_pkcs1_pad_02 (GckAllocator alloc, gsize block, gconstpointer raw,
+ gsize n_raw, gpointer *padded, gsize *n_padded)
+{
+ guchar *pad;
+ gsize n_pad;
+
+ /*
+ * 0x00 0x01 0x?? 0x?? ... 0x00 0x?? 0x?? 0x?? ...
+ * type padding data
+ */
+
+ g_return_val_if_fail (block != 0, FALSE);
+ g_return_val_if_fail (block > 3, FALSE);
+
+ *n_padded = ((n_raw + 3 + (block - 1)) / block) * block;
+ g_assert (n_raw <= *n_padded);
+ n_pad = *n_padded - n_raw;
+ g_assert (n_pad <= block);
+ g_assert (n_pad >= 3);
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ if (padded) {
+ *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
+ if (pad == NULL)
+ return FALSE;
+ pad[0] = 0; /* Prefix */
+ pad[1] = 2; /* Block type */
+ fill_random_nonzero (pad + 2, n_pad - 3);
+ pad[n_pad - 1] = 0;
+ memcpy (pad + n_pad, raw, n_raw);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gck_padding_pkcs1_unpad_01 (GckAllocator alloc, gsize block, gconstpointer padded,
+ gsize n_padded, gpointer *raw, gsize *n_raw)
+{
+ return unpad_pkcs1 (0x01, alloc, block, padded, n_padded, raw, n_raw);
+}
+
+gboolean
+gck_padding_pkcs1_unpad_02 (GckAllocator alloc, gsize block, gconstpointer padded,
+ gsize n_padded, gpointer *raw, gsize *n_raw)
+{
+ return unpad_pkcs1 (0x02, alloc, block, padded, n_padded, raw, n_raw);
+}
+
+gboolean
+gck_padding_pkcs7_pad (GckAllocator alloc, gsize block, gconstpointer raw,
+ gsize n_raw, gpointer *padded, gsize *n_padded)
+{
+ guchar *pad;
+ gsize n_pad;
+
+ g_return_val_if_fail (block != 0, FALSE);
+ g_return_val_if_fail (block < 256, FALSE);
+
+ *n_padded = ((n_raw + block) / block) * block;
+ g_assert (n_raw < *n_padded);
+ n_pad = *n_padded - n_raw;
+ g_assert (n_pad > 0 && n_pad <= block);
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ if (padded) {
+ *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
+ if (pad == NULL)
+ return FALSE;
+ memcpy (pad, raw, n_raw);
+ memset (pad + n_raw, n_pad, n_pad);
+ }
+
+ return TRUE;
+}
+
+gboolean
+gck_padding_pkcs7_unpad (GckAllocator alloc, gsize block, gconstpointer padded,
+ gsize n_padded, gpointer *raw, gsize *n_raw)
+{
+ const guchar *pad;
+ gsize n_pad, i;
+
+ if (n_padded == 0)
+ return FALSE;
+
+ pad = padded;
+ n_pad = pad[n_padded - 1];
+
+ /* Validate the padding */
+ if (n_pad == 0 || n_pad > 256)
+ return FALSE;
+ if (n_pad > n_padded)
+ return FALSE;
+ if (block && n_pad > block)
+ return FALSE;
+ for (i = n_padded - n_pad; i < n_padded; ++i) {
+ if (pad[i] != n_pad)
+ return FALSE;
+ }
+
+ *n_raw = n_padded - n_pad;
+
+ if (alloc == NULL)
+ alloc = g_realloc;
+
+ if (raw) {
+ *raw = (alloc) (NULL, MAX (*n_raw, 1));
+ if (*raw == NULL)
+ return FALSE;
+ memcpy (*raw, pad, *n_raw);
+ }
+
+ return TRUE;
+}
diff --git a/pkcs11/gck/gck-padding.h b/pkcs11/gck/gck-padding.h
new file mode 100644
index 0000000..718e656
--- /dev/null
+++ b/pkcs11/gck/gck-padding.h
@@ -0,0 +1,86 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef GCK_PADDING_H_
+#define GCK_PADDING_H_
+
+#include <glib.h>
+
+typedef gpointer (*GckAllocator) (gpointer,
+ gsize);
+
+typedef gboolean (*GckPadding) (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer input,
+ gsize n_input,
+ gpointer *output,
+ gsize *n_output);
+
+gboolean gck_padding_zero_pad (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer raw,
+ gsize n_raw,
+ gpointer *padded,
+ gsize *n_padded);
+
+gboolean gck_padding_pkcs1_pad_01 (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer raw,
+ gsize n_raw,
+ gpointer *padded,
+ gsize *n_padded);
+
+gboolean gck_padding_pkcs1_pad_02 (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer raw,
+ gsize n_raw,
+ gpointer *padded,
+ gsize *n_padded);
+
+gboolean gck_padding_pkcs1_unpad_01 (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer padded,
+ gsize n_padded,
+ gpointer *raw,
+ gsize *n_raw);
+
+gboolean gck_padding_pkcs1_unpad_02 (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer padded,
+ gsize n_padded,
+ gpointer *raw,
+ gsize *n_raw);
+
+gboolean gck_padding_pkcs7_pad (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer raw,
+ gsize n_raw,
+ gpointer *padded,
+ gsize *n_padded);
+
+gboolean gck_padding_pkcs7_unpad (GckAllocator alloc,
+ gsize n_block,
+ gconstpointer raw,
+ gsize n_raw,
+ gpointer *padded,
+ gsize *n_padded);
+
+#endif /* GCK_PADDING_H_ */
diff --git a/pkcs11/gck/tests/Makefile.am b/pkcs11/gck/tests/Makefile.am
index 1a16b2b..a9cad0e 100644
--- a/pkcs11/gck/tests/Makefile.am
+++ b/pkcs11/gck/tests/Makefile.am
@@ -6,6 +6,7 @@ asn1-def-test.h: test.asn
UNIT_AUTO = \
unit-test-attributes.c \
unit-test-sexp.c \
+ test-padding.c \
unit-test-data-asn1.c \
unit-test-data-der.c \
unit-test-object.c \
diff --git a/pkcs11/gck/tests/test-padding.c b/pkcs11/gck/tests/test-padding.c
new file mode 100644
index 0000000..1ab63c9
--- /dev/null
+++ b/pkcs11/gck/tests/test-padding.c
@@ -0,0 +1,182 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-padding.c: Test padding functionality
+
+ Copyright (C) 2007 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef memberwebs com>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include "gck/gck-padding.h"
+
+#include <gcrypt.h>
+
+static void
+test_padding (GckPadding padding, gsize block, gconstpointer input,
+ gsize n_input, gconstpointer output, gsize n_output)
+{
+ gpointer result;
+ gsize n_result;
+
+ if (!(padding) (NULL, block, input, n_input, &result, &n_result)) {
+ g_assert (output == NULL);
+ return;
+ }
+
+ g_assert (result != NULL);
+ g_assert_cmpsize (n_output, ==, n_result);
+ g_assert (memcmp (output, result, n_output) == 0);
+ g_free (result);
+
+ /* Now make sure it can tell us the right length */
+ if (!(padding) (NULL, block, input, n_input, NULL, &n_result))
+ g_assert_not_reached ();
+
+ g_assert_cmpsize (n_output, ==, n_result);
+}
+
+DEFINE_TEST(zero_padding)
+{
+ guchar padded[] = { 0x00, 0x00, 0x00, 0x00, 'T', 'E', 'S', 'T' };
+ gchar raw[] = "TEST";
+ test_padding (gck_padding_zero_pad, 8, raw, 4, padded, 8);
+}
+
+DEFINE_TEST(zero_padding_no_data)
+{
+ guchar padded[] = { };
+ gchar raw[] = "";
+ test_padding (gck_padding_zero_pad, 8, raw, 0, padded, 0);
+}
+
+DEFINE_TEST(pkcs1_one_padding)
+{
+ guchar padded[] = { 0x00, 0x01, 0xFF, 0x00, 'T', 'E', 'S', 'T' };
+ gchar raw[] = "TEST";
+ test_padding (gck_padding_pkcs1_pad_01, 8, raw, 4, padded, 8);
+ test_padding (gck_padding_pkcs1_unpad_01, 8, padded, 8, raw, 4);
+}
+
+DEFINE_TEST(pkcs1_one_padding_no_data)
+{
+ guchar padded[] = { 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
+ gchar raw[] = "";
+ test_padding (gck_padding_pkcs1_pad_01, 8, raw, 0, padded, 8);
+ test_padding (gck_padding_pkcs1_unpad_01, 8, padded, 8, raw, 0);
+}
+
+DEFINE_TEST(pkcs1_two_padding)
+{
+ guchar padded[] = { 0x00, 0x02, 0x77, 0x66, 0x55, 0x00, 'T', 'E', };
+ gchar raw[] = "TE";
+ guchar *result;
+ gpointer vesult;
+ gsize n_result;
+
+ test_padding (gck_padding_pkcs1_unpad_02, 8, padded, 8, raw, 2);
+
+ /* PKCS#1 02 padding is unpredictable */
+ if (!gck_padding_pkcs1_pad_02 (NULL, 8, raw, 2, &vesult, &n_result))
+ g_assert_not_reached ();
+ result = vesult;
+ g_assert (result != NULL);
+ g_assert_cmpsize (n_result, ==, 8);
+ g_assert (result[0] == 0x00);
+ g_assert (result[1] == 0x02);
+ g_assert (result[2] != 0x00);
+ g_assert (result[3] != 0x00);
+ g_assert (result[4] != 0x00);
+ g_assert (result[5] == 0x00);
+ g_assert (result[6] == 'T');
+ g_assert (result[7] == 'E');
+}
+
+DEFINE_TEST(pkcs1_padding_invalid_prefix)
+{
+ guchar padded[] = { 0x01, 0x04, 0x04, 0x04 };
+ test_padding (gck_padding_pkcs1_unpad_01, 4, padded, 4, NULL, 0);
+}
+
+DEFINE_TEST(pkcs1_padding_invalid_type)
+{
+ guchar padded[] = { 0x00, 0x03, 0xFF, 0x00, 'T', 'E', 'S', 'T' };
+ test_padding (gck_padding_pkcs1_unpad_01, 8, padded, 8, NULL, 0);
+}
+
+DEFINE_TEST(pkcs1_padding_invalid_no_zero)
+{
+ guchar padded[] = { 0x00, 0x01, 0xFF, 0xFF, 'T', 'E', 'S', 'T' };
+ test_padding (gck_padding_pkcs1_unpad_01, 8, padded, 8, NULL, 0);
+}
+
+DEFINE_TEST(pkcs1_padding_invalid_length)
+{
+ guchar padded[] = { 0x00, 0x01, 0xFF, 0xFF, 'T', 'E', 'S' };
+ test_padding (gck_padding_pkcs1_unpad_01, 8, padded, 7, NULL, 0);
+}
+
+DEFINE_TEST(pkcs7_padding)
+{
+ guchar padded[] = { 'T', 'E', 'S', 'T', 0x04, 0x04, 0x04, 0x04 };
+ gchar raw[] = "TEST";
+
+ test_padding (gck_padding_pkcs7_pad, 8, raw, 4, padded, 8);
+ test_padding (gck_padding_pkcs7_unpad, 8, padded, 8, raw, 4);
+}
+
+DEFINE_TEST(pkcs7_padding_equal_block)
+{
+ guchar padded[] = { 'T', 'E', 'S', 'T', 'T', 'E', 'S', 'T', 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 };
+ gchar raw[] = "TESTTEST";
+
+ test_padding (gck_padding_pkcs7_pad, 8, raw, 8, padded, 16);
+ test_padding (gck_padding_pkcs7_unpad, 8, padded, 16, raw, 8);
+}
+
+DEFINE_TEST(pkcs7_padding_zero)
+{
+ guchar padded[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 };
+ gchar raw[] = "";
+
+ test_padding (gck_padding_pkcs7_pad, 8, raw, 0, padded, 8);
+ test_padding (gck_padding_pkcs7_unpad, 8, padded, 8, raw, 0);
+}
+
+DEFINE_TEST(pkcs7_padding_invalid_zero)
+{
+ guchar padded[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ test_padding (gck_padding_pkcs7_unpad, 8, padded, 8, NULL, 0);
+}
+
+DEFINE_TEST(pkcs7_padding_invalid_too_long)
+{
+ guchar padded[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 };
+ test_padding (gck_padding_pkcs7_unpad, 4, padded, 8, NULL, 0);
+ test_padding (gck_padding_pkcs7_unpad, 4, padded, 4, NULL, 0);
+}
+
+DEFINE_TEST(pkcs7_padding_invalid_different)
+{
+ guchar padded[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+ test_padding (gck_padding_pkcs7_unpad, 8, padded, 8, NULL, 0);
+}
diff --git a/tests/gtest-helpers.h b/tests/gtest-helpers.h
index 82ec6e7..2716d5b 100644
--- a/tests/gtest-helpers.h
+++ b/tests/gtest-helpers.h
@@ -87,4 +87,9 @@ void test_external_fail (void);
/* #define DEFINE_ABORT(x) void abort_x(void *__unused G_GNUC_UNUSED, gconstpointer __data G_GNUC_UNUSED)' */
+#ifndef g_assert_cmpsize
+#define g_assert_cmpsize(a, o, b) \
+ g_assert_cmpuint ((guint)(a), o, (guint)(b))
+#endif
+
#endif /* GTEST_HELPERS_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]