diff options
| author | Miloslav Trmač <mitr@redhat.com> | 2010-10-27 00:06:56 +0200 |
|---|---|---|
| committer | Miloslav Trmač <mitr@redhat.com> | 2010-10-27 00:06:56 +0200 |
| commit | e056fd22f61b2881945bf6bc9389c243fbfcde4a (patch) | |
| tree | ced31e7e2679d62afbb1a6cc1736b42c836d8edc /lib | |
| parent | 665a66c7f5f4128bac6bcec7f358a5919da3942e (diff) | |
| parent | 06a02e2391625a09e194acf1c6d31aecf2266b8f (diff) | |
| download | ncrypto-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.c | 273 |
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; +} |
