summaryrefslogtreecommitdiffstats
path: root/lib
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 /lib
parent665a66c7f5f4128bac6bcec7f358a5919da3942e (diff)
parent06a02e2391625a09e194acf1c6d31aecf2266b8f (diff)
downloadncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.tar.gz
ncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.tar.xz
ncrypto-e056fd22f61b2881945bf6bc9389c243fbfcde4a.zip
Merge branch 'local'
Conflicts: lib/ncrypto_local.c
Diffstat (limited to 'lib')
-rw-r--r--lib/ncrypto_local.c273
1 files changed, 266 insertions, 7 deletions
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;
+}