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