Adapt key-manager to work with OpenSSL 1.1 preserving 1.0 compatibility
[platform/core/security/key-manager.git] / src / manager / crypto / sw-backend / obj.cpp
1 /*
2  *  Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file       obj.cpp
18  * @author     BartÅ‚omiej Grzelewski (b.grzelewski@samsung.com)
19  * @version    1.0
20  */
21 #include <memory>
22
23 #include <openssl/bio.h>
24 #include <openssl/evp.h>
25 #include <openssl/x509.h>
26
27 #include <dpl/log/log.h>
28
29 #include <generic-backend/exception.h>
30 #include <sw-backend/obj.h>
31 #include <sw-backend/internals.h>
32
33 namespace CKM {
34 namespace Crypto {
35 namespace SW {
36
37 namespace {
38
39 AlgoType key2algo(DataType type)
40 {
41         switch (static_cast<int>(type)) {
42         case DataType::Type::KEY_RSA_PRIVATE:
43         case DataType::Type::KEY_RSA_PUBLIC:
44                 return AlgoType::RSA_SV;
45
46         case DataType::Type::KEY_DSA_PRIVATE:
47         case DataType::Type::KEY_DSA_PUBLIC:
48                 return AlgoType::DSA_SV;
49
50         case DataType::Type::KEY_ECDSA_PRIVATE:
51         case DataType::Type::KEY_ECDSA_PUBLIC:
52                 return AlgoType::ECDSA_SV;
53
54         default:
55                 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
56         }
57 }
58
59 } // namespace anonymous
60
61 typedef std::unique_ptr<BIO, std::function<void(BIO *)>> BioUniquePtr;
62
63 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
64 {
65         return Internals::symmetricEncrypt(getBinary(), alg, data);
66 }
67 RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
68 {
69         return Internals::symmetricDecrypt(getBinary(), alg, cipher);
70 }
71
72 RawBuffer AKey::sign(
73         const CryptoAlgorithm &alg,
74         const RawBuffer &message)
75 {
76         CryptoAlgorithm algWithType(alg);
77         algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
78         return Internals::sign(getEvpShPtr().get(), algWithType, message);
79 }
80
81 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
82                                  const RawBuffer &sign)
83 {
84         CryptoAlgorithm algWithType(alg);
85         EVP_PKEY *evp = getEvpShPtr().get();
86         AlgoType type;
87
88         // setup algorithm type basing on evp key type if it doesn't exist
89         if (!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
90                 int subType = EVP_PKEY_type(EVP_PKEY_id(evp));
91
92                 switch (subType) {
93                 case EVP_PKEY_RSA:
94                         type = AlgoType::RSA_SV;
95                         break;
96
97                 case EVP_PKEY_DSA:
98                         type = AlgoType::DSA_SV;
99                         break;
100
101                 case EVP_PKEY_EC:
102                         type = AlgoType::ECDSA_SV;
103                         break;
104
105                 default:
106                         ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
107                 }
108
109                 algWithType.setParam(ParamName::ALGO_TYPE, type);
110         }
111
112         return Internals::verify(evp, algWithType, message, sign);
113 }
114
115 RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
116 {
117         return Internals::asymmetricEncrypt(getEvpShPtr(), alg, data);
118 }
119
120 RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
121 {
122         return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
123 }
124
125 EvpShPtr AKey::getEvpShPtr()
126 {
127         if (m_evp)
128                 return m_evp;
129
130         EVP_PKEY *pkey = NULL;
131         BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
132
133         LogDebug("Start to parse key:");
134
135         if (!pkey) {
136                 (void)BIO_reset(bio.get());
137                 BIO_write(bio.get(), m_raw.data(), m_raw.size());
138                 pkey = d2i_PrivateKey_bio(bio.get(), NULL);
139                 LogDebug("Trying d2i_PrivateKey_bio Status: " << (void *)pkey);
140         }
141
142         if (!pkey) {
143                 (void)BIO_reset(bio.get());
144                 BIO_write(bio.get(), m_raw.data(), m_raw.size());
145                 pkey = d2i_PUBKEY_bio(bio.get(), NULL);
146                 LogDebug("Trying d2i_PUBKEY_bio Status: " << (void *)pkey);
147         }
148
149         if (!pkey)
150                 ThrowErr(Exc::Crypto::InternalError, "Failed to parse key");
151
152         m_evp.reset(pkey, EVP_PKEY_free);
153         return m_evp;
154 }
155
156 EvpShPtr Cert::getEvpShPtr()
157 {
158         if (m_evp)
159                 return m_evp;
160
161         int size = static_cast<int>(m_raw.size());
162         const unsigned char *ptr = reinterpret_cast<const unsigned char *>
163                                                            (m_raw.data());
164
165         X509 *x509 = d2i_X509(NULL, &ptr, size);
166
167         if (!x509)
168                 ThrowErr(Exc::Crypto::InternalError, "Failed to parse certificate.");
169
170         m_evp.reset(X509_get_pubkey(x509), EVP_PKEY_free);
171         X509_free(x509);
172         return m_evp;
173 }
174
175 } // namespace SW
176 } // namespace Crypto
177 } // namespace CKM