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