summaryrefslogtreecommitdiff
path: root/usr/lib/pkcs11/cca_stdll/sign_mgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/lib/pkcs11/cca_stdll/sign_mgr.c')
-rw-r--r--usr/lib/pkcs11/cca_stdll/sign_mgr.c658
1 files changed, 658 insertions, 0 deletions
diff --git a/usr/lib/pkcs11/cca_stdll/sign_mgr.c b/usr/lib/pkcs11/cca_stdll/sign_mgr.c
new file mode 100644
index 0000000..c5778f8
--- /dev/null
+++ b/usr/lib/pkcs11/cca_stdll/sign_mgr.c
@@ -0,0 +1,658 @@
+/*
+ * Licensed materials, Property of IBM Corp.
+ *
+ * openCryptoki CCA token
+ *
+ * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006
+ *
+ */
+
+
+// File: sign_mgr.c
+//
+// Signature manager routines
+//
+
+#include <pthread.h>
+
+#include <string.h> // for memcmp() et al
+#include <stdlib.h>
+
+#include "cca_stdll.h"
+
+#include "pkcs11types.h"
+#include "defs.h"
+#include "host_defs.h"
+#include "h_extern.h"
+#include "tok_spec_struct.h"
+
+
+//
+//
+CK_RV
+sign_mgr_init( SESSION * sess,
+ SIGN_VERIFY_CONTEXT * ctx,
+ CK_MECHANISM * mech,
+ CK_BBOOL recover_mode,
+ CK_OBJECT_HANDLE key )
+{
+ OBJECT * key_obj = NULL;
+ CK_ATTRIBUTE * attr = NULL;
+ CK_BYTE * ptr = NULL;
+ CK_KEY_TYPE keytype;
+ CK_OBJECT_CLASS class;
+ CK_BBOOL flag;
+ CK_RV rc;
+
+
+ if (!sess || !ctx){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->active != FALSE){
+ st_err_log(31, __FILE__, __LINE__);
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ // key usage restrictions
+ //
+ rc = object_mgr_find_in_map1( key, &key_obj );
+ if (rc != CKR_OK){
+ st_err_log(18, __FILE__, __LINE__);
+ return CKR_KEY_HANDLE_INVALID;
+ }
+ // is key allowed to generate signatures?
+ //
+ rc = template_attribute_find( key_obj->template, CKA_SIGN, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ flag = *(CK_BBOOL *)attr->pValue;
+ if (flag != TRUE){
+ st_err_log(85, __FILE__, __LINE__);
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ }
+
+
+ // is the mechanism supported? is the key type correct? is a
+ // parameter present if required? is the key size allowed?
+ // is the key allowed to generate signatures?
+ //
+ switch (mech->mechanism) {
+ case CKM_RSA_X_509:
+ case CKM_RSA_PKCS:
+ {
+ if (mech->ulParameterLen != 0){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ keytype = *(CK_KEY_TYPE *)attr->pValue;
+ if (keytype != CKK_RSA){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ // must be a PRIVATE key
+ //
+ flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr );
+ if (flag == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ class = *(CK_OBJECT_CLASS *)attr->pValue;
+
+ // if it's not a private RSA key then we have an internal failure...means
+ // that somehow a public key got assigned a CKA_SIGN attribute
+ //
+ if (class != CKO_PRIVATE_KEY){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ // PKCS #11 doesn't allow multi-part RSA operations
+ //
+ ctx->context_len = 0;
+ ctx->context = NULL;
+ }
+ break;
+
+#if !(NOMD2)
+ case CKM_MD2_RSA_PKCS:
+#endif
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ {
+ if (mech->ulParameterLen != 0){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ keytype = *(CK_KEY_TYPE *)attr->pValue;
+ if (keytype != CKK_RSA){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ // must be a PRIVATE key operation
+ //
+ flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr );
+ if (flag == FALSE){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ else
+ class = *(CK_OBJECT_CLASS *)attr->pValue;
+
+ if (class != CKO_PRIVATE_KEY){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ ctx->context_len = sizeof(RSA_DIGEST_CONTEXT);
+ ctx->context = (CK_BYTE *)malloc(sizeof(RSA_DIGEST_CONTEXT));
+ if (!ctx->context){
+ st_err_log(0, __FILE__, __LINE__);
+ return CKR_HOST_MEMORY;
+ }
+ memset( ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT));
+ }
+ break;
+
+
+#if !(NODSA)
+ case CKM_DSA:
+ {
+ if (mech->ulParameterLen != 0){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ keytype = *(CK_KEY_TYPE *)attr->pValue;
+ if (keytype != CKK_DSA){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ // must be a PRIVATE key
+ //
+ flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr );
+ if (flag == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else
+ class = *(CK_OBJECT_CLASS *)attr->pValue;
+
+ // if it's not a private RSA key then we have an internal failure...means
+ // that somehow a public key got assigned a CKA_SIGN attribute
+ //
+ if (class != CKO_PRIVATE_KEY){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ // PKCS #11 doesn't allow multi-part DSA operations
+ //
+ ctx->context_len = 0;
+ ctx->context = NULL;
+ }
+ break;
+#endif
+
+#if !(NOMD2)
+ case CKM_MD2_HMAC:
+#endif
+ case CKM_MD5_HMAC:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA256_HMAC:
+ {
+ if (mech->ulParameterLen != 0){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ keytype = *(CK_KEY_TYPE *)attr->pValue;
+ if (keytype != CKK_GENERIC_SECRET){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ // PKCS #11 doesn't allow multi-part HMAC operations
+ //
+ ctx->context_len = 0;
+ ctx->context = NULL;
+ }
+ break;
+
+#if !(NOMD2)
+ case CKM_MD2_HMAC_GENERAL:
+#endif
+ case CKM_MD5_HMAC_GENERAL:
+ case CKM_SHA_1_HMAC_GENERAL:
+ case CKM_SHA256_HMAC_GENERAL:
+ {
+ CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
+
+ if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+#if !(NOMD2)
+ if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+#endif
+
+ if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if ((mech->mechanism == CKM_SHA256_HMAC_GENERAL) && (*param > 32)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ keytype = *(CK_KEY_TYPE *)attr->pValue;
+ if (keytype != CKK_GENERIC_SECRET){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ // PKCS #11 doesn't allow multi-part HMAC operations
+ //
+ ctx->context_len = 0;
+ ctx->context = NULL;
+ }
+ break;
+
+ case CKM_SSL3_MD5_MAC:
+ case CKM_SSL3_SHA1_MAC:
+ {
+ CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
+
+ if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ // FIXME - Netscape sets the parameter == 16. PKCS #11 limit is 8
+ //
+ if (mech->mechanism == CKM_SSL3_MD5_MAC) {
+ if (*param < 4 || *param > 16){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ }
+
+ if (mech->mechanism == CKM_SSL3_SHA1_MAC) {
+ if (*param < 4 || *param > 20){
+ st_err_log(29, __FILE__, __LINE__);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ }
+
+ rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr );
+ if (rc == FALSE){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ else {
+ class = *(CK_OBJECT_CLASS *)attr->pValue;
+ if (class != CKO_SECRET_KEY){
+ st_err_log(20, __FILE__, __LINE__);
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+
+ ctx->context_len = sizeof(SSL3_MAC_CONTEXT);
+ ctx->context = (CK_BYTE *)malloc(sizeof(SSL3_MAC_CONTEXT));
+ if (!ctx->context){
+ st_err_log(0, __FILE__, __LINE__);
+ return CKR_HOST_MEMORY;
+ }
+ memset( ctx->context, 0x0, sizeof(SSL3_MAC_CONTEXT));
+ }
+ break;
+
+ default:
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+ }
+
+
+ if (mech->ulParameterLen > 0) {
+ ptr = (CK_BYTE *)malloc(mech->ulParameterLen);
+ if (!ptr){
+ st_err_log(0, __FILE__, __LINE__);
+ return CKR_HOST_MEMORY;
+ }
+ memcpy( ptr, mech->pParameter, mech->ulParameterLen );
+ }
+
+ ctx->key = key;
+ ctx->mech.ulParameterLen = mech->ulParameterLen;
+ ctx->mech.mechanism = mech->mechanism;
+ ctx->mech.pParameter = ptr;
+ ctx->multi = FALSE;
+ ctx->active = TRUE;
+ ctx->recover = recover_mode;
+
+ return CKR_OK;
+}
+
+
+//
+//
+CK_RV
+sign_mgr_cleanup( SIGN_VERIFY_CONTEXT *ctx )
+{
+ if (!ctx){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ ctx->key = 0;
+ ctx->mech.ulParameterLen = 0;
+ ctx->mech.mechanism = 0;
+ ctx->multi = FALSE;
+ ctx->active = FALSE;
+ ctx->recover = FALSE;
+ ctx->context_len = 0;
+
+ if (ctx->mech.pParameter) {
+ free( ctx->mech.pParameter );
+ ctx->mech.pParameter = NULL;
+ }
+
+ if (ctx->context) {
+ free( ctx->context );
+ ctx->context = NULL;
+ }
+
+ return CKR_OK;
+}
+
+
+//
+//
+CK_RV
+sign_mgr_sign( SESSION * sess,
+ CK_BBOOL length_only,
+ SIGN_VERIFY_CONTEXT * ctx,
+ CK_BYTE * in_data,
+ CK_ULONG in_data_len,
+ CK_BYTE * out_data,
+ CK_ULONG * out_data_len )
+{
+ if (!sess || !ctx){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->active == FALSE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ if (ctx->recover == TRUE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // if the caller just wants the signature length, there is no reason to
+ // specify the input data. I just need the input data length
+ //
+ if ((length_only == FALSE) && (!in_data || !out_data)){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->multi == TRUE){
+ st_err_log(31, __FILE__, __LINE__);
+ return CKR_OPERATION_ACTIVE;
+ }
+ switch (ctx->mech.mechanism) {
+ case CKM_RSA_PKCS:
+ return rsa_pkcs_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#if 0
+ case CKM_RSA_X_509:
+ return rsa_x509_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#endif
+#if !(NOMD2)
+ case CKM_MD2_RSA_PKCS:
+#endif
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ return rsa_hash_pkcs_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+
+#if !(NODSA)
+ case CKM_DSA:
+ return dsa_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#endif
+
+#if !(NOMD2)
+ case CKM_MD2_HMAC:
+ case CKM_MD2_HMAC_GENERAL:
+ return md2_hmac_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#endif
+
+ case CKM_MD5_HMAC:
+ case CKM_MD5_HMAC_GENERAL:
+ return md5_hmac_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA_1_HMAC_GENERAL:
+ return sha1_hmac_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+
+ case CKM_SHA256_HMAC:
+ case CKM_SHA256_HMAC_GENERAL:
+ return sha2_hmac_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+
+ case CKM_SSL3_MD5_MAC:
+ case CKM_SSL3_SHA1_MAC:
+ return ssl3_mac_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+
+ default:
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+}
+
+
+//
+//
+CK_RV
+sign_mgr_sign_update( SESSION * sess,
+ SIGN_VERIFY_CONTEXT * ctx,
+ CK_BYTE * in_data,
+ CK_ULONG in_data_len )
+{
+ if (!sess || !ctx || !in_data){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+
+ if (ctx->active == FALSE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ if (ctx->recover == TRUE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ ctx->multi = TRUE;
+
+ switch (ctx->mech.mechanism) {
+#if !(NOMD2)
+ case CKM_MD2_RSA_PKCS:
+#endif
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ return rsa_hash_pkcs_sign_update( sess, ctx, in_data, in_data_len );
+
+ case CKM_SSL3_MD5_MAC:
+ case CKM_SSL3_SHA1_MAC:
+ return ssl3_mac_sign_update( sess, ctx, in_data, in_data_len );
+
+ default:
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+ }
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+}
+
+
+//
+//
+CK_RV
+sign_mgr_sign_final( SESSION * sess,
+ CK_BBOOL length_only,
+ SIGN_VERIFY_CONTEXT * ctx,
+ CK_BYTE * signature,
+ CK_ULONG * sig_len )
+{
+ if (!sess || !ctx){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->active == FALSE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ if (ctx->recover == TRUE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ switch (ctx->mech.mechanism) {
+#if !(NOMD2)
+ case CKM_MD2_RSA_PKCS:
+#endif
+ case CKM_MD5_RSA_PKCS:
+ case CKM_SHA1_RSA_PKCS:
+ return rsa_hash_pkcs_sign_final( sess, length_only, ctx, signature, sig_len );
+
+ case CKM_SSL3_MD5_MAC:
+ case CKM_SSL3_SHA1_MAC:
+ return ssl3_mac_sign_final( sess, length_only, ctx, signature, sig_len );
+
+ default:
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+}
+
+
+//
+//
+CK_RV
+sign_mgr_sign_recover( SESSION * sess,
+ CK_BBOOL length_only,
+ SIGN_VERIFY_CONTEXT * ctx,
+ CK_BYTE * in_data,
+ CK_ULONG in_data_len,
+ CK_BYTE * out_data,
+ CK_ULONG * out_data_len )
+{
+ if (!sess || !ctx){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->active == FALSE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ if (ctx->recover == FALSE){
+ st_err_log(32, __FILE__, __LINE__);
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // if the caller just wants the signature length, there is no reason to
+ // specify the input data. I just need the input data length
+ //
+ if ((length_only == FALSE) && (!in_data || !out_data)){
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (ctx->multi == TRUE){
+ st_err_log(31, __FILE__, __LINE__);
+ return CKR_OPERATION_ACTIVE;
+ }
+ switch (ctx->mech.mechanism) {
+ case CKM_RSA_PKCS:
+ // we can use the same sign mechanism to do sign-recover
+ //
+ return rsa_pkcs_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#if 0
+ case CKM_RSA_X_509:
+ return rsa_x509_sign( sess, length_only, ctx,
+ in_data, in_data_len,
+ out_data, out_data_len );
+#endif
+ default:
+ st_err_log(28, __FILE__, __LINE__);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ st_err_log(4, __FILE__, __LINE__, __FUNCTION__);
+ return CKR_FUNCTION_FAILED;
+}