blob: 064cd7ee19d0eab5a22b35116ca105b30915787a [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 Willdenf268d742014-08-19 15:36:26 -060017#include <openssl/x509.h>
18
Shawn Willdenb9d584d2015-01-22 16:35:00 -070019#include <hardware/keymaster_defs.h>
Shawn Willden98d9b922014-08-26 08:14:10 -060020
Shawn Willdend67afae2014-08-19 12:36:27 -060021#include "asymmetric_key.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060022#include "openssl_utils.h"
Shawn Willden72014ad2014-09-17 13:04:10 -060023#include "unencrypted_key_blob.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060024
25namespace keymaster {
26
Shawn Willden72014ad2014-09-17 13:04:10 -060027keymaster_error_t AsymmetricKey::LoadKey(const UnencryptedKeyBlob& blob) {
Shawn Willdend67afae2014-08-19 12:36:27 -060028 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> evp_key(EVP_PKEY_new());
29 if (evp_key.get() == NULL)
30 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
31
32 EVP_PKEY* tmp_pkey = evp_key.get();
Shawn Willden72014ad2014-09-17 13:04:10 -060033 const uint8_t* key_material = blob.unencrypted_key_material();
Shawn Willdend67afae2014-08-19 12:36:27 -060034 if (d2i_PrivateKey(evp_key_type(), &tmp_pkey, &key_material, blob.key_material_length()) ==
35 NULL) {
36 return KM_ERROR_INVALID_KEY_BLOB;
37 }
38 if (!EvpToInternal(evp_key.get()))
39 return KM_ERROR_UNKNOWN_ERROR;
40
41 return KM_ERROR_OK;
42}
43
44keymaster_error_t AsymmetricKey::key_material(UniquePtr<uint8_t[]>* material, size_t* size) const {
45 if (material == NULL || size == NULL)
46 return KM_ERROR_OUTPUT_PARAMETER_NULL;
47
48 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
49 if (pkey.get() == NULL)
50 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
51
52 if (!InternalToEvp(pkey.get()))
53 return KM_ERROR_UNKNOWN_ERROR;
54
55 *size = i2d_PrivateKey(pkey.get(), NULL /* key_data*/);
56 if (*size <= 0)
57 return KM_ERROR_UNKNOWN_ERROR;
58
59 material->reset(new uint8_t[*size]);
60 uint8_t* tmp = material->get();
61 i2d_PrivateKey(pkey.get(), &tmp);
62
63 return KM_ERROR_OK;
64}
65
Shawn Willdenf268d742014-08-19 15:36:26 -060066keymaster_error_t AsymmetricKey::formatted_key_material(keymaster_key_format_t format,
67 UniquePtr<uint8_t[]>* material,
Shawn Willdend67afae2014-08-19 12:36:27 -060068 size_t* size) const {
Shawn Willdenf268d742014-08-19 15:36:26 -060069 if (format != KM_KEY_FORMAT_X509)
70 return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
71
Shawn Willdend67afae2014-08-19 12:36:27 -060072 if (material == NULL || size == NULL)
73 return KM_ERROR_OUTPUT_PARAMETER_NULL;
74
Shawn Willdenf268d742014-08-19 15:36:26 -060075 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(EVP_PKEY_new());
76 if (!InternalToEvp(pkey.get()))
77 return KM_ERROR_UNKNOWN_ERROR;
78
79 int key_data_length = i2d_PUBKEY(pkey.get(), NULL);
80 if (key_data_length <= 0)
81 return KM_ERROR_UNKNOWN_ERROR;
82
83 material->reset(new uint8_t[key_data_length]);
84 if (material->get() == NULL)
85 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
86
87 uint8_t* tmp = material->get();
88 if (i2d_PUBKEY(pkey.get(), &tmp) != key_data_length) {
89 material->reset();
90 return KM_ERROR_UNKNOWN_ERROR;
91 }
92
93 *size = key_data_length;
94 return KM_ERROR_OK;
Shawn Willdend67afae2014-08-19 12:36:27 -060095}
96
Shawn Willdend67afae2014-08-19 12:36:27 -060097} // namespace keymaster