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 /lib | |
| parent | 91475817b3f08ebf76cee39271aa5a692c8930d5 (diff) | |
| download | ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.gz ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.tar.xz ncrypto-566ee5e8a43f6f9c5705c9d154e89cf43759b77f.zip | |
Add basic digest support
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ncrypto_local.c | 234 |
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 (); +} |
