summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-10-27 00:06:56 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-10-27 00:06:56 +0200
commite056fd22f61b2881945bf6bc9389c243fbfcde4a (patch)
treeced31e7e2679d62afbb1a6cc1736b42c836d8edc
parent665a66c7f5f4128bac6bcec7f358a5919da3942e (diff)
parent06a02e2391625a09e194acf1c6d31aecf2266b8f (diff)
downloadncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.tar.gz
ncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.tar.xz
ncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.zip
Merge branch 'local'
Conflicts: lib/ncrypto_local.c
-rw-r--r--Makefile.am5
-rw-r--r--include/ncrypto/ncrypto.h34
-rw-r--r--lib/ncrypto_local.c273
-rw-r--r--tests/rsa.c4
-rw-r--r--tests/symm_signatures.c266
5 files changed, 574 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am
index 5c74dae..022099b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,7 @@ AM_CPPFLAGS = -I $(top_srcdir)/include $(GLIB_CFLAGS) $(NSS_CFLAGS) \
## Targets
lib_LTLIBRARIES = lib/libncrypto.la
pkginclude_HEADERS = include/ncrypto/ncrypto.h
-TESTS = tests/digests tests/rsa tests/symm_ciphers
+TESTS = tests/digests tests/rsa tests/symm_ciphers tests/symm_signatures
## Rules
noinst_PROGRAMS = $(TESTS)
@@ -52,3 +52,6 @@ tests_rsa_LDFLAGS = -no-install
tests_symm_ciphers_LDADD = lib/libncrypto.la $(GLIB_LIBS)
tests_symm_ciphers_LDFLAGS = -no-install
+
+tests_symm_signatures_LDADD = lib/libncrypto.la $(GLIB_LIBS)
+tests_symm_signatures_LDFLAGS = -no-install
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index aef6bb4..24d8e8e 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -183,4 +183,38 @@ CK_RV ncr_symm_cipher_decrypt (struct ncr_symm_cipher_session *sess, void *dest,
size_t *dest_size_ptr, const void *src,
size_t src_size);
+ /* Symmetric signatures */
+
+struct ncr_symm_signature_session;
+
+/* Session lifetime management. */
+CK_RV ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
+ CK_MECHANISM_TYPE mech);
+CK_RV ncr_symm_signature_free (struct ncr_symm_signature_session *sess);
+/* Use either ncr_symm_signature_sign_{init,update,final} (), or
+ ncr_symm_signature_{sign_init,sign} (). After finishing such a call
+ sequence, a new sequence can be started within the same session. Same for
+ verification sequences.
+
+ Symmetric signature mechanisms tend to use keys of type
+ CKK_GENERIC_SECRET. */
+CK_RV ncr_symm_signature_sign_init (struct ncr_symm_signature_session *sess,
+ struct ncr_symm_key *key);
+CK_RV ncr_symm_signature_sign_update (struct ncr_symm_signature_session *sess,
+ const void *data, size_t size);
+CK_RV ncr_symm_signature_sign_final (struct ncr_symm_signature_session *sess,
+ void *dest, size_t *size_ptr);
+CK_RV ncr_symm_signature_sign (struct ncr_symm_signature_session *sess,
+ void *dest, size_t *dest_size_ptr,
+ const void *data, size_t data_size);
+CK_RV ncr_symm_signature_verify_init (struct ncr_symm_signature_session *sess,
+ struct ncr_symm_key *key);
+CK_RV ncr_symm_signature_verify_update (struct ncr_symm_signature_session *sess,
+ const void *data, size_t size);
+CK_RV ncr_symm_signature_verify_final (struct ncr_symm_signature_session *sess,
+ const void *signature, size_t size);
+CK_RV ncr_symm_signature_verify (struct ncr_symm_signature_session *sess,
+ const void *signature, size_t signature_size,
+ const void *data, size_t data_size);
+
#endif
diff --git a/lib/ncrypto_local.c b/lib/ncrypto_local.c
index 72bc6fd..7062479 100644
--- a/lib/ncrypto_local.c
+++ b/lib/ncrypto_local.c
@@ -32,6 +32,7 @@ Red Hat author: Miloslav Trmač <mitr@redhat.com> */
#include <glib.h>
#include <openssl/evp.h>
+#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <ncrypto/ncrypto.h>
@@ -165,6 +166,12 @@ ncr_symm_key_generate (struct ncr_symm_key **key, CK_MECHANISM_TYPE mech,
value_size = 24;
break;
+ case CKM_GENERIC_SECRET_KEY_GEN:
+ type = CKK_GENERIC_SECRET;
+ g_return_val_if_fail (value_size <= SIZE_MAX - sizeof (*k),
+ CKR_HOST_MEMORY);
+ break;
+
default:
g_return_val_if_reached (CKR_MECHANISM_INVALID);
}
@@ -209,7 +216,7 @@ struct ncr_symm_cipher_session
EVP_CIPHER_CTX ctx;
CK_MECHANISM_TYPE mech;
size_t padding_size; /* Additional space to reserve for padding */
- _Bool encrypting;
+ bool encrypting;
/* Debugging only */
enum { NSCS_NEW, NSCS_INITIALIZED, NSCS_UPDATED, NSCS_FINISHED } state;
};
@@ -245,12 +252,12 @@ ncr_symm_cipher_free (struct ncr_symm_cipher_session *sess)
}
static CK_RV
-symm_cipher_init (struct ncr_symm_cipher_session *sess, _Bool encrypt,
+symm_cipher_init (struct ncr_symm_cipher_session *sess, bool encrypt,
struct ncr_symm_key *key, const void *param,
size_t param_size)
{
const EVP_CIPHER *type;
- _Bool padding;
+ bool padding;
g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
g_return_val_if_fail (sess->state == NSCS_NEW || sess->state == NSCS_FINISHED,
@@ -324,7 +331,7 @@ symm_cipher_init (struct ncr_symm_cipher_session *sess, _Bool encrypt,
}
static CK_RV
-symm_cipher_update (struct ncr_symm_cipher_session *sess, _Bool encrypt,
+symm_cipher_update (struct ncr_symm_cipher_session *sess, bool encrypt,
void *dest, size_t *dest_size_ptr, const void *src,
size_t src_size)
{
@@ -363,7 +370,7 @@ symm_cipher_update (struct ncr_symm_cipher_session *sess, _Bool encrypt,
/* EVP_CipherUpdate + EVP_CipherFinal_ex */
static CK_RV
do_symm_cipher_update_final (struct ncr_symm_cipher_session *sess,
- _Bool encrypt, void *dest, size_t *dest_size_ptr,
+ bool encrypt, void *dest, size_t *dest_size_ptr,
const void *src, size_t src_size)
{
int outl;
@@ -410,7 +417,7 @@ do_symm_cipher_update_final (struct ncr_symm_cipher_session *sess,
}
static CK_RV
-symm_cipher_final (struct ncr_symm_cipher_session *sess, _Bool encrypt,
+symm_cipher_final (struct ncr_symm_cipher_session *sess, bool encrypt,
void *dest, size_t *dest_size_ptr, const void *src,
size_t src_size)
{
@@ -424,7 +431,7 @@ symm_cipher_final (struct ncr_symm_cipher_session *sess, _Bool encrypt,
}
static CK_RV
-symm_cipher (struct ncr_symm_cipher_session *sess, _Bool encrypt, void *dest,
+symm_cipher (struct ncr_symm_cipher_session *sess, bool encrypt, void *dest,
size_t *dest_size_ptr, const void *src, size_t src_size)
{
g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
@@ -498,3 +505,255 @@ ncr_symm_cipher_decrypt (struct ncr_symm_cipher_session *sess, void *dest,
{
return symm_cipher (sess, false, dest, dest_size_ptr, src, src_size);
}
+
+ /* Symmetric signature handling */
+
+static const EVP_MD *
+symm_signature_evp_from_hmac_mech (CK_MECHANISM_TYPE mech)
+{
+ switch (mech)
+ {
+#define E(M, E) \
+ case CKM_##M##_HMAC: \
+ return EVP_##E ();
+ E (MD5, md5);
+ E (SHA_1, sha1);
+ E (SHA224, sha224);
+ E (SHA256, sha256);
+ E (SHA384, sha384);
+ E (SHA512, sha512);
+#undef E
+ default:
+ g_return_val_if_reached (NULL);
+ }
+}
+
+struct ncr_symm_signature_session
+{
+ HMAC_CTX ctx;
+ const EVP_MD *md;
+ size_t md_size;
+ bool signing;
+ /* Debugging only */
+ enum { NSSS_NEW, NSSS_INITIALIZED, NSSS_UPDATED, NSSS_FINISHED } state;
+};
+
+CK_RV
+ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
+ CK_MECHANISM_TYPE mech)
+{
+ struct ncr_symm_signature_session *s;
+ const EVP_MD *md;
+
+ g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD);
+
+ md = symm_signature_evp_from_hmac_mech (mech);
+ if (md == NULL)
+ return CKR_MECHANISM_INVALID;
+
+ s = malloc (sizeof (*s));
+ if (s == NULL)
+ return CKR_HOST_MEMORY;
+
+ HMAC_CTX_init (&s->ctx);
+ s->state = NSSS_NEW;
+ s->md = md;
+ s->md_size = EVP_MD_size (md);
+ g_assert (s->md_size <= EVP_MAX_MD_SIZE);
+ *sess = s;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_symm_signature_free (struct ncr_symm_signature_session *sess)
+{
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+
+ HMAC_CTX_cleanup (&sess->ctx);
+ free (sess);
+ return CKR_OK;
+}
+
+static CK_RV
+symm_signature_init (struct ncr_symm_signature_session *sess, bool sign,
+ struct ncr_symm_key *key)
+{
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_NEW || sess->state == NSSS_FINISHED,
+ CKR_OPERATION_ACTIVE);
+ g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
+
+ /* This is not assured, but holds for supported mechanisms. */
+ g_return_val_if_fail (key->type == CKK_GENERIC_SECRET,
+ CKR_KEY_TYPE_INCONSISTENT);
+
+ if (HMAC_Init_ex (&sess->ctx, key->value, key->size, sess->md, NULL) == 0)
+ return ckr_openssl ();
+
+ sess->signing = sign;
+ sess->state = NSSS_INITIALIZED;
+ return CKR_OK;
+}
+
+static CK_RV
+symm_signature_update (struct ncr_symm_signature_session *sess, bool sign,
+ const void *data, size_t size)
+{
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED
+ || sess->state == NSSS_UPDATED,
+ CKR_OPERATION_NOT_INITIALIZED);
+ g_return_val_if_fail (sess->signing == sign, CKR_OPERATION_NOT_INITIALIZED);
+
+ if (HMAC_Update (&sess->ctx, data, size) == 0)
+ return ckr_openssl ();
+
+ sess->state = NSSS_UPDATED;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_symm_signature_sign_init (struct ncr_symm_signature_session *sess,
+ struct ncr_symm_key *key)
+{
+ return symm_signature_init (sess, true, key);
+}
+
+CK_RV
+ncr_symm_signature_sign_update (struct ncr_symm_signature_session *sess,
+ const void *data, size_t size)
+{
+ return symm_signature_update (sess, true, data, size);
+}
+
+CK_RV
+ncr_symm_signature_sign_final (struct ncr_symm_signature_session *sess,
+ void *dest, size_t *size_ptr)
+{
+ int res;
+
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED
+ || sess->state == NSSS_UPDATED,
+ CKR_OPERATION_NOT_INITIALIZED);
+ g_return_val_if_fail (size_ptr != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess->signing == true, CKR_OPERATION_NOT_INITIALIZED);
+
+ if (dest == NULL)
+ {
+ *size_ptr = sess->md_size;
+ return CKR_OK;
+ }
+ if (*size_ptr < sess->md_size)
+ {
+ *size_ptr = sess->md_size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ *size_ptr = sess->md_size;
+
+ g_return_val_if_fail (dest != NULL, CKR_ARGUMENTS_BAD);
+
+ res = HMAC_Final (&sess->ctx, dest, NULL);
+ sess->state = NSSS_FINISHED;
+ return res ? CKR_OK : ckr_openssl ();
+}
+
+CK_RV
+ncr_symm_signature_sign (struct ncr_symm_signature_session *sess, void *dest,
+ size_t *dest_size_ptr, const void *data,
+ size_t data_size)
+{
+ int res;
+
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED,
+ CKR_OPERATION_NOT_INITIALIZED);
+ g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess->signing == true, CKR_OPERATION_NOT_INITIALIZED);
+
+ if (dest == NULL)
+ {
+ *dest_size_ptr = sess->md_size;
+ return CKR_OK;
+ }
+ if (*dest_size_ptr < sess->md_size)
+ {
+ *dest_size_ptr = sess->md_size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ *dest_size_ptr = sess->md_size;
+
+ g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD);
+
+ res = (HMAC_Update (&sess->ctx, data, data_size) != 0
+ && HMAC_Final (&sess->ctx, dest, NULL) != 0);
+ sess->state = NSSS_FINISHED;
+ return res ? CKR_OK : ckr_openssl ();
+}
+
+CK_RV
+ncr_symm_signature_verify_init (struct ncr_symm_signature_session *sess,
+ struct ncr_symm_key *key)
+{
+ return symm_signature_init (sess, false, key);
+}
+
+CK_RV
+ncr_symm_signature_verify_update (struct ncr_symm_signature_session *sess,
+ const void *data, size_t size)
+{
+ return symm_signature_update (sess, false, data, size);
+}
+
+CK_RV
+ncr_symm_signature_verify_final (struct ncr_symm_signature_session *sess,
+ const void *signature, size_t size)
+{
+ uint8_t buf[EVP_MAX_MD_SIZE];
+ int res;
+
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED
+ || sess->state == NSSS_UPDATED,
+ CKR_OPERATION_NOT_INITIALIZED);
+ g_return_val_if_fail (signature != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess->signing == false, CKR_OPERATION_NOT_INITIALIZED);
+
+ res = HMAC_Final (&sess->ctx, buf, NULL);
+ sess->state = NSSS_FINISHED;
+ if (res == 0)
+ return ckr_openssl ();
+ if (size != sess->md_size)
+ return CKR_SIGNATURE_LEN_RANGE;
+ if (memcmp (signature, buf, size) != 0)
+ return CKR_SIGNATURE_INVALID;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_symm_signature_verify (struct ncr_symm_signature_session *sess,
+ const void *signature, size_t signature_size,
+ const void *data, size_t data_size)
+{
+ uint8_t buf[EVP_MAX_MD_SIZE];
+ int res;
+
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED,
+ CKR_OPERATION_NOT_INITIALIZED);
+ g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (signature != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess->signing == false, CKR_OPERATION_NOT_INITIALIZED);
+
+ res = (HMAC_Update (&sess->ctx, data, data_size) != 0
+ && HMAC_Final (&sess->ctx, buf, NULL) != 0);
+ sess->state = NSSS_FINISHED;
+ if (res == 0)
+ return ckr_openssl ();
+ if (signature_size != sess->md_size)
+ return CKR_SIGNATURE_LEN_RANGE;
+ if (memcmp (signature, buf, signature_size) != 0)
+ return CKR_SIGNATURE_INVALID;
+ return CKR_OK;
+}
diff --git a/tests/rsa.c b/tests/rsa.c
index 9addcf4..224f5c1 100644
--- a/tests/rsa.c
+++ b/tests/rsa.c
@@ -88,6 +88,10 @@ main (void)
res = ncr_public_key_verify (CKM_RSA_PKCS, public, dest, dest_size, input,
sizeof (input));
assert (res == CKR_OK);
+ dest[0]++;
+ res = ncr_public_key_verify (CKM_RSA_PKCS, public, dest, dest_size, input,
+ sizeof (input));
+ assert (res != CKR_OK);
res = ncr_private_key_destroy (private);
assert (res == CKR_OK);
diff --git a/tests/symm_signatures.c b/tests/symm_signatures.c
new file mode 100644
index 0000000..17ca560
--- /dev/null
+++ b/tests/symm_signatures.c
@@ -0,0 +1,266 @@
+/* ncr_symm_signature_* tests.
+
+Copyright 2010 Red Hat, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+Red Hat author: Miloslav Trmač <mitr@redhat.com> */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <ncrypto/ncrypto.h>
+
+struct tv
+{
+ CK_MECHANISM_TYPE mech;
+ const uint8_t *input;
+ size_t input_size;
+ const uint8_t *key;
+ size_t key_size;
+ const uint8_t *output;
+ size_t output_size;
+};
+
+static const struct tv tvs[] =
+ {
+#define TV(M, IN, KEY, OUT) \
+ { \
+ (M), (const uint8_t *)(IN), sizeof (IN) - 1, \
+ (const uint8_t *)(KEY), sizeof (KEY) - 1, (const uint8_t *)(OUT), \
+ sizeof (OUT) - 1 \
+ }
+ TV (CKM_SHA_1_HMAC, "Sample #1",
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F",
+ "\x4F\x4C\xA3\xD5\xD6\x8B\xA7\xCC\x0A\x12\x08\xC9\xC6\x1E\x9C\x5D\xA0\x40\x3C\x0A"),
+ TV (CKM_SHA_1_HMAC, "Sample #2",
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43",
+ "\x09\x22\xD3\x40\x5F\xAA\x3D\x19\x4F\x82\xA4\x58\x30\x73\x7D\x5C\xC6\xC7\x5D\x24"),
+ TV (CKM_SHA_1_HMAC, "Sample #3",
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3",
+ "\xBC\xF4\x1E\xAB\x8B\xB2\xD8\x02\xF3\xD0\x5C\xAF\x7C\xB0\x92\xEC\xF8\xD1\xA3\xAA"),
+ TV (CKM_SHA_1_HMAC, "Sample #4",
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0",
+ "\x9E\xA8\x86\xEF\xE2\x68\xDB\xEC\xCE\x42\x0C\x75\x24\xDF\x32\xE0\x75\x1A\x2A\x26")
+#undef TV
+ };
+
+int
+main (void)
+{
+ struct ncr_symm_signature_session *sess;
+ struct ncr_symm_key *key;
+ uint8_t dest[256];
+ size_t i, j, k, dest_size;
+ CK_RV res;
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_signature_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_create (&key, CKK_GENERIC_SECRET, tvs[i].key,
+ tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_signature_sign_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_sign_update (sess, tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign_final (sess, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) == 0);
+
+ for (k = 0; k < 2; k++)
+ {
+ res = ncr_symm_signature_verify_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_verify_update (sess, tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+
+ memcpy (dest, tvs[i].output, tvs[i].output_size);
+ dest[0] += k;
+ res = ncr_symm_signature_verify_final (sess, dest,
+ tvs[i].output_size);
+ if (k == 0)
+ assert (res == CKR_OK);
+ else
+ assert (res == CKR_SIGNATURE_INVALID);
+ }
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_signature_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_create (&key, CKK_GENERIC_SECRET, tvs[i].key,
+ tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_signature_sign_init (sess, key);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign (sess, dest, &dest_size,
+ tvs[i].input, tvs[i].input_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) == 0);
+
+ for (k = 0; k < 2; k++)
+ {
+ res = ncr_symm_signature_verify_init (sess, key);
+ assert (res == CKR_OK);
+
+ memcpy (dest, tvs[i].output, tvs[i].output_size);
+ dest[0] += k;
+ res = ncr_symm_signature_verify (sess, dest, tvs[i].output_size,
+ tvs[i].input, tvs[i].input_size);
+ if (k == 0)
+ assert (res == CKR_OK);
+ else
+ assert (res == CKR_SIGNATURE_INVALID);
+ }
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_signature_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_generate (&key, CKM_GENERIC_SECRET_KEY_GEN,
+ tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_signature_sign_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_sign_update (sess, tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign_final (sess, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+
+ for (k = 0; k < 2; k++)
+ {
+ res = ncr_symm_signature_verify_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_verify_update (sess, tvs[i].input,
+ tvs[i].input_size);
+ assert (res == CKR_OK);
+
+ dest[0] += k;
+ res = ncr_symm_signature_verify_final (sess, dest,
+ tvs[i].output_size);
+ if (k == 0)
+ assert (res == CKR_OK);
+ else
+ assert (res == CKR_SIGNATURE_INVALID);
+ }
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_signature_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_generate (&key, CKM_GENERIC_SECRET_KEY_GEN,
+ tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
+ res = ncr_symm_signature_sign_init (sess, key);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign (sess, dest, &dest_size,
+ tvs[i].input, tvs[i].input_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+
+ for (k = 0; k < 2; k++)
+ {
+ res = ncr_symm_signature_verify_init (sess, key);
+ assert (res == CKR_OK);
+
+ dest[0] += k;
+ res = ncr_symm_signature_verify (sess, dest, tvs[i].output_size,
+ tvs[i].input, tvs[i].input_size);
+ if (k == 0)
+ assert (res == CKR_OK);
+ else
+ assert (res == CKR_SIGNATURE_INVALID);
+ }
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ return EXIT_SUCCESS;
+}