blob: 053c2d554bf366ad556eaae38456bd2cabda1c57 [file] [log] [blame]
Shawn Willdend67afae2014-08-19 12:36:27 -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
Shawn Willden95e13822014-12-15 16:12:16 -070017#include "key.h"
18
Shawn Willden437fbd12014-08-20 11:59:49 -060019#include <openssl/x509.h>
20
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060021#include "ecdsa_key.h"
Shawn Willden437fbd12014-08-20 11:59:49 -060022#include "openssl_utils.h"
Shawn Willden2c8dd3e2014-09-18 15:16:31 -060023#include "rsa_key.h"
Shawn Willden95e13822014-12-15 16:12:16 -070024#include "symmetric_key.h"
Shawn Willden72014ad2014-09-17 13:04:10 -060025#include "unencrypted_key_blob.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060026
Shawn Willdend67afae2014-08-19 12:36:27 -060027namespace keymaster {
28
Shawn Willden437fbd12014-08-20 11:59:49 -060029struct PKCS8_PRIV_KEY_INFO_Delete {
30 void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
31};
32
Shawn Willden2f3be362014-08-25 11:31:39 -060033Key::Key(const KeyBlob& blob, const Logger& logger) : logger_(logger) {
Shawn Willdend67afae2014-08-19 12:36:27 -060034 authorizations_.push_back(blob.unenforced());
35 authorizations_.push_back(blob.enforced());
36}
37
38/* static */
Shawn Willden72014ad2014-09-17 13:04:10 -060039Key* Key::CreateKey(const UnencryptedKeyBlob& blob, const Logger& logger,
40 keymaster_error_t* error) {
Shawn Willdend67afae2014-08-19 12:36:27 -060041 switch (blob.algorithm()) {
42 case KM_ALGORITHM_RSA:
Shawn Willden2f3be362014-08-25 11:31:39 -060043 return new RsaKey(blob, logger, error);
Shawn Willdend67afae2014-08-19 12:36:27 -060044 case KM_ALGORITHM_ECDSA:
Shawn Willden2f3be362014-08-25 11:31:39 -060045 return new EcdsaKey(blob, logger, error);
Shawn Willden907c3012014-12-08 15:51:55 -070046 case KM_ALGORITHM_AES:
Shawn Willden0d560bf2014-12-15 17:44:02 -070047 case KM_ALGORITHM_HMAC:
Shawn Willden95e13822014-12-15 16:12:16 -070048 return SymmetricKey::CreateKey(blob.algorithm(), blob, logger, error);
Shawn Willdend67afae2014-08-19 12:36:27 -060049 default:
50 *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
51 return NULL;
52 }
53}
54
55/* static */
Shawn Willden2f3be362014-08-25 11:31:39 -060056Key* Key::GenerateKey(const AuthorizationSet& key_description, const Logger& logger,
57 keymaster_error_t* error) {
Shawn Willdend67afae2014-08-19 12:36:27 -060058 keymaster_algorithm_t algorithm;
59 if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
60 *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
61 return NULL;
62 }
63
64 switch (algorithm) {
65 case KM_ALGORITHM_RSA:
Shawn Willden2f3be362014-08-25 11:31:39 -060066 return RsaKey::GenerateKey(key_description, logger, error);
Shawn Willdend67afae2014-08-19 12:36:27 -060067 case KM_ALGORITHM_ECDSA:
Shawn Willden2f3be362014-08-25 11:31:39 -060068 return EcdsaKey::GenerateKey(key_description, logger, error);
Shawn Willden19fca882015-01-22 16:35:30 -070069 case KM_ALGORITHM_AES:
Shawn Willden0d560bf2014-12-15 17:44:02 -070070 case KM_ALGORITHM_HMAC:
Shawn Willden95e13822014-12-15 16:12:16 -070071 return SymmetricKey::GenerateKey(algorithm, key_description, logger, error);
Shawn Willdend67afae2014-08-19 12:36:27 -060072 default:
73 *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
74 return NULL;
75 }
76}
77
Shawn Willden437fbd12014-08-20 11:59:49 -060078/* static */
79Key* Key::ImportKey(const AuthorizationSet& key_description, keymaster_key_format_t key_format,
Shawn Willden2f3be362014-08-25 11:31:39 -060080 const uint8_t* key_data, size_t key_data_length, const Logger& logger,
81 keymaster_error_t* error) {
Shawn Willden437fbd12014-08-20 11:59:49 -060082 *error = KM_ERROR_OK;
83
84 if (key_data == NULL || key_data_length <= 0) {
85 *error = KM_ERROR_INVALID_KEY_BLOB;
86 return NULL;
87 }
88
89 if (key_format != KM_KEY_FORMAT_PKCS8) {
90 *error = KM_ERROR_UNSUPPORTED_KEY_FORMAT;
91 return NULL;
92 }
93
94 UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8(
95 d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, key_data_length));
96 if (pkcs8.get() == NULL) {
97 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
98 return NULL;
99 }
100
101 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKCS82PKEY(pkcs8.get()));
102 if (pkey.get() == NULL) {
103 *error = KM_ERROR_INVALID_KEY_BLOB;
104 return NULL;
105 }
106
107 UniquePtr<Key> key;
108 switch (EVP_PKEY_type(pkey->type)) {
109 case EVP_PKEY_RSA:
Shawn Willden2f3be362014-08-25 11:31:39 -0600110 return RsaKey::ImportKey(key_description, pkey.get(), logger, error);
Shawn Willden437fbd12014-08-20 11:59:49 -0600111 case EVP_PKEY_EC:
Shawn Willden81effc62014-08-27 10:08:46 -0600112 return EcdsaKey::ImportKey(key_description, pkey.get(), logger, error);
Shawn Willden437fbd12014-08-20 11:59:49 -0600113 default:
114 *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
115 return NULL;
116 }
117
118 *error = KM_ERROR_UNIMPLEMENTED;
119 return NULL;
120}
121
Shawn Willdend67afae2014-08-19 12:36:27 -0600122} // namespace keymaster