diff options
| author | Miloslav Trmač <mitr@redhat.com> | 2010-10-04 21:25:21 +0200 |
|---|---|---|
| committer | Miloslav Trmač <mitr@redhat.com> | 2010-10-04 21:25:21 +0200 |
| commit | 566ee5e8a43f6f9c5705c9d154e89cf43759b77f (patch) | |
| tree | efd72b5c8422f192ebeb569036375469e5845ff5 | |
| parent | 91475817b3f08ebf76cee39271aa5a692c8930d5 (diff) | |
| download | ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.gz ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.xz ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.zip | |
Add basic digest support
| -rw-r--r-- | Makefile.am | 13 | ||||
| -rw-r--r-- | configure.ac | 1 | ||||
| -rw-r--r-- | include/ncrypto/ncrypto.h | 56 | ||||
| -rw-r--r-- | lib/ncrypto_local.c | 234 | ||||
| -rw-r--r-- | tests/digests.c | 160 |
5 files changed, 461 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index e19052e..2d4a0ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,12 +29,19 @@ versionedincludedir = $(includedir)/ncrypto-0/ncrypto ACLOCAL_AMFLAGS = -I m4 -AM_CPPFLAGS = -I $(top_srcdir)/include $(NSS_CFLAGS) $(GLIB_CFLAGS) +AM_CPPFLAGS = -I $(top_srcdir)/include $(GLIB_CFLAGS) $(NSS_CFLAGS) \ + $(OPENSSL_CFLAGS) ## Targets lib_LTLIBRARIES = lib/libncrypto.la pkginclude_HEADERS = include/ncrypto/ncrypto.h +TESTS = tests/digests ## Rules -lib_libncrypto_la_SOURCES = lib/ncrypto.c -lib_libncrypto_la_LDFLAGS = -version-info 0:0:0
\ No newline at end of file +noinst_PROGRAMS = $(TESTS) + +lib_libncrypto_la_SOURCES = lib/ncrypto.c lib/ncrypto_local.c +lib_libncrypto_la_LDFLAGS = -version-info 0:0:0 $(OPENSSL_LIBS) + +tests_digests_LDADD = lib/libncrypto.la $(GLIB_LIBS) +tests_digests_LDFLAGS = -no-install diff --git a/configure.ac b/configure.ac index ed53177..fc29b65 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,7 @@ PKG_CHECK_MODULES(GLIB,[glib-2.0]) AC_DEFINE(G_DISABLE_DEPRECATED,, [Stay away from deprecated glib functionality.]) PKG_CHECK_MODULES(NSS,[nss]) +PKG_CHECK_MODULES(OPENSSL,[libcrypto]) # Checks for header files. diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h index e69de29..5da7949 100644 --- a/include/ncrypto/ncrypto.h +++ b/include/ncrypto/ncrypto.h @@ -0,0 +1,56 @@ +/* libncrypto interface. + +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> */ + +#ifndef NCRYPTO_H__ +#define NCRYPTO_H__ + +#include <stddef.h> + +#include <pkcs11.h> + +struct ncr_digest_session; + +/* Session lifetime management. */ +CK_RV ncr_digest_alloc (struct ncr_digest_session **sess, + CK_MECHANISM_TYPE mech); +CK_RV ncr_digest_free (struct ncr_digest_session *sess); +/* Use either: ncr_digest_{init,update*,final} (), or + ncr_{digest_init,digest} (). After finishing such a call sequence, a new + sequence can be started within the same session. */ +CK_RV ncr_digest_init (struct ncr_digest_session *sess); +CK_RV ncr_digest_update (struct ncr_digest_session *sess, const void *data, + size_t size); +CK_RV ncr_digest_final (struct ncr_digest_session *sess, void *dest, + size_t *size_ptr); +CK_RV ncr_digest (struct ncr_digest_session *sess, void *dest, + size_t *dest_size_ptr, const void *data, size_t data_size); + +CK_RV ncr_digest_standalone (CK_MECHANISM_TYPE mech, void *dest, + size_t *dest_size_ptr, const void *data, + size_t data_size); + +#endif diff --git a/lib/ncrypto_local.c b/lib/ncrypto_local.c new file mode 100644 index 0000000..be05dc4 --- /dev/null +++ b/lib/ncrypto_local.c @@ -0,0 +1,234 @@ +/* In-process crypto implementation. + +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 <config.h> + +#include <glib.h> +#include <openssl/evp.h> + +#include <ncrypto/ncrypto.h> + + /* Helpers */ + +static CK_RV +ckr_openssl (void) +{ + /* FIXME: better error handling? This will be replaced anyway. */ + return CKR_GENERAL_ERROR; +} + + /* Digest handling */ + +static const EVP_MD * +digest_evp_from_mech (CK_MECHANISM_TYPE mech) +{ + switch (mech) + { +#define E(M, E) \ + case CKM_##M: \ + 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_digest_session +{ + EVP_MD_CTX ctx; + const EVP_MD *md; + /* Debugging only */ + enum { NDS_NEW, NDS_INITIALIZED, NDS_UPDATED, NDS_FINISHED } state; +}; + +CK_RV +ncr_digest_alloc (struct ncr_digest_session **sess, CK_MECHANISM_TYPE mech) +{ + struct ncr_digest_session *s; + const EVP_MD *md; + + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + + md = digest_evp_from_mech (mech); + if (md == NULL) + return CKR_MECHANISM_INVALID; + + s = malloc (sizeof (*s)); + if (s == NULL) + return CKR_HOST_MEMORY; + + EVP_MD_CTX_init (&s->ctx); + s->state = NDS_NEW; + s->md = md; + *sess = s; + return CKR_OK; +} + +CK_RV +ncr_digest_free (struct ncr_digest_session *sess) +{ + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + + EVP_MD_CTX_cleanup (&sess->ctx); + return CKR_OK; +} + +CK_RV +ncr_digest_init (struct ncr_digest_session *sess) +{ + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (sess->state == NDS_NEW || sess->state == NDS_FINISHED, + CKR_OPERATION_ACTIVE); + + if (EVP_DigestInit_ex (&sess->ctx, sess->md, NULL) == 0) + return ckr_openssl (); + + sess->state = NDS_INITIALIZED; + return CKR_OK; +} + +CK_RV +ncr_digest_update (struct ncr_digest_session *sess, const void *data, + size_t size) +{ + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (sess->state == NDS_INITIALIZED + || sess->state == NDS_UPDATED, + CKR_OPERATION_NOT_INITIALIZED); + + if (EVP_DigestUpdate (&sess->ctx, data, size) == 0) + return ckr_openssl (); + + sess->state = NDS_UPDATED; + return CKR_OK; +} + +CK_RV +ncr_digest_final (struct ncr_digest_session *sess, void *dest, + size_t *size_ptr) +{ + size_t md_size; + + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (sess->state == NDS_INITIALIZED + || sess->state == NDS_UPDATED, + CKR_OPERATION_NOT_INITIALIZED); + + md_size = EVP_MD_size (sess->md); + if (dest == NULL) + { + *size_ptr = md_size; + return CKR_OK; + } + if (*size_ptr < md_size) + { + *size_ptr = md_size; + g_return_val_if_reached (CKR_BUFFER_TOO_SMALL); + } + *size_ptr = md_size; + + g_return_val_if_fail (dest != NULL, CKR_ARGUMENTS_BAD); + + if (EVP_DigestFinal_ex (&sess->ctx, dest, NULL) == 0) + return ckr_openssl (); + + sess->state = NDS_FINISHED; + return CKR_OK; +} + +CK_RV +ncr_digest (struct ncr_digest_session *sess, void *dest, size_t *dest_size_ptr, + const void *data, size_t data_size) +{ + size_t md_size; + + g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (sess->state == NDS_INITIALIZED, + CKR_OPERATION_NOT_INITIALIZED); + g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD); + + md_size = EVP_MD_size (sess->md); + if (dest == NULL) + { + *dest_size_ptr = md_size; + return CKR_OK; + } + if (*dest_size_ptr < md_size) + { + *dest_size_ptr = md_size; + g_return_val_if_reached (CKR_BUFFER_TOO_SMALL); + } + *dest_size_ptr = md_size; + + g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD); + + if (EVP_DigestUpdate(&sess->ctx, data, data_size) == 0 + || EVP_DigestFinal_ex(&sess->ctx, dest, NULL) == 0) + return ckr_openssl (); + + sess->state = NDS_FINISHED; + return CKR_OK; +} + +CK_RV +ncr_digest_standalone (CK_MECHANISM_TYPE mech, void *dest, + size_t *dest_size_ptr, const void *data, + size_t data_size) +{ + const EVP_MD *md; + size_t md_size; + + g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD); + + md = digest_evp_from_mech (mech); + if (md == NULL) + return CKR_MECHANISM_INVALID; + + md_size = EVP_MD_size (md); + if (dest == NULL) + { + *dest_size_ptr = md_size; + return CKR_OK; + } + if (*dest_size_ptr < md_size) + { + *dest_size_ptr = md_size; + g_return_val_if_reached (CKR_BUFFER_TOO_SMALL); + } + *dest_size_ptr = md_size; + + g_return_val_if_fail (data != NULL, CKR_ARGUMENTS_BAD); + + return EVP_Digest(data, data_size, dest, NULL, md, NULL) != 0 + ? CKR_OK : ckr_openssl (); +} diff --git a/tests/digests.c b/tests/digests.c new file mode 100644 index 0000000..8013698 --- /dev/null +++ b/tests/digests.c @@ -0,0 +1,160 @@ +/* ncr_digest_* 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 *output; + size_t output_size; +}; + +static const struct tv tvs[] = + { +#define TV(M, IN, OUT) \ + { \ + (M), (const uint8_t *)(IN), sizeof (IN) - 1, (const uint8_t *)(OUT), \ + sizeof (OUT) - 1 \ + } + TV (CKM_MD5, "", + "\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\x09\x98\xEC\xF8\x42\x7E"), + TV (CKM_MD5, "a", + "\x0C\xC1\x75\xB9\xC0\xF1\xB6\xA8\x31\xC3\x99\xE2\x69\x77\x26\x61"), + TV (CKM_MD5, "abc", + "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72"), + TV (CKM_MD5, "message digest", + "\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0"), + TV (CKM_MD5, "abcdefghijklmnopqrstuvwxyz", + "\xC3\xFC\xD3\xD7\x61\x92\xE4\x00\x7D\xFB\x49\x6C\xCA\x67\xE1\x3B"), + TV (CKM_MD5, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "\xD1\x74\xAB\x98\xD2\x77\xD9\xF5\xA5\x61\x1C\x2C\x9F\x41\x9D\x9F"), + TV (CKM_MD5, + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "\x57\xED\xF4\xA2\x2B\xE3\xC9\x55\xAC\x49\xDA\x2E\x21\x07\xB6\x7A"), + + TV (CKM_SHA_1, "abc", + "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d"), + TV (CKM_SHA_1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1"), + + TV (CKM_SHA224, "abc", + "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7"), + TV (CKM_SHA224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25"), + + TV (CKM_SHA256, "abc", + "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad"), + TV (CKM_SHA256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"), + + TV (CKM_SHA384, "abc", + "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7"), + TV (CKM_SHA384, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39"), + + TV (CKM_SHA512, "abc", + "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f"), + TV (CKM_SHA512, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09"), + + + +#undef TV + }; + +int +main (void) +{ + struct ncr_digest_session *sess; + uint8_t dest[256]; + size_t i, j, dest_size; + CK_RV res; + + for (i = 0; i < G_N_ELEMENTS (tvs); i++) + { + dest_size = sizeof (dest); + res = ncr_digest_standalone (tvs[i].mech, 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 (i = 0; i < G_N_ELEMENTS (tvs); i++) + { + res = ncr_digest_alloc (&sess, tvs[i].mech); + assert (res == CKR_OK); + for (j = 0; j < 2; j++) + { + res = ncr_digest_init (sess); + assert (res == CKR_OK); + + res = ncr_digest_update (sess, tvs[i].input, tvs[i].input_size); + assert (res == CKR_OK); + + dest_size = sizeof (dest); + res = ncr_digest_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); + } + res = ncr_digest_free (sess); + assert (res == CKR_OK); + } + + for (i = 0; i < G_N_ELEMENTS (tvs); i++) + { + res = ncr_digest_alloc (&sess, tvs[i].mech); + assert (res == CKR_OK); + for (j = 0; j < 2; j++) + { + res = ncr_digest_init (sess); + assert (res == CKR_OK); + + dest_size = sizeof (dest); + res = ncr_digest (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); + } + res = ncr_digest_free (sess); + assert (res == CKR_OK); + } + + return EXIT_SUCCESS; +} |
