/* * COPYRIGHT (c) International Business Machines Corp. 2001-2017 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this * software constitutes recipient's acceptance of CPL-1.0 terms which can be * found in the file LICENSE file or at * https://opensource.org/licenses/cpl1.0.php */ // File: verify_mgr.c // // Verify manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV verify_mgr_init(STDLL_TokData_t *tokdata, 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) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // key usage restrictions // rc = object_mgr_find_in_map1(tokdata, key, &key_obj, READ_LOCK); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } if (recover_mode) { // is key allowed to verify signatures where the data can be // recovered from the signature? rc = template_attribute_find(key_obj->template, CKA_VERIFY_RECOVER, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VERIFY_RECOVER for the key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } } else { // is key allowed to verify signatures where the signature is an // appendix to the data? rc = template_attribute_find(key_obj->template, CKA_VERIFY, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VERIFY for the key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } } flag = *(CK_BBOOL *) attr->pValue; if (flag != TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } // 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: case CKM_RSA_PKCS_PSS: if (mech->mechanism == CKM_RSA_PKCS_PSS) { rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VERIFY for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params failed.\n"); goto done; } } else { if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; } if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a private key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } // PKCS #11 doesn't allow multi-part RSA operations // ctx->context_len = 0; ctx->context = NULL; break; case CKM_ECDSA: case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_EC) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; } if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } if (mech->mechanism == CKM_ECDSA) { ctx->context_len = 0; ctx->context = NULL; } else { ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *) malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); } break; case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; } if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *) malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); break; case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params failed.\n"); goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; } if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } ctx->context_len = sizeof(DIGEST_CONTEXT); ctx->context = (CK_BYTE *) malloc(ctx->context_len); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, ctx->context_len); break; #if !(NODSA) case CKM_DSA: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_DSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; } if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } // PKCS #11 doesn't allow multi-part DSA operations // ctx->context_len = 0; ctx->context = NULL; break; #endif case CKM_MD2_HMAC: case CKM_MD5_HMAC: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_GENERIC_SECRET) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; break; case CKM_SHA_1_HMAC: case CKM_SHA224_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA512_224_HMAC: case CKM_SHA512_256_HMAC: case CKM_IBM_SHA3_224_HMAC: case CKM_IBM_SHA3_256_HMAC: case CKM_IBM_SHA3_384_HMAC: case CKM_IBM_SHA3_512_HMAC: if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_GENERIC_SECRET) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; rc = hmac_verify_init(tokdata, sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); goto done; } break; case CKM_MD2_HMAC_GENERAL: case CKM_MD5_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_GENERIC_SECRET) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc= CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA224_HMAC_GENERAL) && (*param > 28)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA256_HMAC_GENERAL) && (*param > 32)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA384_HMAC_GENERAL) && (*param > 48)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA512_HMAC_GENERAL) && (*param > 64)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA512_224_HMAC_GENERAL) && (*param > 28)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } if ((mech->mechanism == CKM_SHA512_256_HMAC_GENERAL) && (*param > 32)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { keytype = *(CK_KEY_TYPE *) attr->pValue; if (keytype != CKK_GENERIC_SECRET) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); rc = CKR_KEY_TYPE_INCONSISTENT; goto done; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; rc = hmac_verify_init(tokdata, sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); goto done; } } 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)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } // Netscape sets the parameter == 16. PKCS #11 limit is 8 // if (mech->mechanism == CKM_SSL3_MD5_MAC) { if (*param < 4 || *param > 16) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } if (mech->mechanism == CKM_SSL3_SHA1_MAC) { if (*param < 4 || *param > 20) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); rc = CKR_FUNCTION_FAILED; goto done; } else { class = *(CK_OBJECT_CLASS *) attr->pValue; if (class != CKO_SECRET_KEY) { TRACE_ERROR("This operation requires a secret key.\n"); rc = CKR_KEY_FUNCTION_NOT_PERMITTED; goto done; } } ctx->context_len = sizeof(SSL3_MAC_CONTEXT); ctx->context = (CK_BYTE *) malloc(sizeof(SSL3_MAC_CONTEXT)); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(SSL3_MAC_CONTEXT)); } break; case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->mechanism == CKM_DES3_MAC_GENERAL) { if (*param < 1 || *param > DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } else { /* CKM_DES_MAC or CKM_DES3_MAC should not have params */ rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } ctx->context = (CK_BYTE *) malloc(sizeof(DES_DATA_CONTEXT)); ctx->context_len = sizeof(DES_DATA_CONTEXT); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(DES_DATA_CONTEXT)); } break; case CKM_DES3_CMAC: case CKM_DES3_CMAC_GENERAL: if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->mechanism == CKM_DES3_CMAC_GENERAL) { if (*param < 1 || *param > DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } else { /* CKM_DES3_CMAC should not have params */ rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } ctx->context = (CK_BYTE *) malloc(sizeof(DES_CMAC_CONTEXT)); ctx->context_len = sizeof(DES_CMAC_CONTEXT); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(DES_CMAC_CONTEXT)); break; case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->mechanism == CKM_AES_MAC_GENERAL) { if (*param < 1 || *param > AES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } else { /* CKM_AES_MAC should not have params */ rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } ctx->context = (CK_BYTE *) malloc(sizeof(AES_DATA_CONTEXT)); ctx->context_len = sizeof(AES_DATA_CONTEXT); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(AES_DATA_CONTEXT)); } break; case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *) mech->pParameter; if (mech->mechanism == CKM_AES_CMAC_GENERAL) { if (*param < 1 || *param > AES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } else { /* CKM_AES_CMAC should not have params */ rc = CKR_MECHANISM_PARAM_INVALID; goto done; } } ctx->context = (CK_BYTE *) malloc(sizeof(AES_CMAC_CONTEXT)); ctx->context_len = sizeof(AES_CMAC_CONTEXT); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(ctx->context, 0x0, sizeof(AES_CMAC_CONTEXT)); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } if (mech->ulParameterLen > 0 && mech->pParameter != NULL) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } 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_init = FALSE; ctx->multi = FALSE; ctx->active = TRUE; ctx->recover = recover_mode; rc = CKR_OK; done: object_put(tokdata, key_obj, TRUE); key_obj = NULL; return rc; } // // CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) { if (!ctx) { TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi_init = FALSE; ctx->multi = FALSE; ctx->active = FALSE; ctx->init_pending = 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 verify_mgr_verify(STDLL_TokData_t *tokdata, SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->multi_init == FALSE) { ctx->multi = FALSE; ctx->multi_init = TRUE; } // 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 (!in_data || !signature) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return rsa_pkcs_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_RSA_X_509: return rsa_x509_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_RSA_PKCS_PSS: return rsa_pss_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); #if !(NODSA) case CKM_DSA: return dsa_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); #endif #if !(NOMD2) case CKM_MD2_HMAC: case CKM_MD2_HMAC_GENERAL: return md2_hmac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); #endif case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: return md5_hmac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC: case CKM_SHA512_256_HMAC_GENERAL: case CKM_IBM_SHA3_224_HMAC: case CKM_IBM_SHA3_256_HMAC: case CKM_IBM_SHA3_384_HMAC: case CKM_IBM_SHA3_512_HMAC: return sha_hmac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_DES3_CMAC: case CKM_DES3_CMAC_GENERAL: return des3_cmac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: return aes_cmac_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: return ec_hash_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_ECDSA: return ec_verify(tokdata, sess, ctx, in_data, in_data_len, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_update(STDLL_TokData_t *tokdata, SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->multi_init == FALSE) { ctx->multi = TRUE; ctx->multi_init = TRUE; } if (ctx->multi == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_DES3_CMAC: case CKM_DES3_CMAC_GENERAL: return des3_cmac_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: return aes_cmac_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: return ec_hash_verify_update(tokdata, sess, ctx, in_data, in_data_len); case CKM_SHA_1_HMAC: case CKM_SHA224_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA512_224_HMAC: case CKM_SHA512_256_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: case CKM_IBM_SHA3_224_HMAC: case CKM_IBM_SHA3_256_HMAC: case CKM_IBM_SHA3_384_HMAC: case CKM_IBM_SHA3_512_HMAC: return hmac_verify_update(tokdata, sess, in_data, in_data_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_final(STDLL_TokData_t *tokdata, SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG sig_len) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->multi_init == FALSE) { ctx->multi = TRUE; ctx->multi_init = TRUE; } if (ctx->multi == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_DES3_CMAC: case CKM_DES3_CMAC_GENERAL: return des3_cmac_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_AES_CMAC: case CKM_AES_CMAC_GENERAL: return aes_cmac_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: return ec_hash_verify_final(tokdata, sess, ctx, signature, sig_len); case CKM_SHA_1_HMAC: case CKM_SHA224_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA512_224_HMAC: case CKM_SHA512_256_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_224_HMAC_GENERAL: case CKM_SHA512_256_HMAC_GENERAL: case CKM_IBM_SHA3_224_HMAC: case CKM_IBM_SHA3_256_HMAC: case CKM_IBM_SHA3_384_HMAC: case CKM_IBM_SHA3_512_HMAC: return hmac_verify_final(tokdata, sess, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_recover(STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_len) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); 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 (!signature || !out_len) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return rsa_pkcs_verify_recover(tokdata, sess, length_only, ctx, signature, sig_len, out_data, out_len); case CKM_RSA_X_509: return rsa_x509_verify_recover(tokdata, sess, length_only, ctx, signature, sig_len, out_data, out_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; }