blob: 2d582dbbefecc0aa464adb56420dd4cc9c5ecc4e [file] [log] [blame]
Shawn Willden1615f2e2014-08-13 10:37:40 -06001/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <openssl/rsa.h>
18#include <openssl/evp.h>
19
20#include "rsa_operation.h"
Shawn Willden28e41472014-08-18 13:35:22 -060021#include "openssl_utils.h"
Shawn Willden1615f2e2014-08-13 10:37:40 -060022
23namespace keymaster {
24
Shawn Willden802bb292014-08-18 10:46:29 -060025struct RSA_Delete {
26 void operator()(RSA* p) const { RSA_free(p); }
27};
28
Shawn Willden802bb292014-08-18 10:46:29 -060029/* static */
30keymaster_error_t RsaOperation::Generate(uint64_t public_exponent, uint32_t key_size,
31 UniquePtr<uint8_t[]>* key_data, size_t* key_data_size) {
32 if (key_data == NULL || key_data_size == NULL)
33 return KM_ERROR_OUTPUT_PARAMETER_NULL;
34
35 UniquePtr<BIGNUM, BIGNUM_Delete> exponent(BN_new());
36 UniquePtr<RSA, RSA_Delete> rsa_key(RSA_new());
37 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
38 if (rsa_key.get() == NULL || pkey.get() == NULL)
39 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
40
41 if (!BN_set_word(exponent.get(), public_exponent) ||
42 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */))
43 return KM_ERROR_UNKNOWN_ERROR;
44
45 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa_key.get()))
46 return KM_ERROR_UNKNOWN_ERROR;
47 else
48 release_because_ownership_transferred(rsa_key);
49
50 *key_data_size = i2d_PrivateKey(pkey.get(), NULL);
51 if (*key_data_size <= 0)
52 return KM_ERROR_UNKNOWN_ERROR;
53
54 key_data->reset(new uint8_t[*key_data_size]);
55 if (key_data->get() == NULL)
56 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
57
58 uint8_t* tmp = key_data->get();
59 i2d_PrivateKey(pkey.get(), &tmp);
60
61 return KM_ERROR_OK;
62}
Shawn Willden1615f2e2014-08-13 10:37:40 -060063
64RsaOperation::RsaOperation(keymaster_purpose_t purpose, const KeyBlob& key)
65 : Operation(purpose), rsa_key_(NULL) {
66 assert(key.algorithm() == KM_ALGORITHM_RSA);
67
68 if ((!key.enforced().GetTagValue(TAG_DIGEST, &digest_) &&
69 !key.unenforced().GetTagValue(TAG_DIGEST, &digest_)) ||
70 digest_ != KM_DIGEST_NONE) {
71 error_ = KM_ERROR_UNSUPPORTED_DIGEST;
72 return;
73 }
74
75 if ((!key.enforced().GetTagValue(TAG_PADDING, &padding_) &&
76 !key.unenforced().GetTagValue(TAG_PADDING, &padding_)) ||
77 padding_ != KM_PAD_NONE) {
78 error_ = KM_ERROR_UNSUPPORTED_PADDING_MODE;
79 return;
80 }
81
82 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> evp_key(EVP_PKEY_new());
83 if (evp_key.get() == NULL) {
84 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
85 return;
86 }
87
88 EVP_PKEY* tmp_pkey = evp_key.get();
89 const uint8_t* key_material = key.key_material();
90 if (d2i_PrivateKey(EVP_PKEY_RSA, &tmp_pkey, &key_material, key.key_material_length()) == NULL) {
91 error_ = KM_ERROR_INVALID_KEY_BLOB;
92 return;
93 }
94
95 rsa_key_ = EVP_PKEY_get1_RSA(evp_key.get());
96 if (rsa_key_ == NULL) {
97 error_ = KM_ERROR_UNKNOWN_ERROR;
98 return;
99 }
100
101 // Since we're not using a digest function, we just need to store the text, up to the key
102 // size, until Finish is called, so we allocate a place to put it.
Shawn Willden43e999e2014-08-13 13:29:50 -0600103 if (!data_.Reinitialize(RSA_size(rsa_key_))) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600104 error_ = KM_ERROR_MEMORY_ALLOCATION_FAILED;
105 return;
106 }
107 error_ = KM_ERROR_OK;
108}
109
110RsaOperation::~RsaOperation() {
111 if (rsa_key_ != NULL)
112 RSA_free(rsa_key_);
113}
114
Shawn Willden43e999e2014-08-13 13:29:50 -0600115keymaster_error_t RsaOperation::Update(const Buffer& input, Buffer* /* output */) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600116 switch (purpose()) {
117 default:
118 return KM_ERROR_UNIMPLEMENTED;
119 case KM_PURPOSE_SIGN:
Shawn Willden43e999e2014-08-13 13:29:50 -0600120 case KM_PURPOSE_VERIFY:
121 return StoreData(input);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600122 }
123}
124
Shawn Willden43e999e2014-08-13 13:29:50 -0600125keymaster_error_t RsaOperation::StoreData(const Buffer& input) {
126 if (!data_.write(input.peek_read(), input.available_read()))
Shawn Willden1615f2e2014-08-13 10:37:40 -0600127 return KM_ERROR_INVALID_INPUT_LENGTH;
128 return KM_ERROR_OK;
129}
130
Shawn Willden43e999e2014-08-13 13:29:50 -0600131keymaster_error_t RsaOperation::Finish(const Buffer& signature, Buffer* output) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600132 switch (purpose()) {
133 case KM_PURPOSE_SIGN: {
Shawn Willden43e999e2014-08-13 13:29:50 -0600134 output->Reinitialize(RSA_size(rsa_key_));
135 if (data_.available_read() != output->buffer_size())
Shawn Willden1615f2e2014-08-13 10:37:40 -0600136 return KM_ERROR_INVALID_INPUT_LENGTH;
137
Shawn Willden43e999e2014-08-13 13:29:50 -0600138 int bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
139 output->peek_write(), rsa_key_, RSA_NO_PADDING);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600140 if (bytes_encrypted < 0)
141 return KM_ERROR_UNKNOWN_ERROR;
142 assert(bytes_encrypted == RSA_size(rsa_key_));
Shawn Willden43e999e2014-08-13 13:29:50 -0600143 output->advance_write(bytes_encrypted);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600144 return KM_ERROR_OK;
145 }
Shawn Willden43e999e2014-08-13 13:29:50 -0600146 case KM_PURPOSE_VERIFY: {
147 if ((int)data_.available_read() != RSA_size(rsa_key_))
148 return KM_ERROR_INVALID_INPUT_LENGTH;
149 if (data_.available_read() != signature.available_read())
150 return KM_ERROR_VERIFICATION_FAILED;
151
152 UniquePtr<uint8_t[]> decrypted_data(new uint8_t[RSA_size(rsa_key_)]);
153 int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
154 decrypted_data.get(), rsa_key_, RSA_NO_PADDING);
155 if (bytes_decrypted < 0)
156 return KM_ERROR_UNKNOWN_ERROR;
157 assert(bytes_decrypted == RSA_size(rsa_key_));
158
159 if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) == 0)
160 return KM_ERROR_OK;
161 return KM_ERROR_VERIFICATION_FAILED;
162 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600163 default:
164 return KM_ERROR_UNIMPLEMENTED;
165 }
166}
167
168} // namespace keymaster