Add wrapping capability to keystore engine
Change-Id: Ie71722747b6f0c5f53a8f333e838a54057eb9ab5
diff --git a/keystore-engine/eng_keystore.cpp b/keystore-engine/eng_keystore.cpp
index 4790a66..e771c2e 100644
--- a/keystore-engine/eng_keystore.cpp
+++ b/keystore-engine/eng_keystore.cpp
@@ -125,7 +125,7 @@
int keystore_rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
int padding) {
- ALOGV("keystore_rsa_sign(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
+ ALOGV("keystore_rsa_priv_enc(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
int num = RSA_size(rsa);
UniquePtr<uint8_t> padded(new uint8_t[num]);
@@ -175,11 +175,11 @@
int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), padded.get(),
num, &reply, &replyLen);
if (ret < 0) {
- ALOGW("There was an error during rsa_mod_exp: could not connect");
+ ALOGW("There was an error during signing: could not connect");
free(reply);
return 0;
} else if (ret != 0) {
- ALOGW("Error during rsa_mod_exp from keystore: %d", ret);
+ ALOGW("Error during signing from keystore: %d", ret);
free(reply);
return 0;
} else if (replyLen <= 0) {
@@ -188,18 +188,87 @@
}
memcpy(to, reply, replyLen);
+ free(reply);
- ALOGV("rsa=%p keystore_rsa_sign => returning %p len %llu", rsa, to,
+ ALOGV("rsa=%p keystore_rsa_priv_enc => returning %p len %llu", rsa, to,
(unsigned long long) replyLen);
return static_cast<int>(replyLen);
}
+int keystore_rsa_priv_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
+ int padding) {
+ ALOGV("keystore_rsa_priv_dec(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
+
+ uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle));
+ if (key_id == NULL) {
+ ALOGE("key had no key_id!");
+ return 0;
+ }
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+ sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+ if (service == NULL) {
+ ALOGE("could not contact keystore");
+ return 0;
+ }
+
+ int num = RSA_size(rsa);
+
+ uint8_t* reply = NULL;
+ size_t replyLen;
+ int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), from,
+ flen, &reply, &replyLen);
+ if (ret < 0) {
+ ALOGW("There was an error during rsa_mod_exp: could not connect");
+ return 0;
+ } else if (ret != 0) {
+ ALOGW("Error during sign from keystore: %d", ret);
+ return 0;
+ } else if (replyLen <= 0) {
+ ALOGW("No valid signature returned");
+ return 0;
+ }
+
+ /* Trim off the top zero if it's there */
+ uint8_t* alignedReply;
+ if (*reply == 0x00) {
+ alignedReply = reply + 1;
+ replyLen--;
+ } else {
+ alignedReply = reply;
+ }
+
+ int outSize;
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ outSize = RSA_padding_check_PKCS1_type_2(to, num, alignedReply, replyLen, num);
+ break;
+ case RSA_X931_PADDING:
+ outSize = RSA_padding_check_X931(to, num, alignedReply, replyLen, num);
+ break;
+ case RSA_NO_PADDING:
+ outSize = RSA_padding_check_none(to, num, alignedReply, replyLen, num);
+ break;
+ default:
+ ALOGE("Unknown padding type: %d", padding);
+ outSize = -1;
+ break;
+ }
+
+ free(reply);
+
+ ALOGV("rsa=%p keystore_rsa_priv_dec => returning %p len %llu", rsa, to, outSize);
+ return outSize;
+}
+
static RSA_METHOD keystore_rsa_meth = {
KEYSTORE_ENGINE_NAME,
- NULL, /* rsa_pub_enc */
+ NULL, /* rsa_pub_enc (wrap) */
NULL, /* rsa_pub_dec (verification) */
keystore_rsa_priv_enc, /* rsa_priv_enc (signing) */
- NULL, /* rsa_priv_dec */
+ keystore_rsa_priv_dec, /* rsa_priv_dec (unwrap) */
NULL, /* rsa_mod_exp */
NULL, /* bn_mod_exp */
NULL, /* init */
@@ -216,7 +285,6 @@
keystore_rsa_meth.rsa_pub_enc = rsa_meth->rsa_pub_enc;
keystore_rsa_meth.rsa_pub_dec = rsa_meth->rsa_pub_dec;
- keystore_rsa_meth.rsa_priv_dec = rsa_meth->rsa_priv_dec;
keystore_rsa_meth.rsa_mod_exp = rsa_meth->rsa_mod_exp;
keystore_rsa_meth.bn_mod_exp = rsa_meth->bn_mod_exp;