1c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden/*
2c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * Copyright 2014 The Android Open Source Project
3c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden *
4c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
5c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * you may not use this file except in compliance with the License.
6c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * You may obtain a copy of the License at
7c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden *
8c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
9c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden *
10c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * Unless required by applicable law or agreed to in writing, software
11c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
12c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * See the License for the specific language governing permissions and
14c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden * limitations under the License.
15c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden */
16c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden
17efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden#include "ecdsa_operation.h"
18efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
19c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden#include <openssl/ecdsa.h>
20c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden
21f862a764e4d20495d484664de852e4d6de26f08bThai Duong#include "ec_key.h"
22567a4a04f43d35b785d50508e6459b01f2ab4d14Shawn Willden#include "openssl_err.h"
23c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden#include "openssl_utils.h"
24c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden
25c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willdennamespace keymaster {
26c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden
270d061c80d06f94291568e725f9eb649962a80352Shawn Willdenstatic const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE,      KM_DIGEST_SHA1,
280d061c80d06f94291568e725f9eb649962a80352Shawn Willden                                                       KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256,
290d061c80d06f94291568e725f9eb649962a80352Shawn Willden                                                       KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
3084b8da52a242c42d9a6a8cc8f128fb4c8baa6f8fShawn Willden
3113e29e0e2a3377ec50b5168b4384d3912559bb63Shawn WilldenOperation* EcdsaOperationFactory::CreateOperation(const Key& key,
32226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden                                                  const AuthorizationSet& begin_params,
3313e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden                                                  keymaster_error_t* error) {
3413e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    const EcKey* ecdsa_key = static_cast<const EcKey*>(&key);
3513e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    if (!ecdsa_key) {
3613e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden        *error = KM_ERROR_UNKNOWN_ERROR;
3713e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden        return nullptr;
3813e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    }
3984b8da52a242c42d9a6a8cc8f128fb4c8baa6f8fShawn Willden
40efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
41efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (!ecdsa_key->InternalToEvp(pkey.get())) {
42efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        *error = KM_ERROR_UNKNOWN_ERROR;
43226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden        return nullptr;
4463ac043f81f8e2a15bbadcb6628b92096295ab6aShawn Willden    }
45226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden
46efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    keymaster_digest_t digest;
47efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (!GetAndValidateDigest(begin_params, key, &digest, error))
48efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return nullptr;
49efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
50efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    *error = KM_ERROR_OK;
51efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    Operation* op = InstantiateOperation(digest, pkey.release());
5213e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    if (!op)
5313e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden        *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
5413e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    return op;
5513e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden}
5684b8da52a242c42d9a6a8cc8f128fb4c8baa6f8fShawn Willden
5713e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willdenconst keymaster_digest_t* EcdsaOperationFactory::SupportedDigests(size_t* digest_count) const {
5813e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    *digest_count = array_length(supported_digests);
5913e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden    return supported_digests;
6013e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden}
6113e29e0e2a3377ec50b5168b4384d3912559bb63Shawn Willden
625ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn WilldenEcdsaOperation::~EcdsaOperation() {
635ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden    if (ecdsa_key_ != NULL)
64efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        EVP_PKEY_free(ecdsa_key_);
65efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    EVP_MD_CTX_cleanup(&digest_ctx_);
665ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden}
675ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden
68efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willdenkeymaster_error_t EcdsaOperation::InitDigest() {
69efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    switch (digest_) {
70efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_NONE:
71efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
72efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_MD5:
730d061c80d06f94291568e725f9eb649962a80352Shawn Willden        return KM_ERROR_UNSUPPORTED_DIGEST;
74efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_SHA1:
75efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        digest_algorithm_ = EVP_sha1();
76efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
77efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_SHA_2_224:
78efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        digest_algorithm_ = EVP_sha224();
79efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
80efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_SHA_2_256:
81efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        digest_algorithm_ = EVP_sha256();
82efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
83efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_SHA_2_384:
84efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        digest_algorithm_ = EVP_sha384();
85efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
86efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    case KM_DIGEST_SHA_2_512:
87efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        digest_algorithm_ = EVP_sha512();
88efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
895ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden    default:
90efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_UNSUPPORTED_DIGEST;
915ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden    }
925ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden}
935ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden
94d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willdeninline size_t min(size_t a, size_t b) {
95d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden    return (a < b) ? a : b;
96d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden}
97d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden
98b7361134bff4d3d7ef1d5a3c60e50c9952dc2b56Shawn Willdenkeymaster_error_t EcdsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
992101e9e8215cce6da36d8d7382486737b68e8c93Shawn Willden    if (!data_.reserve((EVP_PKEY_bits(ecdsa_key_) + 7) / 8))
100d67afae61f822463120c36fea846362450dd7d71Shawn Willden        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
101d530305019e1ccc1e30a4f8edeb88db3d126e235Shawn Willden
102d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden    if (!data_.write(input.peek_read(), min(data_.available_write(), input.available_read())))
103d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
104d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden
105b7361134bff4d3d7ef1d5a3c60e50c9952dc2b56Shawn Willden    *input_consumed = input.available_read();
1065ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden    return KM_ERROR_OK;
1075ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden}
1085ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden
109efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willdenkeymaster_error_t EcdsaSignOperation::Begin(const AuthorizationSet& /* input_params */,
110efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                                            AuthorizationSet* /* output_params */) {
111efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    keymaster_error_t error = InitDigest();
112efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (error != KM_ERROR_OK)
113efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return error;
114efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
115efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE)
116efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
117efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
118efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    EVP_PKEY_CTX* pkey_ctx;
119efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
120efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                           ecdsa_key_) != 1)
121efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return TranslateLastOpenSslError();
122efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    return KM_ERROR_OK;
123efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden}
124efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
125efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willdenkeymaster_error_t EcdsaSignOperation::Update(const AuthorizationSet& /* additional_params */,
126ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                             const Buffer& input,
127ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                             AuthorizationSet* /* output_params */,
128ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                             Buffer* /* output */, size_t* input_consumed) {
129efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE)
130efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return StoreData(input, input_consumed);
131efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
132efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
133efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return TranslateLastOpenSslError();
134efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    *input_consumed = input.available_read();
135efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    return KM_ERROR_OK;
136efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden}
137efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
138cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willdenkeymaster_error_t EcdsaSignOperation::Finish(const AuthorizationSet& additional_params,
139cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden                                             const Buffer& input, const Buffer& /* signature */,
140ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                             AuthorizationSet* /* output_params */,
141ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                             Buffer* output) {
142efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (!output)
143efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OUTPUT_PARAMETER_NULL;
144efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
145cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    keymaster_error_t error = UpdateForFinish(additional_params, input);
146cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    if (error != KM_ERROR_OK)
147cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden        return error;
148cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden
149efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    size_t siglen;
150efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE) {
151fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong        UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
152efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (!ecdsa.get())
153efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
154efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
155efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        output->Reinitialize(ECDSA_size(ecdsa.get()));
156efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        unsigned int siglen_tmp;
157efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
158efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                        output->peek_write(), &siglen_tmp, ecdsa.get()))
159efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
160efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        siglen = siglen_tmp;
161efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    } else {
162efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
163efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
164efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (!output->Reinitialize(siglen))
165efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
166efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
167efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
168efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    }
1690f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!output->advance_write(siglen))
1700f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
171d67afae61f822463120c36fea846362450dd7d71Shawn Willden    return KM_ERROR_OK;
172d67afae61f822463120c36fea846362450dd7d71Shawn Willden}
173d67afae61f822463120c36fea846362450dd7d71Shawn Willden
174efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willdenkeymaster_error_t EcdsaVerifyOperation::Begin(const AuthorizationSet& /* input_params */,
175efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                                              AuthorizationSet* /* output_params */) {
176efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    keymaster_error_t error = InitDigest();
177efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (error != KM_ERROR_OK)
178efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return error;
179efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
180efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE)
181efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return KM_ERROR_OK;
182efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
183efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    EVP_PKEY_CTX* pkey_ctx;
184efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
185efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                             ecdsa_key_) != 1)
186efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return TranslateLastOpenSslError();
187efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    return KM_ERROR_OK;
188efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden}
189efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
190efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willdenkeymaster_error_t EcdsaVerifyOperation::Update(const AuthorizationSet& /* additional_params */,
191ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                               const Buffer& input,
192ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                               AuthorizationSet* /* output_params */,
193ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                               Buffer* /* output */, size_t* input_consumed) {
194efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE)
195efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return StoreData(input, input_consumed);
196efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
197efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
198efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        return TranslateLastOpenSslError();
199efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    *input_consumed = input.available_read();
200efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    return KM_ERROR_OK;
201efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden}
202efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
203cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willdenkeymaster_error_t EcdsaVerifyOperation::Finish(const AuthorizationSet& additional_params,
204cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden                                               const Buffer& input, const Buffer& signature,
205ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                               AuthorizationSet* /* output_params */,
206ded8e7d0ad241fc0a930dbebbd9f2e2bf4e929a2Shawn Willden                                               Buffer* /* output */) {
207cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    keymaster_error_t error = UpdateForFinish(additional_params, input);
208cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    if (error != KM_ERROR_OK)
209cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden        return error;
210cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden
211efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    if (digest_ == KM_DIGEST_NONE) {
212fabacaf3e6019804cc8a98a2b8296be1d0125519Thai Duong        UniquePtr<EC_KEY, EC_KEY_Delete> ecdsa(EVP_PKEY_get1_EC_KEY(ecdsa_key_));
213efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (!ecdsa.get())
214efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
215efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
216efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        int result =
217efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
218efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                         signature.peek_read(), signature.available_read(), ecdsa.get());
219efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        if (result < 0)
220efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return TranslateLastOpenSslError();
221efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden        else if (result == 0)
222efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden            return KM_ERROR_VERIFICATION_FAILED;
223efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    } else if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(),
224efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden                                      signature.available_read()))
225d67afae61f822463120c36fea846362450dd7d71Shawn Willden        return KM_ERROR_VERIFICATION_FAILED;
226efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden
227efbd7e432228cf1e65abb6d85dffa38ec03f7a26Shawn Willden    return KM_ERROR_OK;
2285ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden}
2295ac2f8ff7c82d2b5c2dd17273ce58c7806df0ec2Shawn Willden
230c3864dde9ffa9a52bb60802664e1cab1de5c0287Shawn Willden}  // namespace keymaster
231