Add RSA verification.
Change-Id: Ie9ac37dba7ead62b0ca17054bbf6d2744cea5946
diff --git a/rsa_operation.cpp b/rsa_operation.cpp
index 4635154..620df65 100644
--- a/rsa_operation.cpp
+++ b/rsa_operation.cpp
@@ -66,7 +66,7 @@
// Since we're not using a digest function, we just need to store the text, up to the key
// size, until Finish is called, so we allocate a place to put it.
- if (!data_to_sign_.Reinitialize(RSA_size(rsa_key_))) {
+ if (!data_.Reinitialize(RSA_size(rsa_key_))) {
error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
return;
}
@@ -78,37 +78,54 @@
RSA_free(rsa_key_);
}
-keymaster_error_t RsaOperation::Update(const Buffer& input, Buffer* output) {
+keymaster_error_t RsaOperation::Update(const Buffer& input, Buffer* /* output */) {
switch (purpose()) {
default:
return KM_ERROR_UNIMPLEMENTED;
case KM_PURPOSE_SIGN:
- return Sign(input, output);
+ case KM_PURPOSE_VERIFY:
+ return StoreData(input);
}
}
-keymaster_error_t RsaOperation::Sign(const Buffer& input, Buffer* /* output */) {
- if (!data_to_sign_.write(input.peek_read(), input.available_read()))
+keymaster_error_t RsaOperation::StoreData(const Buffer& input) {
+ if (!data_.write(input.peek_read(), input.available_read()))
return KM_ERROR_INVALID_INPUT_LENGTH;
return KM_ERROR_OK;
}
-keymaster_error_t RsaOperation::Finish(Buffer* signature, Buffer* /* output */) {
+keymaster_error_t RsaOperation::Finish(const Buffer& signature, Buffer* output) {
switch (purpose()) {
case KM_PURPOSE_SIGN: {
- signature->Reinitialize(RSA_size(rsa_key_));
- if (data_to_sign_.available_read() != signature->buffer_size())
+ output->Reinitialize(RSA_size(rsa_key_));
+ if (data_.available_read() != output->buffer_size())
return KM_ERROR_INVALID_INPUT_LENGTH;
- int bytes_encrypted =
- RSA_private_encrypt(data_to_sign_.available_read(), data_to_sign_.peek_read(),
- signature->peek_write(), rsa_key_, RSA_NO_PADDING);
+ int bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
+ output->peek_write(), rsa_key_, RSA_NO_PADDING);
if (bytes_encrypted < 0)
return KM_ERROR_UNKNOWN_ERROR;
assert(bytes_encrypted == RSA_size(rsa_key_));
- signature->advance_write(bytes_encrypted);
+ output->advance_write(bytes_encrypted);
return KM_ERROR_OK;
}
+ case KM_PURPOSE_VERIFY: {
+ if ((int)data_.available_read() != RSA_size(rsa_key_))
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ if (data_.available_read() != signature.available_read())
+ return KM_ERROR_VERIFICATION_FAILED;
+
+ UniquePtr<uint8_t[]> decrypted_data(new uint8_t[RSA_size(rsa_key_)]);
+ int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
+ decrypted_data.get(), rsa_key_, RSA_NO_PADDING);
+ if (bytes_decrypted < 0)
+ return KM_ERROR_UNKNOWN_ERROR;
+ assert(bytes_decrypted == RSA_size(rsa_key_));
+
+ if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) == 0)
+ return KM_ERROR_OK;
+ return KM_ERROR_VERIFICATION_FAILED;
+ }
default:
return KM_ERROR_UNIMPLEMENTED;
}