From 99ebfdf37c218e6426438d0ac131ea77440e5a26 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 8 Sep 2015 18:00:48 +0200 Subject: [PATCH] Added support for CKU_CONTEXT_SPECIFIC. --- lib/ykpiv.c | 5 +++- ykcs11/mechanisms.c | 13 ++++++++++ ykcs11/mechanisms.h | 1 + ykcs11/openssl_utils.c | 7 ++++++ ykcs11/openssl_utils.h | 1 + ykcs11/ykcs11.c | 56 +++++++++++++++++++++++++++++++++--------- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index fc60d47..a152d11 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -602,7 +602,10 @@ static ykpiv_rc _general_authenticate(ykpiv_state *state, if(state->verbose) { fprintf(stderr, "Failed sign command with code %x.\n", sw); } - return YKPIV_GENERIC_ERROR; + if (sw == 0x6982) + return YKPIV_AUTHENTICATION_ERROR; + else + return YKPIV_GENERIC_ERROR; } /* skip the first 7c tag */ if(data[0] != 0x7c) { diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index 23285e8..ce1ef72 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -244,6 +244,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_SHA512_RSA_PKCS_PSS: // Finalize the hash rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -275,6 +276,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_SHA512_RSA_PKCS: // Finalize the hash add digest info rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -295,6 +297,7 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { case CKM_ECDSA_SHA256: // Finalize the hash rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid); + op_info->op.sign.md_ctx = NULL; if (rv != CKR_OK) return CKR_FUNCTION_FAILED; @@ -306,6 +309,16 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) { } } +CK_RV sign_mechanism_cleanup(op_info_t *op_info) { + + if (op_info->op.sign.md_ctx != NULL) { + do_md_cleanup(op_info->op.sign.md_ctx); + op_info->op.sign.md_ctx = NULL; + } + + return CKR_OK; +} + CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) { CK_ULONG i; diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h index 27bdced..c919dde 100644 --- a/ykcs11/mechanisms.h +++ b/ykcs11/mechanisms.h @@ -11,6 +11,7 @@ CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m); CK_RV apply_sign_mechanism_init(op_info_t *op_info); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); +CK_RV sign_mechanism_cleanup(op_info_t *op_info); CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 1756735..17ba0ae 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -557,3 +557,10 @@ CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len return CKR_OK; } + +CK_RV do_md_cleanup(ykcs11_md_ctx_t *ctx) { + + EVP_MD_CTX_destroy((EVP_MD_CTX *) ctx); + + return CKR_OK; +} diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 14f8a28..6fef0ff 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -32,5 +32,6 @@ CK_RV do_pkcs_pss(RSA *key, CK_BYTE_PTR in, CK_ULONG in_len, int nid, CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx); CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int *nid); +CK_RV do_md_cleanup(ykcs11_md_ctx_t *ctx); #endif diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c795d17..b20f06f 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -147,7 +147,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( ) { DIN; - int i; + CK_ULONG i; int j; if (piv_state == NULL) { @@ -765,6 +765,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)( break; case CKU_CONTEXT_SPECIFIC: + if (op_info.type == YKCS11_NOOP) { + DBG(("No operation in progress. Context specific user is forbidden.")); + return CKR_USER_TYPE_INVALID; + } + if (op_info.type == YKCS11_SIGN) { + return C_Login(hSession, CKU_USER, pPin, ulPinLen); + } + else + return C_Login(hSession, CKU_SO, pPin, ulPinLen); + default: return CKR_USER_TYPE_INVALID; } @@ -1627,13 +1637,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( { DIN; + ykpiv_rc piv_rv; + CK_RV rv; + if (op_info.type != YKCS11_SIGN) { DBG(("Signature operation not initialized")); - return CKR_OPERATION_NOT_INITIALIZED; + rv = CKR_OPERATION_NOT_INITIALIZED; + goto sign_out; } // TODO: check other conditions - ykpiv_rc r; // TODO: delete this ? if (pSignature == NULL_PTR) { // Just return the size of the signature @@ -1650,7 +1663,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) { DBG(("Unable to perform signing operation step")); - return CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation + rv = CKR_FUNCTION_FAILED; // TODO: every error in here must stop and clear the signing operation + goto sign_out; } } else { @@ -1658,7 +1672,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( // RSA_X_509 if (ulDataLen > (op_info.op.sign.key_len / 8)) { DBG(("Data must be shorter than key length (%lu bits)", op_info.op.sign.key_len)); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } } else { @@ -1666,7 +1681,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( if (ulDataLen > 128) { // Specs say ECDSA only supports 1024 bit DBG(("Meximum data length for ECDSA is 128 bytes")); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } } @@ -1674,10 +1690,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( memcpy(op_info.buf, pData, ulDataLen); } - if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) { DBG(("Unable to finalize signing operation")); - return CKR_FUNCTION_FAILED; + rv = CKR_FUNCTION_FAILED; + goto sign_out; } DBG(("Using key %lx", op_info.op.sign.key_id)); @@ -1685,10 +1701,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); *pulSignatureLen = sizeof(op_info.buf); - if ((r = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0)) != YKPIV_OK) { - DBG(("Sign error, %s", ykpiv_strerror(r))); - return CKR_FUNCTION_FAILED; + piv_rv = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0); + if (piv_rv != YKPIV_OK) { + if (piv_rv == YKPIV_AUTHENTICATION_ERROR) { + DBG(("Operation requires authentication or touch")); + rv = CKR_USER_NOT_LOGGED_IN; + goto sign_out; + } + else { + DBG(("Sign error, %s", ykpiv_strerror(piv_rv))); + rv = CKR_FUNCTION_FAILED; + goto sign_out; + } } + DBG(("Got %lu bytes back", *pulSignatureLen)); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); @@ -1703,8 +1729,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( op_info.type = YKCS11_NOOP; // TODO: anything to clear here? + rv = CKR_OK; + + sign_out: + op_info.type = YKCS11_NOOP; + sign_mechanism_cleanup(&op_info); + DOUT; - return CKR_OK; + return rv; } CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)(