diff options
author | Shawn Willden <swillden@google.com> | 2014-12-29 14:07:08 -0700 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-02-25 12:32:45 -0700 |
commit | 63ac043f81f8e2a15bbadcb6628b92096295ab6a (patch) | |
tree | c75bc9e2d2c96a9745cf7dd000168ea0eab1538a /rsa_operation.cpp | |
parent | 3745efd184f9989137289b8a6fcb32afc308f94a (diff) | |
download | android_system_keymaster-63ac043f81f8e2a15bbadcb6628b92096295ab6a.tar.gz android_system_keymaster-63ac043f81f8e2a15bbadcb6628b92096295ab6a.tar.bz2 android_system_keymaster-63ac043f81f8e2a15bbadcb6628b92096295ab6a.zip |
Refactor operation creation to use an operation factory registry.
Also modify GoogleKeymaster to query the operation factories to get
lists of supported modes and digests.
Change-Id: Ied30185df5dddaeaeb1106df63237757896d77db
Diffstat (limited to 'rsa_operation.cpp')
-rw-r--r-- | rsa_operation.cpp | 201 |
1 files changed, 198 insertions, 3 deletions
diff --git a/rsa_operation.cpp b/rsa_operation.cpp index 4ca7812..27394a6 100644 --- a/rsa_operation.cpp +++ b/rsa_operation.cpp @@ -14,17 +14,212 @@ * limitations under the License. */ +#include "rsa_operation.h" + #include <limits.h> #include <openssl/err.h> -#include <openssl/evp.h> -#include <openssl/rsa.h> -#include "rsa_operation.h" #include "openssl_utils.h" +#include "rsa_key.h" namespace keymaster { +/** + * Abstract base for all RSA operation factories. This class exists mainly to centralize some code + * common to all RSA operation factories. + */ +class RsaOperationFactory : public OperationFactory { + public: + virtual KeyType registry_key() const { return KeyType(KM_ALGORITHM_RSA, purpose()); } + virtual keymaster_purpose_t purpose() const = 0; + + protected: + bool GetAndValidatePadding(const Key& key, keymaster_padding_t* padding, + keymaster_error_t* error) const; + bool GetAndValidateDigest(const Key& key, keymaster_digest_t* digest, + keymaster_error_t* error) const; + static RSA* GetRsaKey(const Key& key, keymaster_error_t* error); +}; + +bool RsaOperationFactory::GetAndValidatePadding(const Key& key, keymaster_padding_t* padding, + keymaster_error_t* error) const { + *error = KM_ERROR_UNSUPPORTED_PADDING_MODE; + if (!key.authorizations().GetTagValue(TAG_PADDING, padding)) + return false; + + size_t padding_count; + const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count); + for (size_t i = 0; i < padding_count; ++i) { + if (*padding == supported_paddings[i]) { + *error = KM_ERROR_OK; + return true; + } + } + return false; +} + +bool RsaOperationFactory::GetAndValidateDigest(const Key& key, keymaster_digest_t* digest, + keymaster_error_t* error) const { + *error = KM_ERROR_UNSUPPORTED_DIGEST; + if (!key.authorizations().GetTagValue(TAG_DIGEST, digest)) + return false; + + size_t digest_count; + const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count); + for (size_t i = 0; i < digest_count; ++i) { + if (*digest == supported_digests[i]) { + *error = KM_ERROR_OK; + return true; + } + } + return false; +} + +/* static */ +RSA* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) { + const RsaKey* rsa_key = static_cast<const RsaKey*>(&key); + assert(rsa_key); + if (!rsa_key || !rsa_key->key()) { + *error = KM_ERROR_UNKNOWN_ERROR; + return NULL; + } + return RSAPrivateKey_dup(rsa_key->key()); +} + +static const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE}; +static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE}; + +/** + * Abstract base for RSA operations that digest their input (signing and verification). This class + * does most of the work of creation of RSA digesting operations, delegating only the actual + * operation instantiation. + */ +class RsaDigestingOperationFactory : public RsaOperationFactory { + public: + virtual Operation* CreateOperation(const Key& key, const Logger& logger, + keymaster_error_t* error); + + virtual const keymaster_digest_t* SupportedDigests(size_t* digest_count) const { + *digest_count = array_length(supported_digests); + return supported_digests; + } + + virtual const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const { + *padding_mode_count = array_length(supported_sig_padding); + return supported_sig_padding; + } + + private: + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_digest_t digest, + keymaster_padding_t padding, RSA* key) = 0; +}; + +Operation* RsaDigestingOperationFactory::CreateOperation(const Key& key, const Logger& logger, + keymaster_error_t* error) { + keymaster_padding_t padding; + keymaster_digest_t digest; + RSA* rsa; + if (!GetAndValidateDigest(key, &digest, error) || + !GetAndValidatePadding(key, &padding, error) || !(rsa = GetRsaKey(key, error))) + return NULL; + + Operation* op = InstantiateOperation(logger, digest, padding, rsa); + if (!op) + *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; + return op; +} + +static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_RSA_OAEP, + KM_PAD_RSA_PKCS1_1_5_ENCRYPT}; + +/** + * Abstract base for en/de-crypting RSA operation factories. This class does most of the work of + * creating such operations, delegating only the actual operation instantiation. + */ +class RsaCryptingOperationFactory : public RsaOperationFactory { + public: + virtual Operation* CreateOperation(const Key& key, const Logger& logger, + keymaster_error_t* error); + + virtual const keymaster_padding_t* SupportedPaddingModes(size_t* padding_mode_count) const { + *padding_mode_count = array_length(supported_crypt_padding); + return supported_crypt_padding; + } + + virtual const keymaster_digest_t* SupportedDigests(size_t* digest_count) const { + *digest_count = 0; + return NULL; + } + + private: + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_padding_t padding, + RSA* key) = 0; +}; + +Operation* RsaCryptingOperationFactory::CreateOperation(const Key& key, const Logger& logger, + keymaster_error_t* error) { + keymaster_padding_t padding; + RSA* rsa; + if (!GetAndValidatePadding(key, &padding, error) || !(rsa = GetRsaKey(key, error))) + return NULL; + + Operation* op = InstantiateOperation(logger, padding, rsa); + if (!op) + *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; + return op; +} + +/** + * Concrete factory for RSA signing operations. + */ +class RsaSigningOperationFactory : public RsaDigestingOperationFactory { + public: + virtual keymaster_purpose_t purpose() const { return KM_PURPOSE_SIGN; } + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_digest_t digest, + keymaster_padding_t padding, RSA* key) { + return new RsaSignOperation(logger, digest, padding, key); + } +}; +static OperationFactoryRegistry::Registration<RsaSigningOperationFactory> sign_registration; + +/** + * Concrete factory for RSA signing operations. + */ +class RsaVerificationOperationFactory : public RsaDigestingOperationFactory { + virtual keymaster_purpose_t purpose() const { return KM_PURPOSE_VERIFY; } + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_digest_t digest, + keymaster_padding_t padding, RSA* key) { + return new RsaVerifyOperation(logger, digest, padding, key); + } +}; +static OperationFactoryRegistry::Registration<RsaVerificationOperationFactory> verify_registration; + +/** + * Concrete factory for RSA signing operations. + */ +class RsaEncryptionOperationFactory : public RsaCryptingOperationFactory { + virtual keymaster_purpose_t purpose() const { return KM_PURPOSE_ENCRYPT; } + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_padding_t padding, + RSA* key) { + return new RsaEncryptOperation(logger, padding, key); + } +}; +static OperationFactoryRegistry::Registration<RsaEncryptionOperationFactory> encrypt_registration; + +/** + * Concrete factory for RSA signing operations. + */ +class RsaDecryptionOperationFactory : public RsaCryptingOperationFactory { + virtual keymaster_purpose_t purpose() const { return KM_PURPOSE_DECRYPT; } + virtual Operation* InstantiateOperation(const Logger& logger, keymaster_padding_t padding, + RSA* key) { + return new RsaDecryptOperation(logger, padding, key); + } +}; + +static OperationFactoryRegistry::Registration<RsaDecryptionOperationFactory> decrypt_registration; + struct RSA_Delete { void operator()(RSA* p) const { RSA_free(p); } }; |