2 * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
18 * @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
21 #include <openssl/bio.h>
22 #include <openssl/evp.h>
23 #include <openssl/x509.h>
25 #include <dpl/log/log.h>
28 #include <generic-backend/exception.h>
29 #include <sw-backend/obj.h>
30 #include <sw-backend/store.h>
31 #include <sw-backend/internals.h>
32 #include <ckm/ckm-key.h>
40 AlgoType key2algo(DataType type)
43 case DataType::KEY_RSA_PRIVATE:
44 case DataType::KEY_RSA_PUBLIC:
45 return AlgoType::RSA_SV;
47 case DataType::KEY_DSA_PRIVATE:
48 case DataType::KEY_DSA_PUBLIC:
49 return AlgoType::DSA_SV;
51 case DataType::KEY_ECDSA_PRIVATE:
52 case DataType::KEY_ECDSA_PUBLIC:
53 return AlgoType::ECDSA_SV;
56 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
60 } // namespace anonymous
62 Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &)
64 auto data = Internals::deriveKBKDF(getBinary(), alg);
66 return Token(backendId(), data.type, Store::pack(data.buffer, pass));
69 Token Key::unwrap(const CryptoAlgorithm ¶ms,
70 const Data &wrappedKey,
74 auto decrypted = decrypt(params, wrappedKey.data);
76 if (!wrappedKey.type.isKey()) {
77 ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a key");
80 // validate the decrypted key
81 if (wrappedKey.type.isSKey()) {
82 auto tmp = CKM::Key::createAES(decrypted);
84 ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid AES key");
86 auto tmp = CKM::Key::create(decrypted);
88 ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid asymmetric key");
90 if (wrappedKey.type != DataType(tmp->getType()))
91 ThrowErr(Exc::Crypto::InputParam, "Wrapped key type does not match the required one");
94 return Token(backendId(), wrappedKey.type, Store::pack(decrypted, pass));
97 RawBuffer Key::wrap(const CryptoAlgorithm ¶ms,
98 const Token &keyToWrap,
99 const Password &keyToWrapPass)
101 RawBuffer data = Store::unpack(keyToWrap.data, keyToWrapPass);
102 return encrypt(params, data);
106 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
108 return Internals::symmetricEncrypt(getBinary(), alg, data);
110 RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
112 return Internals::symmetricDecrypt(getBinary(), alg, cipher);
115 RawBuffer AKey::sign(
116 const CryptoAlgorithm &alg,
117 const RawBuffer &message)
119 CryptoAlgorithm algWithType(alg);
120 algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
121 return Internals::sign(getEvpShPtr().get(), algWithType, message);
124 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
125 const RawBuffer &sign)
127 CryptoAlgorithm algWithType(alg);
128 EVP_PKEY *evp = getEvpShPtr().get();
131 // setup algorithm type basing on evp key type if it doesn't exist
132 if (!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
133 int subType = EVP_PKEY_type(EVP_PKEY_id(evp));
137 type = AlgoType::RSA_SV;
141 type = AlgoType::DSA_SV;
145 type = AlgoType::ECDSA_SV;
149 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
152 algWithType.setParam(ParamName::ALGO_TYPE, type);
155 return Internals::verify(evp, algWithType, message, sign);
158 RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
160 return Internals::asymmetricEncrypt(getEvpShPtr(), alg, data);
163 RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
165 return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
168 Token AKey::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer & /* digest */)
170 auto data = Internals::deriveECDH(getEvpShPtr(), alg);
172 return Token(backendId(), data.type, Store::pack(data.buffer, pass));
175 EvpShPtr AKey::getEvpShPtr()
180 EVP_PKEY *pkey = NULL;
181 auto bio = uptr<BIO_free_all>(BIO_new(BIO_s_mem()));
183 LogDebug("Start to parse key:");
186 (void)BIO_reset(bio.get());
187 BIO_write(bio.get(), m_raw.data(), m_raw.size());
188 pkey = d2i_PrivateKey_bio(bio.get(), NULL);
189 LogDebug("Trying d2i_PrivateKey_bio Status: " << (void *)pkey);
193 (void)BIO_reset(bio.get());
194 BIO_write(bio.get(), m_raw.data(), m_raw.size());
195 pkey = d2i_PUBKEY_bio(bio.get(), NULL);
196 LogDebug("Trying d2i_PUBKEY_bio Status: " << (void *)pkey);
200 ThrowErr(Exc::Crypto::InternalError, "Failed to parse key");
202 m_evp.reset(pkey, EVP_PKEY_free);
206 EvpShPtr Cert::getEvpShPtr()
211 int size = static_cast<int>(m_raw.size());
212 const unsigned char *ptr = reinterpret_cast<const unsigned char *>
215 X509 *x509 = d2i_X509(NULL, &ptr, size);
218 ThrowErr(Exc::Crypto::InternalError, "Failed to parse certificate.");
220 m_evp.reset(X509_get_pubkey(x509), EVP_PKEY_free);
225 Token Cert::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &)
227 ThrowErr(Exc::Crypto::OperationNotSupported);
230 Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, const RawBuffer &)
232 ThrowErr(Exc::Crypto::OperationNotSupported);
235 RawBuffer Cert::wrap(const CryptoAlgorithm &, const Token &, const Password &)
237 ThrowErr(Exc::Crypto::OperationNotSupported);
241 } // namespace Crypto