Add key importing, RSA only.
Change-Id: I639e797939a28b2b2a815541c9926dc194657c54
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 32d8fe9..8698ff4 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -154,6 +154,68 @@
return new_key;
}
+/* static */
+RsaKey* RsaKey::ImportKey(const AuthorizationSet& key_description, EVP_PKEY* pkey,
+ keymaster_error_t* error) {
+ if (!error)
+ return NULL;
+ *error = KM_ERROR_UNKNOWN_ERROR;
+
+ UniquePtr<RSA, RSA_Delete> rsa_key(EVP_PKEY_get1_RSA(pkey));
+ if (!rsa_key.get())
+ return NULL;
+
+ AuthorizationSet authorizations(key_description);
+
+ uint64_t public_exponent;
+ if (authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
+ // public_exponent specified, make sure it matches the key
+ UniquePtr<BIGNUM, BIGNUM_Delete> public_exponent_bn(BN_new());
+ if (!BN_set_word(public_exponent_bn.get(), public_exponent))
+ return NULL;
+ if (BN_cmp(public_exponent_bn.get(), rsa_key->e) != 0) {
+ *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ return NULL;
+ }
+ } else {
+ // public_exponent not specified, use the one from the key.
+ public_exponent = BN_get_word(rsa_key->e);
+ if (public_exponent == 0xffffffffL) {
+ *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ return NULL;
+ }
+ authorizations.push_back(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
+ }
+
+ uint32_t key_size;
+ if (authorizations.GetTagValue(TAG_KEY_SIZE, &key_size)) {
+ // key_size specified, make sure it matches the key.
+ if (RSA_size(rsa_key.get()) != (int)key_size) {
+ *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ return NULL;
+ }
+ } else {
+ key_size = RSA_size(rsa_key.get()) * 8;
+ authorizations.push_back(TAG_KEY_SIZE, key_size);
+ }
+
+ keymaster_algorithm_t algorithm;
+ if (authorizations.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+ if (algorithm != KM_ALGORITHM_RSA) {
+ *error = KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ return NULL;
+ }
+ } else {
+ authorizations.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA);
+ }
+
+ // Don't bother with the other parameters. If the necessary padding, digest, purpose, etc. are
+ // missing, the error will be diagnosed when the key is used (when auth checking is
+ // implemented).
+ *error = KM_ERROR_OK;
+ return new RsaKey(rsa_key.release(), authorizations);
+}
+
RsaKey::RsaKey(const KeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) {
if (error)
*error = LoadKey(blob);