1 /*
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 <keymaster/km_openssl/ecdsa_operation.h>
18
19 #include <openssl/ecdsa.h>
20
21 #include <keymaster/km_openssl/ec_key.h>
22 #include <keymaster/km_openssl/openssl_err.h>
23 #include <keymaster/km_openssl/openssl_utils.h>
24
25 namespace keymaster {
26
27 static const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE, KM_DIGEST_SHA1,
28 KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
29 KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
30
CreateOperation(Key && key,const AuthorizationSet & begin_params,keymaster_error_t * error)31 OperationPtr EcdsaOperationFactory::CreateOperation(Key&& key, const AuthorizationSet& begin_params,
32 keymaster_error_t* error) {
33 const EcKey& ecdsa_key = static_cast<EcKey&>(key);
34
35 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
36 if (!ecdsa_key.InternalToEvp(pkey.get())) {
37 *error = KM_ERROR_UNKNOWN_ERROR;
38 return nullptr;
39 }
40
41 keymaster_digest_t digest;
42 if (!GetAndValidateDigest(begin_params, ecdsa_key, &digest, error, true)) {
43 return nullptr;
44 }
45
46 *error = KM_ERROR_OK;
47 auto op = OperationPtr(InstantiateOperation(key.hw_enforced_move(), key.sw_enforced_move(),
48 digest, pkey.release()));
49 if (!op) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
50 return op;
51 }
52
SupportedDigests(size_t * digest_count) const53 const keymaster_digest_t* EcdsaOperationFactory::SupportedDigests(size_t* digest_count) const {
54 *digest_count = array_length(supported_digests);
55 return supported_digests;
56 }
57
~EcdsaOperation()58 EcdsaOperation::~EcdsaOperation() {
59 if (ecdsa_key_ != nullptr) EVP_PKEY_free(ecdsa_key_);
60 EVP_MD_CTX_cleanup(&digest_ctx_);
61 }
62
InitDigest()63 keymaster_error_t EcdsaOperation::InitDigest() {
64 switch (digest_) {
65 case KM_DIGEST_NONE:
66 return KM_ERROR_OK;
67 case KM_DIGEST_MD5:
68 return KM_ERROR_UNSUPPORTED_DIGEST;
69 case KM_DIGEST_SHA1:
70 digest_algorithm_ = EVP_sha1();
71 return KM_ERROR_OK;
72 case KM_DIGEST_SHA_2_224:
73 digest_algorithm_ = EVP_sha224();
74 return KM_ERROR_OK;
75 case KM_DIGEST_SHA_2_256:
76 digest_algorithm_ = EVP_sha256();
77 return KM_ERROR_OK;
78 case KM_DIGEST_SHA_2_384:
79 digest_algorithm_ = EVP_sha384();
80 return KM_ERROR_OK;
81 case KM_DIGEST_SHA_2_512:
82 digest_algorithm_ = EVP_sha512();
83 return KM_ERROR_OK;
84 default:
85 return KM_ERROR_UNSUPPORTED_DIGEST;
86 }
87 }
88
min(size_t a,size_t b)89 inline size_t min(size_t a, size_t b) {
90 return (a < b) ? a : b;
91 }
92
StoreData(const Buffer & input,size_t * input_consumed)93 keymaster_error_t EcdsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
94 if (!data_.reserve((EVP_PKEY_bits(ecdsa_key_) + 7) / 8))
95 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
96
97 if (!data_.write(input.peek_read(), min(data_.available_write(), input.available_read())))
98 return KM_ERROR_UNKNOWN_ERROR;
99
100 *input_consumed = input.available_read();
101 return KM_ERROR_OK;
102 }
103
Begin(const AuthorizationSet &,AuthorizationSet *)104 keymaster_error_t EcdsaSignOperation::Begin(const AuthorizationSet& /* input_params */,
105 AuthorizationSet* /* output_params */) {
106 auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
107 (size_t)sizeof(operation_handle_));
108 if (rc != KM_ERROR_OK) return rc;
109
110 keymaster_error_t error = InitDigest();
111 if (error != KM_ERROR_OK) return error;
112
113 if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
114
115 EVP_PKEY_CTX* pkey_ctx;
116 if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
117 ecdsa_key_) != 1)
118 return TranslateLastOpenSslError();
119 return KM_ERROR_OK;
120 }
121
Update(const AuthorizationSet &,const Buffer & input,AuthorizationSet *,Buffer *,size_t * input_consumed)122 keymaster_error_t EcdsaSignOperation::Update(const AuthorizationSet& /* additional_params */,
123 const Buffer& input,
124 AuthorizationSet* /* output_params */,
125 Buffer* /* output */, size_t* input_consumed) {
126 if (digest_ == KM_DIGEST_NONE) return StoreData(input, input_consumed);
127
128 if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
129 return TranslateLastOpenSslError();
130 *input_consumed = input.available_read();
131 return KM_ERROR_OK;
132 }
133
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer &,AuthorizationSet *,Buffer * output)134 keymaster_error_t EcdsaSignOperation::Finish(const AuthorizationSet& additional_params,
135 const Buffer& input, const Buffer& /* signature */,
136 AuthorizationSet* /* output_params */,
137 Buffer* output) {
138 if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
139
140 keymaster_error_t error = UpdateForFinish(additional_params, input);
141 if (error != KM_ERROR_OK) return error;
142
143 size_t siglen;
144 if (digest_ == KM_DIGEST_NONE) {
145 UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
146 if (!ecdsa.get()) return TranslateLastOpenSslError();
147
148 output->Reinitialize(ECDSA_size(ecdsa.get()));
149 unsigned int siglen_tmp;
150 if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
151 output->peek_write(), &siglen_tmp, ecdsa.get()))
152 return TranslateLastOpenSslError();
153 siglen = siglen_tmp;
154 } else {
155 if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
156 return TranslateLastOpenSslError();
157 if (!output->Reinitialize(siglen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
158 if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
159 return TranslateLastOpenSslError();
160 }
161 if (!output->advance_write(siglen)) return KM_ERROR_UNKNOWN_ERROR;
162 return KM_ERROR_OK;
163 }
164
Begin(const AuthorizationSet &,AuthorizationSet *)165 keymaster_error_t EcdsaVerifyOperation::Begin(const AuthorizationSet& /* input_params */,
166 AuthorizationSet* /* output_params */) {
167 auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
168 (size_t)sizeof(operation_handle_));
169 if (rc != KM_ERROR_OK) return rc;
170
171 keymaster_error_t error = InitDigest();
172 if (error != KM_ERROR_OK) return error;
173
174 if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
175
176 EVP_PKEY_CTX* pkey_ctx;
177 if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
178 ecdsa_key_) != 1)
179 return TranslateLastOpenSslError();
180 return KM_ERROR_OK;
181 }
182
Update(const AuthorizationSet &,const Buffer & input,AuthorizationSet *,Buffer *,size_t * input_consumed)183 keymaster_error_t EcdsaVerifyOperation::Update(const AuthorizationSet& /* additional_params */,
184 const Buffer& input,
185 AuthorizationSet* /* output_params */,
186 Buffer* /* output */, size_t* input_consumed) {
187 if (digest_ == KM_DIGEST_NONE) return StoreData(input, input_consumed);
188
189 if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
190 return TranslateLastOpenSslError();
191 *input_consumed = input.available_read();
192 return KM_ERROR_OK;
193 }
194
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer & signature,AuthorizationSet *,Buffer *)195 keymaster_error_t EcdsaVerifyOperation::Finish(const AuthorizationSet& additional_params,
196 const Buffer& input, const Buffer& signature,
197 AuthorizationSet* /* output_params */,
198 Buffer* /* output */) {
199 keymaster_error_t error = UpdateForFinish(additional_params, input);
200 if (error != KM_ERROR_OK) return error;
201
202 if (digest_ == KM_DIGEST_NONE) {
203 UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
204 if (!ecdsa.get()) return TranslateLastOpenSslError();
205
206 int result =
207 ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
208 signature.peek_read(), signature.available_read(), ecdsa.get());
209 if (result < 0)
210 return TranslateLastOpenSslError();
211 else if (result == 0)
212 return KM_ERROR_VERIFICATION_FAILED;
213 } else if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(),
214 signature.available_read()))
215 return KM_ERROR_VERIFICATION_FAILED;
216
217 return KM_ERROR_OK;
218 }
219
220 } // namespace keymaster
221