• 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 "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 &,const Buffer &,AuthorizationSet *,Buffer * output)138 keymaster_error_t EcdsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
139                                              const Buffer& /* signature */,
140                                              AuthorizationSet* /* output_params */,
141                                              Buffer* output) {
142     if (!output)
143         return KM_ERROR_OUTPUT_PARAMETER_NULL;
144 
145     size_t siglen;
146     if (digest_ == KM_DIGEST_NONE) {
147         UniquePtr<EC_KEY, EC_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
148         if (!ecdsa.get())
149             return TranslateLastOpenSslError();
150 
151         output->Reinitialize(ECDSA_size(ecdsa.get()));
152         unsigned int siglen_tmp;
153         if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
154                         output->peek_write(), &siglen_tmp, ecdsa.get()))
155             return TranslateLastOpenSslError();
156         siglen = siglen_tmp;
157     } else {
158         if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
159             return TranslateLastOpenSslError();
160         if (!output->Reinitialize(siglen))
161             return KM_ERROR_MEMORY_ALLOCATION_FAILED;
162         if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
163             return TranslateLastOpenSslError();
164     }
165     if (!output->advance_write(siglen))
166         return KM_ERROR_UNKNOWN_ERROR;
167     return KM_ERROR_OK;
168 }
169 
Begin(const AuthorizationSet &,AuthorizationSet *)170 keymaster_error_t EcdsaVerifyOperation::Begin(const AuthorizationSet& /* input_params */,
171                                               AuthorizationSet* /* output_params */) {
172     keymaster_error_t error = InitDigest();
173     if (error != KM_ERROR_OK)
174         return error;
175 
176     if (digest_ == KM_DIGEST_NONE)
177         return KM_ERROR_OK;
178 
179     EVP_PKEY_CTX* pkey_ctx;
180     if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
181                              ecdsa_key_) != 1)
182         return TranslateLastOpenSslError();
183     return KM_ERROR_OK;
184 }
185 
Update(const AuthorizationSet &,const Buffer & input,AuthorizationSet *,Buffer *,size_t * input_consumed)186 keymaster_error_t EcdsaVerifyOperation::Update(const AuthorizationSet& /* additional_params */,
187                                                const Buffer& input,
188                                                AuthorizationSet* /* output_params */,
189                                                Buffer* /* output */, size_t* input_consumed) {
190     if (digest_ == KM_DIGEST_NONE)
191         return StoreData(input, input_consumed);
192 
193     if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
194         return TranslateLastOpenSslError();
195     *input_consumed = input.available_read();
196     return KM_ERROR_OK;
197 }
198 
Finish(const AuthorizationSet &,const Buffer & signature,AuthorizationSet *,Buffer *)199 keymaster_error_t EcdsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
200                                                const Buffer& signature,
201                                                AuthorizationSet* /* output_params */,
202                                                Buffer* /* output */) {
203     if (digest_ == KM_DIGEST_NONE) {
204         UniquePtr<EC_KEY, EC_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
205         if (!ecdsa.get())
206             return TranslateLastOpenSslError();
207 
208         int result =
209             ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
210                          signature.peek_read(), signature.available_read(), ecdsa.get());
211         if (result < 0)
212             return TranslateLastOpenSslError();
213         else if (result == 0)
214             return KM_ERROR_VERIFICATION_FAILED;
215     } else if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(),
216                                       signature.available_read()))
217         return KM_ERROR_VERIFICATION_FAILED;
218 
219     return KM_ERROR_OK;
220 }
221 
222 }  // namespace keymaster
223