static int sc_hsm_C_Sign(struct p11Object_t *pObject, CK_MECHANISM_TYPE mech, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { int rc, algo, signaturelen; unsigned short SW1SW2; unsigned char scr[256]; FUNC_CALLED(); rc = getSignatureSize(mech, pObject); if (rc < 0) { FUNC_FAILS(CKR_MECHANISM_INVALID, "Unknown mechanism"); } signaturelen = rc; if (pSignature == NULL) { *pulSignatureLen = signaturelen; FUNC_RETURNS(CKR_OK); } if (*pulSignatureLen < signaturelen) { *pulSignatureLen = signaturelen; FUNC_FAILS(CKR_BUFFER_TOO_SMALL, "Signature length is larger than buffer"); } algo = getAlgorithmIdForSigning(mech); if (algo < 0) { FUNC_FAILS(CKR_MECHANISM_INVALID, "Mechanism not supported"); } if ((algo == ALGO_EC_RAW) || (algo == ALGO_EC_SHA1)) { rc = transmitAPDU(pObject->token->slot, 0x80, 0x68, (unsigned char)pObject->tokenid, (unsigned char)algo, ulDataLen, pData, 0, scr, sizeof(scr), &SW1SW2); } else { if (mech == CKM_RSA_PKCS) { if (signaturelen > sizeof(scr)) { FUNC_FAILS(CKR_BUFFER_TOO_SMALL, "Signature length is larger than buffer"); } applyPKCSPadding(pData, ulDataLen, scr, signaturelen); rc = transmitAPDU(pObject->token->slot, 0x80, 0x68, (unsigned char)pObject->tokenid, (unsigned char)algo, signaturelen, scr, 0, pSignature, *pulSignatureLen, &SW1SW2); } else { rc = transmitAPDU(pObject->token->slot, 0x80, 0x68, (unsigned char)pObject->tokenid, (unsigned char)algo, ulDataLen, pData, 0, pSignature, *pulSignatureLen, &SW1SW2); } } if (rc < 0) { FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed"); } if (SW1SW2 != 0x9000) { FUNC_FAILS(CKR_DEVICE_ERROR, "Signature operation failed"); } if ((algo == ALGO_EC_RAW) || (algo == ALGO_EC_SHA1)) { rc = decodeECDSASignature(scr, rc, pSignature, *pulSignatureLen); if (rc < 0) { FUNC_FAILS(CKR_BUFFER_TOO_SMALL, "supplied buffer too small"); } } *pulSignatureLen = rc; FUNC_RETURNS(CKR_OK); }
static int starcos_C_Sign(struct p11Object_t *pObject, CK_MECHANISM_TYPE mech, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { int rc, len, signaturelen; unsigned short SW1SW2; unsigned char scr[256],*s, *d; struct p11Slot_t *slot; FUNC_CALLED(); rc = getSignatureSize(mech, pObject); if (rc < 0) { FUNC_FAILS(CKR_MECHANISM_INVALID, "Unknown mechanism"); } signaturelen = rc; if (pSignature == NULL) { *pulSignatureLen = signaturelen; FUNC_RETURNS(CKR_OK); } if (*pulSignatureLen < (CK_ULONG)signaturelen) { *pulSignatureLen = signaturelen; FUNC_FAILS(CKR_BUFFER_TOO_SMALL, "Signature length is larger than buffer"); } slot = pObject->token->slot; starcosLock(pObject->token); if (!slot->token) { FUNC_RETURNS(CKR_DEVICE_REMOVED); } rc = starcosSelectApplication(pObject->token); if (rc < 0) { starcosUnlock(pObject->token); FUNC_FAILS(CKR_DEVICE_ERROR, "selecting application failed"); } if ((mech != CKM_RSA_PKCS) && (mech != CKM_ECDSA) && (mech != CKM_ECDSA_SHA1) && (mech != CKM_SC_HSM_PSS_SHA1) && (mech != CKM_SC_HSM_PSS_SHA224) && (mech != CKM_SC_HSM_PSS_SHA256) && (mech != CKM_SC_HSM_PSS_SHA384) && (mech != CKM_SC_HSM_PSS_SHA512)) { rc = starcosDigest(pObject->token, mech, pData, ulDataLen); if (rc != CKR_OK) { starcosUnlock(pObject->token); FUNC_FAILS(rc, "digesting failed"); } pData = NULL; ulDataLen = 0; } rc = getAlgorithmIdForSigning(pObject->token, mech, &s); if (rc != CKR_OK) { starcosUnlock(pObject->token); FUNC_FAILS(rc, "getAlgorithmIdForSigning() failed"); } d = scr; *d++ = *s++; len = *s; *d++ = *s++; while (len--) { *d++ = *s++; } *d++ = 0x84; *d++ = 0x01; *d++ = (unsigned char)pObject->tokenid; rc = transmitAPDU(pObject->token->slot, 0x00, 0x22, 0x41, 0xB6, (int)(d - scr), scr, 0, NULL, 0, &SW1SW2); if (rc < 0) { starcosUnlock(pObject->token); FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed"); } if (SW1SW2 != 0x9000) { starcosUnlock(pObject->token); FUNC_FAILS(CKR_DEVICE_ERROR, "MANAGE SE failed"); } rc = transmitAPDU(pObject->token->slot, 0x00, 0x2A, 0x9E, 0x9A, ulDataLen, pData, 0, pSignature, *pulSignatureLen, &SW1SW2); if (rc < 0) { starcosUnlock(pObject->token); FUNC_FAILS(CKR_DEVICE_ERROR, "transmitAPDU failed"); } if (SW1SW2 != 0x9000) { starcosUnlock(pObject->token); switch(SW1SW2) { case 0x6A81: FUNC_FAILS(CKR_KEY_FUNCTION_NOT_PERMITTED, "Signature operation not allowed for key"); break; case 0x6982: pObject->token->user = INT_CKU_NO_USER; FUNC_FAILS(CKR_USER_NOT_LOGGED_IN, "User not logged in"); break; } FUNC_FAILS(CKR_DEVICE_ERROR, "Signature operation failed"); } *pulSignatureLen = rc; if ((pObject->token->user == CKU_USER) && (pObject->token->pinUseCounter == 1)) { pObject->token->user = INT_CKU_NO_USER; } starcosUnlock(pObject->token); FUNC_RETURNS(CKR_OK); }