blob: c7521c787da84d1b40998482f12060ad98b8e16d [file] [log] [blame]
Shawn Willdenc3864dd2014-08-18 15:20:01 -06001/*
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 <openssl/ecdsa.h>
18
Thai Duongf862a762015-03-18 14:10:56 -070019#include "ec_key.h"
Shawn Willdenc3864dd2014-08-18 15:20:01 -060020#include "ecdsa_operation.h"
Shawn Willden567a4a02014-12-31 12:14:46 -070021#include "openssl_err.h"
Shawn Willdenc3864dd2014-08-18 15:20:01 -060022#include "openssl_utils.h"
23
24namespace keymaster {
25
Shawn Willden84b8da52015-03-11 07:21:32 -060026static const keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE};
27
Shawn Willden13e29e02015-05-08 11:02:46 -060028class EcdsaOperationFactory : public OperationFactory {
29 private:
30 KeyType registry_key() const override { return KeyType(KM_ALGORITHM_EC, purpose()); }
31 Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
32 keymaster_error_t* error) override;
33 const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;
Shawn Willden63ac0432014-12-29 14:07:08 -070034
Shawn Willden13e29e02015-05-08 11:02:46 -060035 virtual keymaster_purpose_t purpose() const = 0;
36 virtual Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) = 0;
37};
Shawn Willden63ac0432014-12-29 14:07:08 -070038
Shawn Willden13e29e02015-05-08 11:02:46 -060039Operation* EcdsaOperationFactory::CreateOperation(const Key& key,
Shawn Willden226746b2015-05-08 11:36:56 -060040 const AuthorizationSet& begin_params,
Shawn Willden13e29e02015-05-08 11:02:46 -060041 keymaster_error_t* error) {
42 const EcKey* ecdsa_key = static_cast<const EcKey*>(&key);
43 if (!ecdsa_key) {
44 *error = KM_ERROR_UNKNOWN_ERROR;
45 return nullptr;
Shawn Willden63ac0432014-12-29 14:07:08 -070046 }
Shawn Willden84b8da52015-03-11 07:21:32 -060047
Shawn Willden226746b2015-05-08 11:36:56 -060048 *error = KM_ERROR_UNSUPPORTED_DIGEST;
Shawn Willden13e29e02015-05-08 11:02:46 -060049 keymaster_digest_t digest;
Shawn Willden226746b2015-05-08 11:36:56 -060050 if (!begin_params.GetTagValue(TAG_DIGEST, &digest)) {
51 LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
52 return nullptr;
53 } else if (!supported(digest)) {
54 LOG_E("Digest %d not supported", digest);
55 return nullptr;
56 } else if (!ecdsa_key->authorizations().Contains(TAG_DIGEST, digest) &&
57 !ecdsa_key->authorizations().Contains(TAG_DIGEST_OLD, digest)) {
58 LOG_E("Digest %d was specified, but not authorized by key", digest);
59 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
Shawn Willden13e29e02015-05-08 11:02:46 -060060 return NULL;
61 }
Shawn Willden226746b2015-05-08 11:36:56 -060062 *error = KM_ERROR_OK;
63
Shawn Willden13e29e02015-05-08 11:02:46 -060064 Operation* op = InstantiateOperation(digest, ecdsa_key->key());
65 if (!op)
66 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
67 return op;
68}
69
70const keymaster_digest_t* EcdsaOperationFactory::SupportedDigests(size_t* digest_count) const {
71 *digest_count = array_length(supported_digests);
72 return supported_digests;
73}
74
75class EcdsaSignOperationFactory : public EcdsaOperationFactory {
76 private:
77 keymaster_purpose_t purpose() const override { return KM_PURPOSE_SIGN; }
78 Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) {
79 return new EcdsaSignOperation(purpose(), digest, key);
Shawn Willden84b8da52015-03-11 07:21:32 -060080 }
Shawn Willden63ac0432014-12-29 14:07:08 -070081};
Shawn Willden13e29e02015-05-08 11:02:46 -060082
Shawn Willden63ac0432014-12-29 14:07:08 -070083static OperationFactoryRegistry::Registration<EcdsaSignOperationFactory> sign_registration;
84
Shawn Willden13e29e02015-05-08 11:02:46 -060085class EcdsaVerifyOperationFactory : public EcdsaOperationFactory {
Shawn Willden63ac0432014-12-29 14:07:08 -070086 public:
Shawn Willden13e29e02015-05-08 11:02:46 -060087 keymaster_purpose_t purpose() const override { return KM_PURPOSE_VERIFY; }
88 Operation* InstantiateOperation(keymaster_digest_t digest, EC_KEY* key) {
89 return new EcdsaVerifyOperation(KM_PURPOSE_VERIFY, digest, key);
Shawn Willden63ac0432014-12-29 14:07:08 -070090 }
91};
92static OperationFactoryRegistry::Registration<EcdsaVerifyOperationFactory> verify_registration;
93
Shawn Willden5ac2f8f2014-08-18 15:33:10 -060094EcdsaOperation::~EcdsaOperation() {
95 if (ecdsa_key_ != NULL)
96 EC_KEY_free(ecdsa_key_);
97}
98
Shawn Willden6bfbff02015-02-06 19:48:24 -070099keymaster_error_t EcdsaOperation::Update(const AuthorizationSet& /* additional_params */,
100 const Buffer& input, Buffer* /* output */,
Shawn Willdenb7361132014-12-08 08:15:14 -0700101 size_t* input_consumed) {
102 assert(input_consumed);
Shawn Willden5ac2f8f2014-08-18 15:33:10 -0600103 switch (purpose()) {
104 default:
105 return KM_ERROR_UNIMPLEMENTED;
106 case KM_PURPOSE_SIGN:
107 case KM_PURPOSE_VERIFY:
Shawn Willdenb7361132014-12-08 08:15:14 -0700108 return StoreData(input, input_consumed);
Shawn Willden5ac2f8f2014-08-18 15:33:10 -0600109 }
110}
111
Shawn Willdenb7361132014-12-08 08:15:14 -0700112keymaster_error_t EcdsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
Shawn Willdenb3407022014-08-27 06:30:52 -0600113 if (!data_.reserve(data_.available_read() + input.available_read()) ||
Shawn Willdend67afae2014-08-19 12:36:27 -0600114 !data_.write(input.peek_read(), input.available_read()))
115 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdenb7361132014-12-08 08:15:14 -0700116 *input_consumed = input.available_read();
Shawn Willden5ac2f8f2014-08-18 15:33:10 -0600117 return KM_ERROR_OK;
118}
119
Shawn Willden6bfbff02015-02-06 19:48:24 -0700120keymaster_error_t EcdsaSignOperation::Finish(const AuthorizationSet& /* additional_params */,
121 const Buffer& /* signature */, Buffer* output) {
Shawn Willdenb7361132014-12-08 08:15:14 -0700122 assert(output);
Shawn Willdend67afae2014-08-19 12:36:27 -0600123 output->Reinitialize(ECDSA_size(ecdsa_key_));
124 unsigned int siglen;
125 if (!ECDSA_sign(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
126 output->peek_write(), &siglen, ecdsa_key_))
Shawn Willden567a4a02014-12-31 12:14:46 -0700127 return TranslateLastOpenSslError();
Shawn Willdend67afae2014-08-19 12:36:27 -0600128 output->advance_write(siglen);
129 return KM_ERROR_OK;
130}
131
Shawn Willden6bfbff02015-02-06 19:48:24 -0700132keymaster_error_t EcdsaVerifyOperation::Finish(const AuthorizationSet& /* additional_params */,
133 const Buffer& signature, Buffer* /* output */) {
Shawn Willdend67afae2014-08-19 12:36:27 -0600134 int result = ECDSA_verify(0 /* type -- ignored */, data_.peek_read(), data_.available_read(),
135 signature.peek_read(), signature.available_read(), ecdsa_key_);
136 if (result < 0)
Shawn Willden567a4a02014-12-31 12:14:46 -0700137 return TranslateLastOpenSslError();
Shawn Willdend67afae2014-08-19 12:36:27 -0600138 else if (result == 0)
139 return KM_ERROR_VERIFICATION_FAILED;
140 else
Shawn Willden5ac2f8f2014-08-18 15:33:10 -0600141 return KM_ERROR_OK;
Shawn Willden5ac2f8f2014-08-18 15:33:10 -0600142}
143
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600144} // namespace keymaster