ec_keymaster0_key.cpp revision 0629810b145187575bc26c910dded0d24c64569d
1/*
2 * Copyright 2015 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 "ec_keymaster0_key.h"
18
19#include <memory>
20
21#include <keymaster/android_keymaster_utils.h>
22#include <keymaster/logger.h>
23#include <keymaster/soft_keymaster_context.h>
24
25#include "keymaster0_engine.h"
26#include "openssl_utils.h"
27
28using std::unique_ptr;
29
30namespace keymaster {
31
32EcdsaKeymaster0KeyFactory::EcdsaKeymaster0KeyFactory(const SoftKeymasterContext* context,
33                                                     const Keymaster0Engine* engine)
34    : EcdsaKeyFactory(context), engine_(engine), soft_context_(context) {
35}
36
37keymaster_error_t EcdsaKeymaster0KeyFactory::GenerateKey(const AuthorizationSet& key_description,
38                                                         KeymasterKeyBlob* key_blob,
39                                                         AuthorizationSet* hw_enforced,
40                                                         AuthorizationSet* sw_enforced) const {
41    if (!key_blob || !hw_enforced || !sw_enforced)
42        return KM_ERROR_OUTPUT_PARAMETER_NULL;
43
44    if (!engine_ || !engine_->supports_ec())
45        return super::GenerateKey(key_description, key_blob, hw_enforced, sw_enforced);
46
47    uint32_t key_size;
48    if (!key_description.GetTagValue(TAG_KEY_SIZE, &key_size)) {
49        LOG_E("%s", "No key size specified for EC key generation");
50        return KM_ERROR_UNSUPPORTED_KEY_SIZE;
51    }
52
53    KeymasterKeyBlob key_material;
54    if (!engine_->GenerateEcKey(key_size, &key_material))
55        return KM_ERROR_UNKNOWN_ERROR;
56
57    // These tags are hardware-enforced.  Putting them in the hw_enforced set here will ensure that
58    // context_->CreateKeyBlob doesn't put them in sw_enforced.
59    hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
60    hw_enforced->push_back(TAG_KEY_SIZE, key_size);
61
62    return context_->CreateKeyBlob(key_description, KM_ORIGIN_GENERATED, key_material, key_blob,
63                                   hw_enforced, sw_enforced);
64}
65
66keymaster_error_t EcdsaKeymaster0KeyFactory::ImportKey(
67    const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
68    const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
69    AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
70    if (!output_key_blob || !hw_enforced || !sw_enforced)
71        return KM_ERROR_OUTPUT_PARAMETER_NULL;
72
73    if (!engine_ || !engine_->supports_ec())
74        return super::ImportKey(key_description, input_key_material_format, input_key_material,
75                                output_key_blob, hw_enforced, sw_enforced);
76
77    AuthorizationSet authorizations;
78    uint32_t key_size;
79    keymaster_error_t error = UpdateImportKeyDescription(
80        key_description, input_key_material_format, input_key_material, &authorizations, &key_size);
81    if (error != KM_ERROR_OK)
82        return error;
83
84    KeymasterKeyBlob imported_hw_key;
85    if (!engine_->ImportKey(input_key_material_format, input_key_material, &imported_hw_key))
86        return KM_ERROR_UNKNOWN_ERROR;
87
88    // These tags are hardware-enforced.  Putting them in the hw_enforced set here will ensure that
89    // context_->CreateKeyBlob doesn't put them in sw_enforced.
90    hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
91    hw_enforced->push_back(TAG_KEY_SIZE, key_size);
92
93    return context_->CreateKeyBlob(authorizations, KM_ORIGIN_IMPORTED, imported_hw_key,
94                                   output_key_blob, hw_enforced, sw_enforced);
95}
96
97keymaster_error_t EcdsaKeymaster0KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
98                                                     const AuthorizationSet& hw_enforced,
99                                                     const AuthorizationSet& sw_enforced,
100                                                     UniquePtr<Key>* key) const {
101    if (!key)
102        return KM_ERROR_OUTPUT_PARAMETER_NULL;
103
104    if (sw_enforced.GetTagCount(TAG_ALGORITHM) == 1)
105        return super::LoadKey(key_material, hw_enforced, sw_enforced, key);
106
107    unique_ptr<EC_KEY, EC_Delete> ec_key(engine_->BlobToEcKey(key_material));
108    if (!ec_key)
109        return KM_ERROR_UNKNOWN_ERROR;
110
111    keymaster_error_t error;
112    key->reset(new EcKeymaster0Key(ec_key.release(), hw_enforced, sw_enforced, engine_, &error));
113    if (error != KM_ERROR_OK)
114        return error;
115
116    return KM_ERROR_OK;
117}
118
119EcKeymaster0Key::EcKeymaster0Key(EC_KEY* ec_key, const AuthorizationSet& hw_enforced,
120                                 const AuthorizationSet& sw_enforced,
121                                 const Keymaster0Engine* engine, keymaster_error_t* error)
122    : EcKey(ec_key, hw_enforced, sw_enforced, error), engine_(engine) {
123}
124
125keymaster_error_t EcKeymaster0Key::key_material(UniquePtr<uint8_t[]>* material,
126                                                size_t* size) const {
127    if (!engine_)
128        return super::key_material(material, size);
129
130    const keymaster_key_blob_t* blob = engine_->EcKeyToBlob(key());
131    if (!blob)
132        return KM_ERROR_UNKNOWN_ERROR;
133
134    *size = blob->key_material_size;
135    material->reset(new uint8_t[*size]);
136    if (!material->get())
137        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
138    memcpy(material->get(), blob->key_material, *size);
139    return KM_ERROR_OK;
140}
141
142}  // namespace keymaster
143