summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-10-04 21:25:21 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-10-04 21:25:21 +0200
commit566ee5e8a43f6f9c5705c9d154e89cf43759b77f (patch)
treeefd72b5c8422f192ebeb569036375469e5845ff5 /lib
parent91475817b3f08ebf76cee39271aa5a692c8930d5 (diff)
downloadncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.gz
ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.xz
ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.zip
Add basic digest support
Diffstat (limited to 'lib')
-rw-r--r--lib/ncrypto_local.c234
1 files changed, 234 insertions, 0 deletions
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 ();
+}