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 
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 
53 const keymaster_digest_t* EcdsaOperationFactory::SupportedDigests(size_t* digest_count) const {
54     *digest_count = array_length(supported_digests);
55     return supported_digests;
56 }
57 
58 EcdsaOperation::~EcdsaOperation() {
59     if (ecdsa_key_ != nullptr) EVP_PKEY_free(ecdsa_key_);
60     EVP_MD_CTX_cleanup(&digest_ctx_);
61 }
62 
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 
89 inline size_t min(size_t a, size_t b) {
90     return (a < b) ? a : b;
91 }
92 
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 
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 
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 
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 
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 
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 
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