chaps: Cancel operations on error returns
The PKCS#11 spec indicates that if errors are returned from
crypto operation functions, the in-progress operation should
be terminated. For example, in section 11.8 (p.140), the
description of C_Encrypt has:
"A call to C_Encrypt always terminates the active encryption
operation unless it returns CKR_BUFFER_TOO_SMALL or is a
successful call (i.e., one which returns CKR_OK) to determine
the length of the buffer needed to hold the ciphertext."
Some errors from these functions (typically CKR_ARGUMENTS_BAD)
are detected on the client side; to ensure that the chapsd state
is correctly updated to cancel the operation, we add a collection
of <Operation>Cancel methods to the D-Bus interface.
There are also some errors detected at the daemon side (in
particular, the interspersal of one-shot and incremental
operations); these can just trigger a local call to the appropriate
<Operation>Cancel function.
BUG=None
TEST=Chaps unit tests (with ASAN) plus PKCS11 tests
Change-Id: I8108907bfad9b5ba4b81ba25cf253b4e03ca9b9f
Reviewed-on: https://chromium-review.googlesource.com/221938
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: David Drysdale <drysdale@google.com>
Tested-by: David Drysdale <drysdale@google.com>
diff --git a/chaps/chaps.cc b/chaps/chaps.cc
index 60abdf9..bd9d7df 100644
--- a/chaps/chaps.cc
+++ b/chaps/chaps.cc
@@ -722,8 +722,10 @@
CK_BYTE_PTR pEncryptedData,
CK_ULONG_PTR pulEncryptedDataLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- if ((!pData && ulDataLen > 0) || !pulEncryptedDataLen)
+ if ((!pData && ulDataLen > 0) || !pulEncryptedDataLen) {
+ g_proxy->EncryptCancel(*g_user_isolate, hSession);
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -752,7 +754,10 @@
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pPart || !pulEncryptedPartLen, CKR_ARGUMENTS_BAD);
+ if (!pPart || !pulEncryptedPartLen) {
+ g_proxy->EncryptCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -779,7 +784,10 @@
CK_BYTE_PTR pLastEncryptedPart,
CK_ULONG_PTR pulLastEncryptedPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pulLastEncryptedPartLen, CKR_ARGUMENTS_BAD);
+ if (!pulLastEncryptedPartLen) {
+ g_proxy->EncryptCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -825,8 +833,10 @@
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- if ((!pEncryptedData && ulEncryptedDataLen > 0) || !pulDataLen)
+ if ((!pEncryptedData && ulEncryptedDataLen > 0) || !pulDataLen) {
+ g_proxy->DecryptCancel(*g_user_isolate, hSession);
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length = pData ? static_cast<uint64_t>(*pulDataLen) : 0;
@@ -855,7 +865,10 @@
CK_BYTE_PTR pPart,
CK_ULONG_PTR pulPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pEncryptedPart || !pulPartLen, CKR_ARGUMENTS_BAD);
+ if (!pEncryptedPart || !pulPartLen) {
+ g_proxy->DecryptCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length = pPart ? static_cast<uint64_t>(*pulPartLen) : 0;
@@ -882,7 +895,10 @@
CK_BYTE_PTR pLastPart,
CK_ULONG_PTR pulLastPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pulLastPartLen, CKR_ARGUMENTS_BAD);
+ if (!pulLastPartLen) {
+ g_proxy->DecryptCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -926,8 +942,10 @@
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- if ((!pData && ulDataLen > 0) || !pulDigestLen)
+ if ((!pData && ulDataLen > 0) || !pulDigestLen) {
+ g_proxy->DigestCancel(*g_user_isolate, hSession);
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length = pDigest ? static_cast<uint64_t>(*pulDigestLen) : 0;
@@ -953,7 +971,10 @@
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pPart, CKR_ARGUMENTS_BAD);
+ if (!pPart) {
+ g_proxy->DigestCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
CK_RV result = g_proxy->DigestUpdate(
*g_user_isolate,
hSession,
@@ -977,7 +998,10 @@
CK_BYTE_PTR pDigest,
CK_ULONG_PTR pulDigestLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pulDigestLen, CKR_ARGUMENTS_BAD);
+ if (!pulDigestLen) {
+ g_proxy->DigestCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length = pDigest ? static_cast<uint64_t>(*pulDigestLen) : 0;
@@ -1022,8 +1046,10 @@
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- if ((!pData && ulDataLen > 0) || !pulSignatureLen)
+ if ((!pData && ulDataLen > 0) || !pulSignatureLen) {
+ g_proxy->SignCancel(*g_user_isolate, hSession);
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -1050,7 +1076,10 @@
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pPart, CKR_ARGUMENTS_BAD);
+ if (!pPart) {
+ g_proxy->SignCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
CK_RV result = g_proxy->SignUpdate(*g_user_isolate,
hSession,
chaps::ConvertByteBufferToVector(pPart,
@@ -1065,7 +1094,10 @@
CK_BYTE_PTR pSignature,
CK_ULONG_PTR pulSignatureLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pulSignatureLen, CKR_ARGUMENTS_BAD);
+ if (!pulSignatureLen) {
+ g_proxy->SignCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
vector<uint8_t> data_out;
uint64_t data_out_length;
uint64_t max_out_length =
@@ -1160,8 +1192,10 @@
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- if (!pSignature || (!pData && ulDataLen > 0))
+ if (!pSignature || (!pData && ulDataLen > 0)) {
+ g_proxy->VerifyCancel(*g_user_isolate, hSession);
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
CK_RV result = g_proxy->Verify(
*g_user_isolate,
hSession,
@@ -1177,7 +1211,10 @@
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pPart, CKR_ARGUMENTS_BAD);
+ if (!pPart) {
+ g_proxy->VerifyCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
CK_RV result = g_proxy->VerifyUpdate(
*g_user_isolate,
hSession,
@@ -1192,7 +1229,10 @@
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen) {
LOG_CK_RV_AND_RETURN_IF(!g_is_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- LOG_CK_RV_AND_RETURN_IF(!pSignature, CKR_ARGUMENTS_BAD);
+ if (!pSignature) {
+ g_proxy->VerifyCancel(*g_user_isolate, hSession);
+ LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
+ }
CK_RV result = g_proxy->VerifyFinal(
*g_user_isolate,
hSession,
diff --git a/chaps/chaps_adaptor.cc b/chaps/chaps_adaptor.cc
index 7f3eb2b..fbb87dc 100644
--- a/chaps/chaps_adaptor.cc
+++ b/chaps/chaps_adaptor.cc
@@ -1093,6 +1093,22 @@
actual_out_length, data_out, result);
}
+void ChapsAdaptor::EncryptCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id) {
+ AutoLock lock(*lock_);
+ VLOG(1) << "CALL: " << __func__;
+ SecureBlob isolate_credential_blob(&isolate_credential.front(),
+ isolate_credential.size());
+ ClearVector(const_cast<vector<uint8_t>*>(&isolate_credential));
+ service_->EncryptCancel(isolate_credential_blob, session_id);
+}
+
+void ChapsAdaptor::EncryptCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& /*error*/) {
+ EncryptCancel(isolate_credential, session_id);
+}
+
uint32_t ChapsAdaptor::DecryptInit(
const vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -1232,6 +1248,22 @@
actual_out_length, data_out, result);
}
+void ChapsAdaptor::DecryptCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id) {
+ AutoLock lock(*lock_);
+ VLOG(1) << "CALL: " << __func__;
+ SecureBlob isolate_credential_blob(&isolate_credential.front(),
+ isolate_credential.size());
+ ClearVector(const_cast<vector<uint8_t>*>(&isolate_credential));
+ service_->DecryptCancel(isolate_credential_blob, session_id);
+}
+
+void ChapsAdaptor::DecryptCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& /*error*/) {
+ DecryptCancel(isolate_credential, session_id);
+}
+
uint32_t ChapsAdaptor::DigestInit(
const vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -1375,6 +1407,22 @@
digest, result);
}
+void ChapsAdaptor::DigestCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id) {
+ AutoLock lock(*lock_);
+ VLOG(1) << "CALL: " << __func__;
+ SecureBlob isolate_credential_blob(&isolate_credential.front(),
+ isolate_credential.size());
+ ClearVector(const_cast<vector<uint8_t>*>(&isolate_credential));
+ service_->DigestCancel(isolate_credential_blob, session_id);
+}
+
+void ChapsAdaptor::DigestCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& /*error*/) {
+ DigestCancel(isolate_credential, session_id);
+}
+
uint32_t ChapsAdaptor::SignInit(const vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -1497,6 +1545,22 @@
signature, result);
}
+void ChapsAdaptor::SignCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id) {
+ AutoLock lock(*lock_);
+ VLOG(1) << "CALL: " << __func__;
+ SecureBlob isolate_credential_blob(&isolate_credential.front(),
+ isolate_credential.size());
+ ClearVector(const_cast<vector<uint8_t>*>(&isolate_credential));
+ service_->SignCancel(isolate_credential_blob, session_id);
+}
+
+void ChapsAdaptor::SignCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& /*error*/) {
+ SignCancel(isolate_credential, session_id);
+}
+
uint32_t ChapsAdaptor::SignRecoverInit(
const vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -1665,6 +1729,23 @@
return VerifyFinal(isolate_credential, session_id, signature);
}
+void ChapsAdaptor::VerifyCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id) {
+ AutoLock lock(*lock_);
+ VLOG(1) << "CALL: " << __func__;
+ SecureBlob isolate_credential_blob(&isolate_credential.front(),
+ isolate_credential.size());
+ ClearVector(const_cast<vector<uint8_t>*>(&isolate_credential));
+ service_->VerifyCancel(isolate_credential_blob, session_id);
+}
+
+void ChapsAdaptor::VerifyCancel(const vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& /*error*/) {
+ VerifyCancel(isolate_credential, session_id);
+}
+
+
uint32_t ChapsAdaptor::VerifyRecoverInit(
const vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
diff --git a/chaps/chaps_adaptor.h b/chaps/chaps_adaptor.h
index 74b1cb6..2d95b59 100644
--- a/chaps/chaps_adaptor.h
+++ b/chaps/chaps_adaptor.h
@@ -257,6 +257,9 @@
std::vector<uint8_t>& data_out, // NOLINT - refs
uint32_t& result, // NOLINT - refs
::DBus::Error& error); // NOLINT - refs
+ virtual void EncryptCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& error); // NOLINT - refs
virtual uint32_t DecryptInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -286,6 +289,9 @@
std::vector<uint8_t>& data_out, // NOLINT - refs
uint32_t& result, // NOLINT - refs
::DBus::Error& error); // NOLINT - refs
+ virtual void DecryptCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& error); // NOLINT - refs
virtual uint32_t DigestInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -314,6 +320,9 @@
std::vector<uint8_t>& digest, // NOLINT - refs
uint32_t& result, // NOLINT - refs
::DBus::Error& error); // NOLINT - refs
+ virtual void DigestCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& error); // NOLINT - refs
virtual uint32_t SignInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -339,6 +348,9 @@
std::vector<uint8_t>& signature, // NOLINT - refs
uint32_t& result, // NOLINT - refs
::DBus::Error& error); // NOLINT - refs
+ virtual void SignCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& error); // NOLINT - refs
virtual uint32_t SignRecoverInit(
const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -373,6 +385,9 @@
const uint64_t& session_id,
const std::vector<uint8_t>& signature,
::DBus::Error& error); // NOLINT - refs
+ virtual void VerifyCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id,
+ ::DBus::Error& error); // NOLINT - refs
virtual uint32_t VerifyRecoverInit(
const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -670,6 +685,8 @@
uint64_t& actual_out_length, // NOLINT - refs
std::vector<uint8_t>& data_out, // NOLINT - refs
uint32_t& result); // NOLINT - refs
+ virtual void EncryptCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id);
virtual uint32_t DecryptInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -695,6 +712,8 @@
uint64_t& actual_out_length, // NOLINT - refs
std::vector<uint8_t>& data_out, // NOLINT - refs
uint32_t& result); // NOLINT - refs
+ virtual void DecryptCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id);
virtual uint32_t DigestInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -718,6 +737,8 @@
uint64_t& actual_out_length, // NOLINT - refs
std::vector<uint8_t>& digest, // NOLINT - refs
uint32_t& result); // NOLINT - refs
+ virtual void DigestCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id);
virtual uint32_t SignInit(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const uint64_t& mechanism_type,
@@ -739,6 +760,8 @@
uint64_t& actual_out_length, // NOLINT - refs
std::vector<uint8_t>& signature, // NOLINT - refs
uint32_t& result); // NOLINT - refs
+ virtual void SignCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id);
virtual uint32_t SignRecoverInit(
const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
@@ -767,6 +790,8 @@
virtual uint32_t VerifyFinal(const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
const std::vector<uint8_t>& signature);
+ virtual void VerifyCancel(const std::vector<uint8_t>& isolate_credential,
+ const uint64_t& session_id);
virtual uint32_t VerifyRecoverInit(
const std::vector<uint8_t>& isolate_credential,
const uint64_t& session_id,
diff --git a/chaps/chaps_interface.h b/chaps/chaps_interface.h
index 8a8c527..4b8af8c 100644
--- a/chaps/chaps_interface.h
+++ b/chaps/chaps_interface.h
@@ -208,6 +208,10 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out) = 0;
+ // PKCS #11 v2.20 section 11.8 page 140,142: any errors terminate the active
+ // encryption operation.
+ virtual void EncryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id) = 0;
// PKCS #11 v2.20 section 11.9 page 144.
virtual uint32_t DecryptInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
@@ -234,6 +238,10 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out) = 0;
+ // PKCS #11 v2.20 section 11.9 page 145,146: any errors terminate the active
+ // decryption operation.
+ virtual void DecryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id) = 0;
// PKCS #11 v2.20 section 11.10 page 148.
virtual uint32_t DigestInit(
const chromeos::SecureBlob& isolate_credential,
@@ -261,6 +269,10 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* digest) = 0;
+ // PKCS #11 v2.20 section 11.10 page 149,151: any errors terminate the active
+ // digest operation.
+ virtual void DigestCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id) = 0;
// PKCS #11 v2.20 section 11.11 page 152.
virtual uint32_t SignInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
@@ -284,6 +296,10 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* signature) = 0;
+ // PKCS #11 v2.20 section 11.11 page 153,154: any errors terminate the active
+ // signing operation.
+ virtual void SignCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id) = 0;
// PKCS #11 v2.20 section 11.11 page 155.
virtual uint32_t SignRecoverInit(
const chromeos::SecureBlob& isolate_credential,
@@ -317,6 +333,10 @@
virtual uint32_t VerifyFinal(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
const std::vector<uint8_t>& signature) = 0;
+ // PKCS #11 v2.20 section 11.12 page 159: any errors terminate the active
+ // verification operation.
+ virtual void VerifyCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id) = 0;
// PKCS #11 v2.20 section 11.12 page 161.
virtual uint32_t VerifyRecoverInit(
const chromeos::SecureBlob& isolate_credential,
diff --git a/chaps/chaps_interface.xml b/chaps/chaps_interface.xml
index 80fc2e6..5436a62 100644
--- a/chaps/chaps_interface.xml
+++ b/chaps/chaps_interface.xml
@@ -440,6 +440,12 @@
</arg>
</method>
+ <!-- PKCS #11 v2.20 section 11.8 page 140,142 (implicit). -->
+ <method name="EncryptCancel">
+ <arg type="ay" name="isolate_credential" direction="in"/>
+ <arg type="t" name="session_id" direction="in"/>
+ </method>
+
<!-- PKCS #11 v2.20 section 11.9 page 144. -->
<method name="DecryptInit">
<arg type="ay" name="isolate_credential" direction="in"/>
@@ -490,6 +496,12 @@
</arg>
</method>
+ <!-- PKCS #11 v2.20 section 11.9 page 145,146 (implicit). -->
+ <method name="DecryptCancel">
+ <arg type="ay" name="isolate_credential" direction="in"/>
+ <arg type="t" name="session_id" direction="in"/>
+ </method>
+
<!-- PKCS #11 v2.20 section 11.10 page 148. -->
<method name="DigestInit">
<arg type="ay" name="isolate_credential" direction="in"/>
@@ -546,6 +558,12 @@
</arg>
</method>
+ <!-- PKCS #11 v2.20 section 11.10 page 149,151 (implicit). -->
+ <method name="DigestCancel">
+ <arg type="ay" name="isolate_credential" direction="in"/>
+ <arg type="t" name="session_id" direction="in"/>
+ </method>
+
<!-- PKCS #11 v2.20 section 11.11 page 152. -->
<method name="SignInit">
<arg type="ay" name="isolate_credential" direction="in"/>
@@ -593,6 +611,12 @@
</arg>
</method>
+ <!-- PKCS #11 v2.20 section 11.11 page 153,154 (implicit). -->
+ <method name="SignCancel">
+ <arg type="ay" name="isolate_credential" direction="in"/>
+ <arg type="t" name="session_id" direction="in"/>
+ </method>
+
<!-- PKCS #11 v2.20 section 11.11 page 155. -->
<method name="SignRecoverInit">
<arg type="ay" name="isolate_credential" direction="in"/>
@@ -661,6 +685,12 @@
</arg>
</method>
+ <!-- PKCS #11 v2.20 section 11.12 page 159. -->
+ <method name="VerifyCancel">
+ <arg type="ay" name="isolate_credential" direction="in"/>
+ <arg type="t" name="session_id" direction="in"/>
+ </method>
+
<!-- PKCS #11 v2.20 section 11.12 page 161. -->
<method name="VerifyRecoverInit">
<arg type="ay" name="isolate_credential" direction="in"/>
diff --git a/chaps/chaps_proxy.cc b/chaps/chaps_proxy.cc
index f950234..09d4769 100644
--- a/chaps/chaps_proxy.cc
+++ b/chaps/chaps_proxy.cc
@@ -788,6 +788,18 @@
return result;
}
+void ChapsProxyImpl::EncryptCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ AutoLock lock(lock_);
+ if (!proxy_.get())
+ return;
+ try {
+ proxy_->EncryptCancel(isolate_credential, session_id);
+ } catch (DBus::Error err) {
+ LOG(ERROR) << "DBus::Error - " << err.what();
+ }
+}
+
uint32_t ChapsProxyImpl::DecryptInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -883,6 +895,18 @@
return result;
}
+void ChapsProxyImpl::DecryptCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ AutoLock lock(lock_);
+ if (!proxy_.get())
+ return;
+ try {
+ proxy_->DecryptCancel(isolate_credential, session_id);
+ } catch (DBus::Error err) {
+ LOG(ERROR) << "DBus::Error - " << err.what();
+ }
+}
+
uint32_t ChapsProxyImpl::DigestInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -979,6 +1003,18 @@
return result;
}
+void ChapsProxyImpl::DigestCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ AutoLock lock(lock_);
+ if (!proxy_.get())
+ return;
+ try {
+ proxy_->DigestCancel(isolate_credential, session_id);
+ } catch (DBus::Error err) {
+ LOG(ERROR) << "DBus::Error - " << err.what();
+ }
+}
+
uint32_t ChapsProxyImpl::SignInit(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -1061,6 +1097,18 @@
return result;
}
+void ChapsProxyImpl::SignCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ AutoLock lock(lock_);
+ if (!proxy_.get())
+ return;
+ try {
+ proxy_->SignCancel(isolate_credential, session_id);
+ } catch (DBus::Error err) {
+ LOG(ERROR) << "DBus::Error - " << err.what();
+ }
+}
+
uint32_t ChapsProxyImpl::SignRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -1174,6 +1222,18 @@
return result;
}
+void ChapsProxyImpl::VerifyCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ AutoLock lock(lock_);
+ if (!proxy_.get())
+ return;
+ try {
+ proxy_->VerifyCancel(isolate_credential, session_id);
+ } catch (DBus::Error err) {
+ LOG(ERROR) << "DBus::Error - " << err.what();
+ }
+}
+
uint32_t ChapsProxyImpl::VerifyRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_proxy.h b/chaps/chaps_proxy.h
index 7236b40..83226f3 100644
--- a/chaps/chaps_proxy.h
+++ b/chaps/chaps_proxy.h
@@ -197,6 +197,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void EncryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DecryptInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -219,6 +221,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void DecryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DigestInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -240,6 +244,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* digest);
+ virtual void DigestCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -259,6 +265,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* signature);
+ virtual void SignCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
@@ -286,6 +294,8 @@
virtual uint32_t VerifyFinal(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
const std::vector<uint8_t>& signature);
+ virtual void VerifyCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t VerifyRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_proxy_mock.h b/chaps/chaps_proxy_mock.h
index 342e4bb..7d5ad32 100644
--- a/chaps/chaps_proxy_mock.h
+++ b/chaps/chaps_proxy_mock.h
@@ -149,6 +149,8 @@
uint64_t,
uint64_t*,
std::vector<uint8_t>*));
+ MOCK_METHOD2(EncryptCancel, void(const chromeos::SecureBlob&,
+ uint64_t));
MOCK_METHOD5(DecryptInit, uint32_t(const chromeos::SecureBlob&,
uint64_t,
uint64_t,
@@ -171,6 +173,8 @@
uint64_t,
uint64_t*,
std::vector<uint8_t>*));
+ MOCK_METHOD2(DecryptCancel, void(const chromeos::SecureBlob&,
+ uint64_t));
MOCK_METHOD4(DigestInit, uint32_t(const chromeos::SecureBlob&,
uint64_t,
uint64_t,
@@ -192,6 +196,8 @@
uint64_t,
uint64_t*,
std::vector<uint8_t>*));
+ MOCK_METHOD2(DigestCancel, void(const chromeos::SecureBlob&,
+ uint64_t));
MOCK_METHOD5(SignInit, uint32_t(const chromeos::SecureBlob&,
uint64_t,
uint64_t,
@@ -211,6 +217,8 @@
uint64_t,
uint64_t*,
std::vector<uint8_t>*));
+ MOCK_METHOD2(SignCancel, void(const chromeos::SecureBlob&,
+ uint64_t));
MOCK_METHOD5(SignRecoverInit, uint32_t(const chromeos::SecureBlob&,
uint64_t,
uint64_t,
@@ -237,6 +245,8 @@
MOCK_METHOD3(VerifyFinal, uint32_t(const chromeos::SecureBlob&,
uint64_t,
const std::vector<uint8_t>&));
+ MOCK_METHOD2(VerifyCancel, void(const chromeos::SecureBlob&,
+ uint64_t));
MOCK_METHOD5(VerifyRecoverInit, uint32_t(const chromeos::SecureBlob&,
uint64_t,
uint64_t,
diff --git a/chaps/chaps_service.cc b/chaps/chaps_service.cc
index 5ba8165..027832f 100644
--- a/chaps/chaps_service.cc
+++ b/chaps/chaps_service.cc
@@ -648,6 +648,17 @@
PreservedByteVector(data_out));
}
+void ChapsServiceImpl::EncryptCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ Session* session = NULL;
+ if (!slot_manager_->GetSession(isolate_credential,
+ session_id,
+ &session))
+ return;
+ CHECK(session);
+ session->OperationCancel(kEncrypt);
+}
+
uint32_t ChapsServiceImpl::DecryptInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -732,6 +743,18 @@
PreservedByteVector(data_out));
}
+void ChapsServiceImpl::DecryptCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ Session* session = NULL;
+ if (!slot_manager_->GetSession(isolate_credential,
+ session_id,
+ &session))
+ return;
+ CHECK(session);
+ session->OperationCancel(kDecrypt);
+}
+
+
uint32_t ChapsServiceImpl::DigestInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -811,6 +834,17 @@
PreservedByteVector(digest));
}
+void ChapsServiceImpl::DigestCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ Session* session = NULL;
+ if (!slot_manager_->GetSession(isolate_credential,
+ session_id,
+ &session))
+ return;
+ CHECK(session);
+ session->OperationCancel(kDigest);
+}
+
uint32_t ChapsServiceImpl::SignInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -888,6 +922,17 @@
PreservedByteVector(signature));
}
+void ChapsServiceImpl::SignCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ Session* session = NULL;
+ if (!slot_manager_->GetSession(isolate_credential,
+ session_id,
+ &session))
+ return;
+ CHECK(session);
+ session->OperationCancel(kSign);
+}
+
uint32_t ChapsServiceImpl::SignRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -965,6 +1010,17 @@
return session->VerifyFinal(ConvertByteVectorToString(signature));
}
+void ChapsServiceImpl::VerifyCancel(const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ Session* session = NULL;
+ if (!slot_manager_->GetSession(isolate_credential,
+ session_id,
+ &session))
+ return;
+ CHECK(session);
+ session->OperationCancel(kVerify);
+}
+
uint32_t ChapsServiceImpl::VerifyRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_service.h b/chaps/chaps_service.h
index 8b1dcfe..46b462c 100644
--- a/chaps/chaps_service.h
+++ b/chaps/chaps_service.h
@@ -173,6 +173,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void EncryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DecryptInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -195,6 +197,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void DecryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DigestInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -216,6 +220,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* digest);
+ virtual void DigestCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -235,6 +241,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* signature);
+ virtual void SignCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
@@ -262,6 +270,8 @@
virtual uint32_t VerifyFinal(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
const std::vector<uint8_t>& signature);
+ virtual void VerifyCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t VerifyRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_service_redirect.cc b/chaps/chaps_service_redirect.cc
index e999df9..38e8e10 100644
--- a/chaps/chaps_service_redirect.cc
+++ b/chaps/chaps_service_redirect.cc
@@ -659,6 +659,12 @@
return CKR_OK;
}
+void ChapsServiceRedirect::EncryptCancel(
+ const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ LOG(ERROR) << "Unexpected cancel operation";
+}
+
uint32_t ChapsServiceRedirect::DecryptInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -763,6 +769,12 @@
return CKR_OK;
}
+void ChapsServiceRedirect::DecryptCancel(
+ const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ LOG(ERROR) << "Unexpected cancel operation";
+}
+
uint32_t ChapsServiceRedirect::DigestInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -854,6 +866,12 @@
return CKR_OK;
}
+void ChapsServiceRedirect::DigestCancel(
+ const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ LOG(ERROR) << "Unexpected cancel operation";
+}
+
uint32_t ChapsServiceRedirect::SignInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -936,6 +954,12 @@
return CKR_OK;
}
+void ChapsServiceRedirect::SignCancel(
+ const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ LOG(ERROR) << "Unexpected cancel operation";
+}
+
uint32_t ChapsServiceRedirect::SignRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
@@ -1046,6 +1070,12 @@
return CKR_OK;
}
+void ChapsServiceRedirect::VerifyCancel(
+ const SecureBlob& isolate_credential,
+ uint64_t session_id) {
+ LOG(ERROR) << "Unexpected cancel operation";
+}
+
uint32_t ChapsServiceRedirect::VerifyRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_service_redirect.h b/chaps/chaps_service_redirect.h
index bbf0ec6..daedd17 100644
--- a/chaps/chaps_service_redirect.h
+++ b/chaps/chaps_service_redirect.h
@@ -175,6 +175,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void EncryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DecryptInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -197,6 +199,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* data_out);
+ virtual void DecryptCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t DigestInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -218,6 +222,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* digest);
+ virtual void DigestCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignInit(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
@@ -237,6 +243,8 @@
uint64_t max_out_length,
uint64_t* actual_out_length,
std::vector<uint8_t>* signature);
+ virtual void SignCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t SignRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
@@ -264,6 +272,8 @@
virtual uint32_t VerifyFinal(const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
const std::vector<uint8_t>& signature);
+ virtual void VerifyCancel(const chromeos::SecureBlob& isolate_credential,
+ uint64_t session_id);
virtual uint32_t VerifyRecoverInit(
const chromeos::SecureBlob& isolate_credential,
uint64_t session_id,
diff --git a/chaps/chaps_test.cc b/chaps/chaps_test.cc
index 1d1761b..a0f5932 100644
--- a/chaps/chaps_test.cc
+++ b/chaps/chaps_test.cc
@@ -1570,6 +1570,11 @@
CK_ULONG_PTR ul = (CK_ULONG_PTR)0x1234;
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_EncryptInit(1, NULL, 3));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_DecryptInit(1, NULL, 3));
+
+ // All of the following failures should trigger an attempt to cancel the
+ // operation in progress.
+ EXPECT_CALL(proxy, EncryptCancel(_, 1)).Times(5);
+ EXPECT_CALL(proxy, DecryptCancel(_, 1)).Times(5);
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Encrypt(1, p, 3, p, NULL));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Decrypt(1, p, 3, p, NULL));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Encrypt(1, NULL, 3, p, ul));
@@ -1745,6 +1750,10 @@
CK_BYTE_PTR p = (CK_BYTE_PTR)0x1234;
CK_ULONG_PTR ul = (CK_ULONG_PTR)0x1234;
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_DigestInit(1, NULL));
+
+ // All of the following failures should trigger an attempt to cancel the
+ // operation in progress.
+ EXPECT_CALL(proxy, DigestCancel(_, 1)).Times(5);
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Digest(1, p, 3, p, NULL));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Digest(1, NULL, 3, p, ul));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_DigestUpdate(1, NULL, 3));
@@ -1944,6 +1953,11 @@
CK_ULONG_PTR ul = (CK_ULONG_PTR)0x1234;
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_SignInit(1, NULL, 3));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_VerifyInit(1, NULL, 3));
+
+ // All of the following failures should trigger an attempt to cancel the
+ // operation in progress.
+ EXPECT_CALL(proxy, SignCancel(_, 1)).Times(5);
+ EXPECT_CALL(proxy, VerifyCancel(_, 1)).Times(7);
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Sign(1, p, 3, p, NULL));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Sign(1, NULL, 3, p, ul));
EXPECT_EQ(CKR_ARGUMENTS_BAD, C_Verify(1, NULL, 3, p, 3));
diff --git a/chaps/session.h b/chaps/session.h
index dab76fb..c08caab 100644
--- a/chaps/session.h
+++ b/chaps/session.h
@@ -93,6 +93,8 @@
virtual CK_RV OperationFinal(OperationType operation,
int* required_out_length,
std::string* data_out) = 0;
+ // Cancels an operation that is already active (like C_EncryptUpdate).
+ virtual void OperationCancel(OperationType operation) = 0;
// Finalizes a signature verification operation (like C_VerifyFinal).
virtual CK_RV VerifyFinal(const std::string& signature) = 0;
// Performs an entire operation in a single step (like C_Encrypt). This is
diff --git a/chaps/session_impl.cc b/chaps/session_impl.cc
index 033fe31..cc5bc14 100644
--- a/chaps/session_impl.cc
+++ b/chaps/session_impl.cc
@@ -282,6 +282,7 @@
}
if (context->is_finished_) {
LOG(ERROR) << "Operation is finished.";
+ OperationCancel(operation);
return CKR_OPERATION_ACTIVE;
}
context->is_incremental_ = true;
@@ -298,7 +299,10 @@
CHECK(operation < kNumOperationTypes);
OperationContext* context = &operation_context_[operation];
if (context->is_cipher_) {
- return CipherUpdate(context, data_in, required_out_length, data_out);
+ CK_RV rv = CipherUpdate(context, data_in, required_out_length, data_out);
+ if ((rv != CKR_OK) && (rv != CKR_BUFFER_TOO_SMALL))
+ OperationCancel(operation);
+ return rv;
} else if (context->is_digest_) {
EVP_DigestUpdate(&context->digest_context_,
data_in.data(),
@@ -316,6 +320,17 @@
return CKR_OK;
}
+void SessionImpl::OperationCancel(OperationType operation) {
+ CHECK(operation < kNumOperationTypes);
+ OperationContext* context = &operation_context_[operation];
+ if (!context->is_valid_) {
+ LOG(ERROR) << "Operation is not initialized.";
+ return;
+ }
+ // Drop the context and any associated data.
+ context->Clear();
+}
+
CK_RV SessionImpl::OperationFinal(OperationType operation,
int* required_out_length,
string* data_out) {
@@ -329,6 +344,7 @@
}
if (!context->is_incremental_ && context->is_finished_) {
LOG(ERROR) << "Operation is not incremental.";
+ OperationCancel(operation);
return CKR_OPERATION_ACTIVE;
}
context->is_incremental_ = true;
@@ -423,6 +439,7 @@
}
if (context->is_incremental_) {
LOG(ERROR) << "Operation is incremental.";
+ OperationCancel(operation);
return CKR_OPERATION_ACTIVE;
}
CK_RV result = CKR_OK;
diff --git a/chaps/session_impl.h b/chaps/session_impl.h
index a725831..5cb3977 100644
--- a/chaps/session_impl.h
+++ b/chaps/session_impl.h
@@ -80,6 +80,7 @@
virtual CK_RV OperationFinal(OperationType operation,
int* required_out_length,
std::string* data_out);
+ virtual void OperationCancel(OperationType operation);
virtual CK_RV VerifyFinal(const std::string& signature);
virtual CK_RV OperationSinglePart(OperationType operation,
const std::string& data_in,
diff --git a/chaps/session_mock.h b/chaps/session_mock.h
index 0bf6d07..d646a48 100644
--- a/chaps/session_mock.h
+++ b/chaps/session_mock.h
@@ -49,6 +49,7 @@
int*,
std::string*));
MOCK_METHOD3(OperationFinal, CK_RV(OperationType, int*, std::string*));
+ MOCK_METHOD1(OperationCancel, void(OperationType));
MOCK_METHOD1(VerifyFinal, CK_RV(const std::string&));
MOCK_METHOD4(OperationSinglePart, CK_RV(OperationType,
const std::string&,
diff --git a/chaps/session_test.cc b/chaps/session_test.cc
index 4a197b4..5fdc37c 100644
--- a/chaps/session_test.cc
+++ b/chaps/session_test.cc
@@ -464,6 +464,11 @@
in.substr(10, 20),
&len,
&out));
+
+ // The error also terminates the operation.
+ len = 0;
+ EXPECT_EQ(CKR_OPERATION_NOT_INITIALIZED,
+ session_->OperationFinal(kDigest, &len, &out));
}
TEST_F(TestSession, SinglePartOperationPreventsUpdate) {
@@ -480,6 +485,10 @@
in.substr(10, 10),
NULL,
NULL));
+
+ // The error also terminates the operation.
+ EXPECT_EQ(CKR_OPERATION_NOT_INITIALIZED,
+ session_->OperationSinglePart(kDigest, in, &len, &out));
}
TEST_F(TestSession, SinglePartOperationPreventsFinal) {
@@ -494,6 +503,10 @@
len = 0;
EXPECT_EQ(CKR_OPERATION_ACTIVE,
session_->OperationFinal(kDigest, &len, &out));
+
+ // The error also terminates the operation.
+ EXPECT_EQ(CKR_OPERATION_NOT_INITIALIZED,
+ session_->OperationSinglePart(kDigest, in, &len, &out));
}
// Test RSA PKCS #1 encryption.