diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 758594e0..1db0999d 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -37,7 +37,7 @@ class CryptoSession { bool GetSystemId(uint32_t* system_id); bool GetProvisioningId(std::string* provisioning_id); - bool Open(); + CdmResponseType Open(); void Close(); bool IsOpen() { return open_; } @@ -49,9 +49,11 @@ class CryptoSession { bool is_provisioning, std::string* signature); bool PrepareRenewalRequest(const std::string& message, std::string* signature); - bool LoadKeys(const std::string& message, const std::string& signature, - const std::string& mac_key_iv, const std::string& mac_key, - int num_keys, const CryptoKey* key_array); + CdmResponseType LoadKeys(const std::string& message, + const std::string& signature, + const std::string& mac_key_iv, + const std::string& mac_key, + int num_keys, const CryptoKey* key_array); bool LoadCertificatePrivateKey(std::string& wrapped_key); bool RefreshKeys(const std::string& message, const std::string& signature, int num_keys, const CryptoKey* key_array); diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index f65b3c16..0be6a9e7 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -38,6 +38,7 @@ enum CdmResponseType { KEY_CANCELED, NEED_PROVISIONING, DEVICE_REVOKED, + INSUFFICIENT_CRYPTO_RESOURCES, }; #define CORE_DISALLOW_COPY_AND_ASSIGN(TypeName) \ diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 225b9a0d..688216d7 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -28,7 +28,8 @@ typedef std::set::iterator CdmEventListenerIter; CdmResponseType CdmSession::Init() { scoped_ptr session(new CryptoSession()); - if (!session->Open()) return UNKNOWN_ERROR; + CdmResponseType sts = session->Open(); + if (NO_ERROR != sts) return sts; std::string token; if (Properties::use_certificates_as_identification()) { diff --git a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp index e7332266..fd034ad4 100644 --- a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp +++ b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp @@ -57,9 +57,10 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest( std::string* default_url) { default_url->assign(kDefaultProvisioningServerUrl); - if (!crypto_session_.Open()) { + CdmResponseType sts = crypto_session_.Open(); + if (NO_ERROR != sts) { LOGE("GetProvisioningRequest: fails to create a crypto session"); - return UNKNOWN_ERROR; + return sts; } // Prepares device provisioning request. diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 998ebe18..7896c2ad 100755 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -205,19 +205,22 @@ bool CryptoSession::GetProvisioningId(std::string* provisioning_id) { return true; } -bool CryptoSession::Open() { +CdmResponseType CryptoSession::Open() { LOGV("CryptoSession::Open: Lock"); AutoLock auto_lock(crypto_lock_); if (!initialized_) return false; if (open_) return true; OEMCrypto_SESSION sid; - if (OEMCrypto_SUCCESS == OEMCrypto_OpenSession(&sid)) { + OEMCryptoResult sts = OEMCrypto_OpenSession(&sid); + if (OEMCrypto_SUCCESS == sts) { oec_session_id_ = static_cast(sid); LOGV("OpenSession: id= %ld", (uint32_t)oec_session_id_); open_ = true; + } else if (OEMCrypto_ERROR_TOO_MANY_SESSIONS == sts) { + return INSUFFICIENT_CRYPTO_RESOURCES; } - return open_; + return open_ ? NO_ERROR : UNKNOWN_ERROR; } void CryptoSession::Close() { @@ -319,11 +322,12 @@ size_t CryptoSession::GetOffset(std::string message, std::string field) { return pos; } -bool CryptoSession::LoadKeys(const std::string& message, - const std::string& signature, - const std::string& mac_key_iv, - const std::string& mac_key, int num_keys, - const CryptoKey* key_array) { +CdmResponseType CryptoSession::LoadKeys(const std::string& message, + const std::string& signature, + const std::string& mac_key_iv, + const std::string& mac_key, + int num_keys, + const CryptoKey* key_array) { LOGV("CryptoSession::LoadKeys: Lock"); AutoLock auto_lock(crypto_lock_); @@ -354,11 +358,18 @@ bool CryptoSession::LoadKeys(const std::string& message, } } LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_); - return (OEMCrypto_SUCCESS == - OEMCrypto_LoadKeys(oec_session_id_, msg, message.size(), - reinterpret_cast(signature.data()), - signature.size(), enc_mac_key_iv, enc_mac_key, - num_keys, &load_key_array[0])); + OEMCryptoResult sts = OEMCrypto_LoadKeys( + oec_session_id_, msg, message.size(), + reinterpret_cast(signature.data()), signature.size(), + enc_mac_key_iv, enc_mac_key, num_keys, &load_key_array[0]); + + if (OEMCrypto_SUCCESS == sts) { + return KEY_ADDED; + } else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) { + return INSUFFICIENT_CRYPTO_RESOURCES; + } else { + return KEY_ERROR; + } } bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) { @@ -565,7 +576,9 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { &buffer_descriptor, params.subsample_flags); - if (OEMCrypto_SUCCESS != sts) { + if (OEMCrypto_ERROR_INSUFFICIENT_RESOURCES == sts) { + return INSUFFICIENT_CRYPTO_RESOURCES; + } else if (OEMCrypto_SUCCESS != sts) { return UNKNOWN_ERROR; } return NO_ERROR; diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 982cb024..d8b01d84 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -368,13 +368,9 @@ CdmResponseType CdmLicense::HandleKeyResponse( // merge from Eureka) policy_engine_->SetLicense(license); - if (session_->LoadKeys(signed_response.msg(), signed_response.signature(), - mac_key_iv, mac_key, key_array.size(), - &key_array[0])) { - return KEY_ADDED; - } else { - return KEY_ERROR; - } + return session_->LoadKeys(signed_response.msg(), signed_response.signature(), + mac_key_iv, mac_key, key_array.size(), + &key_array[0]); } CdmResponseType CdmLicense::HandleKeyUpdateResponse( diff --git a/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf index 5e2286d3..269a7e9a 100644 Binary files a/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf and b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf differ diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index b3f688da..9c0084ef 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -27,6 +27,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return android::ERROR_DRM_NOT_PROVISIONED; case wvcdm::DEVICE_REVOKED: return android::ERROR_DRM_DEVICE_REVOKED; + case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES: + return android::ERROR_DRM_RESOURCE_BUSY; case wvcdm::KEY_ERROR: // KEY_ERROR is used by the CDM to mean just about any kind of error, not // just license errors, so it is mapped to the generic response. diff --git a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp index 64250671..0e81cb31 100644 --- a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp +++ b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp @@ -153,7 +153,13 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], ALOGE("Decrypt error result in session %s during unencrypted block: %d", mSessionId.c_str(), res); errorDetailMsg->setTo("Error decrypting data."); - return kErrorCDMGeneric; + if (res == wvcdm::INSUFFICIENT_CRYPTO_RESOURCES) { + // This error is actionable by the app and should be passed up. + return mapCdmResponseType(res); + } else { + // Swallow the specifics of other errors to obscure decrypt internals. + return kErrorCDMGeneric; + } } offset += subSample.mNumBytesOfClearData; @@ -175,7 +181,13 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], ALOGE("Decrypt error result in session %s during encrypted block: %d", mSessionId.c_str(), res); errorDetailMsg->setTo("Error decrypting data."); - return kErrorCDMGeneric; + if (res == wvcdm::INSUFFICIENT_CRYPTO_RESOURCES) { + // This error is actionable by the app and should be passed up. + return mapCdmResponseType(res); + } else { + // Swallow the specifics of other errors to obscure decrypt internals. + return kErrorCDMGeneric; + } } offset += subSample.mNumBytesOfEncryptedData; diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index f964987c..720f7c20 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -59,6 +59,8 @@ typedef enum OEMCryptoResult { OEMCrypto_ERROR_TOO_MANY_KEYS = 33, OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED = 34, OEMCrypto_ERROR_INVALID_RSA_KEY = 35, + OEMCrypto_ERROR_KEY_EXPIRED = 36, + OEMCrypto_ERROR_INSUFFICIENT_RESOURCES = 37, } OEMCryptoResult; /* @@ -353,8 +355,9 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session); * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 8. @@ -390,10 +393,9 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys( * * Returns: * OEMCrypto_SUCCESS success - * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE - * OEMCrypto_ERROR_INVALID_CONTEXT * * Version: * This method changed in API version 5. @@ -431,9 +433,10 @@ OEMCryptoResult OEMCrypto_GenerateNonce( * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_SHORT_BUFFER - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT + * OEMCrypto_ERROR_SHORT_BUFFER + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 5. @@ -506,11 +509,11 @@ OEMCryptoResult OEMCrypto_GenerateSignature( * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT * OEMCrypto_ERROR_SIGNATURE_FAILURE * OEMCrypto_ERROR_INVALID_NONCE * OEMCrypto_ERROR_TOO_MANY_KEYS + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 8. @@ -562,10 +565,11 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT * OEMCrypto_ERROR_INVALID_NONCE * OEMCrypto_ERROR_SIGNATURE_FAILURE + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 8. @@ -617,12 +621,15 @@ OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, * but not with other functions on this session. * * Returns: - * OEMCrypto_SUCCESS success - * OEMCrypto_ERROR_INVALID_SESSION crypto session ID invalid or not open - * OEMCrypto_ERROR_NO_DEVICE_KEY failed to decrypt device key - * OEMCrypto_ERROR_NO_CONTENT_KEY failed to decrypt content key - * OEMCrypto_ERROR_CONTROL_INVALID invalid or unsupported control input - * OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox + * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_INVALID_SESSION crypto session ID invalid or not open + * OEMCrypto_ERROR_NO_DEVICE_KEY failed to decrypt device key + * OEMCrypto_ERROR_NO_CONTENT_KEY failed to decrypt content key + * OEMCrypto_ERROR_CONTROL_INVALID invalid or unsupported control input + * OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox + * OEMCrypto_ERROR_KEY_EXPIRED + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 8. @@ -710,9 +717,11 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, * OEMCrypto_SUCCESS * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT * OEMCrypto_ERROR_DECRYPT_FAILED + * OEMCrypto_ERROR_KEY_EXPIRED + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 5. @@ -726,6 +735,44 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, const OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags); +/* + * OEMCrypto_WrapKeybox + * + * Description: + * Wrap the Keybox with a key derived from the device key. If transportKey + * is not NULL, the input keybox is encrypted with transportKey. If so, + * decrypt the input keybox before wrapping it, using transportKey in AES-CBC + * mode with an IV of all zeroes. This function is only needed if the + * provisioning method involves saving the keybox to the file system. + * + * Parameters: + * keybox (in) - Pointer to keybox data. + * keyboxLength - Length of the Keybox data in bytes + * wrappedKeybox (out) - Pointer to wrapped keybox + * wrappedKeyboxLength (out) - Pointer to the length of the wrapped keybox in + * bytes + * transportKey (in) - An optional AES transport key. If provided, the input + * keybox is encrypted with this transport key with AES-CBC + * and a null IV. + * transportKeyLength - number of bytes in the transportKey + * + * Returns: + * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_WRAP_KEYBOX failed to wrap Keybox + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_NOT_IMPLEMENTED + * + * Version: + * This method is supported by all API versions. + */ +OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, + size_t keyBoxLength, + uint8_t *wrappedKeybox, + size_t *wrappedKeyBoxLength, + const uint8_t *transportKey, + size_t transportKeyLength); + + /* * OEMCrypto_InstallKeybox * @@ -746,6 +793,7 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, * * Returns: * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_WRITE_KEYBOX failed to handle and store Keybox * * Version: @@ -865,43 +913,6 @@ OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength); -/* - * OEMCrypto_WrapKeybox - * - * Description: - * Wrap the Keybox with a key derived for the device key. If transportKey - * is not NULL, the input keybox is encrypted with transportKey. If so, - * decrypt the input keybox before wrapping it, using transportKey in AES-CBC - * mode with an IV of all zeroes. This function is only needed if the - * provisioning method involves saving the keybox to the file system. - * - * Parameters: - * keybox (in) - Pointer to keybox data. - * keyboxLength - Length of the Keybox data in bytes - * wrappedKeybox (out) - Pointer to wrapped keybox - * wrappedKeyboxLength (out) - Pointer to the length of the wrapped keybox in - * bytes - * transportKey (in) - An optional AES transport key. If provided, the input - * keybox is encrypted with this transport key with AES-CBC - * and a null IV. - * transportKeyLength - number of bytes in the transportKey - * - * Returns: - * OEMCrypto_SUCCESS success - * OEMCrypto_ERROR_WRAP_KEYBOX failed to wrap Keybox - * OEMCrypto_ERROR_NOT_IMPLEMENTED - * - * Version: - * This method is supported by all API versions. - */ -OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, - size_t keyBoxLength, - uint8_t *wrappedKeybox, - size_t *wrappedKeyBoxLength, - const uint8_t *transportKey, - size_t transportKeyLength); - - /* * OEMCrypto_RewrapDeviceRSAKey * @@ -940,11 +951,12 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_RSA_KEY * OEMCrypto_ERROR_SIGNATURE_FAILURE * OEMCrypto_ERROR_INVALID_NONCE * OEMCrypto_ERROR_SHORT_BUFFER + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API versions 8. @@ -987,8 +999,9 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_RSA_KEY + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 6. @@ -1024,6 +1037,9 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_INVALID_SESSION * OEMCrypto_ERROR_SHORT_BUFFER if the signature buffer is too small. + * OEMCrypto_ERROR_INVALID_RSA_KEY + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 6. @@ -1068,8 +1084,9 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED * OEMCrypto_ERROR_INVALID_SESSION - * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_INVALID_CONTEXT + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Version: * This method changed in API version 8. @@ -1145,8 +1162,10 @@ const char* OEMCrypto_SecurityLevel(); * * Returns: * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_KEY_EXPIRED * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Threading: @@ -1190,8 +1209,10 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, * * Returns: * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_KEY_EXPIRED * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Threading: @@ -1232,10 +1253,14 @@ OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session, * Returns * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_SHORT_BUFFER if signature buffer is not large enough to hold - * buffer. + * signature. + * OEMCrypto_ERROR_KEY_EXPIRED + * OEMCrypto_ERROR_DECRYPT_FAILED * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE + * * Threading * This function may be called simultaneously with functions on other sessions, * but not with other functions on this session. @@ -1275,9 +1300,11 @@ OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, * * Returns: * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_KEY_EXPIRED * OEMCrypto_ERROR_SIGNATURE_FAILURE * OEMCrypto_ERROR_NO_DEVICE_KEY * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * * Threading: