Add support for binary data to GStore
[platform/core/security/key-manager.git] / src / manager / crypto / sw-backend / obj.cpp
1 /*
2  *  Copyright (c) 2000 - 2015 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 #define EVP_SUCCESS 1   // DO NOTCHANGE THIS VALUE
34 #define EVP_FAIL    0   // DO NOTCHANGE THIS VALUE
35
36 namespace CKM {
37 namespace Crypto {
38 namespace SW {
39
40 namespace {
41
42 AlgoType key2algo(DataType type) {
43     switch(static_cast<int>(type)) {
44     case DataType::Type::KEY_RSA_PRIVATE:
45     case DataType::Type::KEY_RSA_PUBLIC:
46         return AlgoType::RSA_SV;
47     case DataType::Type::KEY_DSA_PRIVATE:
48     case DataType::Type::KEY_DSA_PUBLIC:
49         return AlgoType::DSA_SV;
50     case DataType::Type::KEY_ECDSA_PRIVATE:
51     case DataType::Type::KEY_ECDSA_PUBLIC:
52         return AlgoType::ECDSA_SV;
53     default:
54         ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
55     }
56 }
57
58 } // namespace anonymous
59
60 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
61
62 RawBuffer BData::getBinary() const {
63     return m_raw;
64 }
65
66 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
67 {
68     return Internals::symmetricEncrypt(getBinary(), alg, data);
69 }
70 RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
71 {
72     return Internals::symmetricDecrypt(getBinary(), alg, cipher);
73 }
74
75 RawBuffer AKey::sign(
76     const CryptoAlgorithm &alg,
77     const RawBuffer &message)
78 {
79     CryptoAlgorithm algWithType(alg);
80     algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
81     return Internals::sign(getEvpShPtr().get(), algWithType, message);
82 }
83
84 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message, const RawBuffer &sign) {
85     CryptoAlgorithm algWithType(alg);
86     EVP_PKEY* evp = getEvpShPtr().get();
87     AlgoType type;
88
89     // setup algorithm type basing on evp key type if it doesn't exist
90     if(!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
91         int subType = EVP_PKEY_type(evp->type);
92         switch(subType) {
93         case EVP_PKEY_RSA:
94             type = AlgoType::RSA_SV; break;
95         case EVP_PKEY_DSA:
96             type = AlgoType::DSA_SV; break;
97         case EVP_PKEY_EC:
98             type = AlgoType::ECDSA_SV; break;
99         default:
100             ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
101         }
102         algWithType.setParam(ParamName::ALGO_TYPE, type);
103     }
104     return Internals::verify(evp, algWithType, message, sign);
105 }
106
107 RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
108 {
109     return Internals::asymmetricEncrypt(getEvpShPtr(), alg, data);
110 }
111
112 RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
113 {
114     return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
115 }
116
117 EvpShPtr AKey::getEvpShPtr() {
118     if (m_evp)
119         return m_evp;
120
121     EVP_PKEY *pkey = NULL;
122     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
123
124     LogDebug("Start to parse key:");
125
126     if (!pkey) {
127         (void)BIO_reset(bio.get());
128         BIO_write(bio.get(), m_raw.data(), m_raw.size());
129         pkey = d2i_PrivateKey_bio(bio.get(), NULL);
130         LogDebug("Trying d2i_PrivateKey_bio Status: " << (void*)pkey);
131     }
132
133     if (!pkey) {
134         (void)BIO_reset(bio.get());
135         BIO_write(bio.get(), m_raw.data(), m_raw.size());
136         pkey = d2i_PUBKEY_bio(bio.get(), NULL);
137         LogDebug("Trying d2i_PUBKEY_bio Status: " << (void*)pkey);
138     }
139
140     if (!pkey) {
141         ThrowErr(Exc::Crypto::InternalError, "Failed to parse key");
142     }
143
144     m_evp.reset(pkey, EVP_PKEY_free);
145     return m_evp;
146 }
147
148 EvpShPtr Cert::getEvpShPtr() {
149     if (m_evp)
150         return m_evp;
151
152     int size = static_cast<int>(m_raw.size());
153     const unsigned char *ptr = reinterpret_cast<const unsigned char *>(m_raw.data());
154
155     X509 *x509 = d2i_X509(NULL, &ptr, size);
156
157     if (!x509) {
158         ThrowErr(Exc::Crypto::InternalError, "Failed to parse certificate.");
159     }
160
161     m_evp.reset(X509_get_pubkey(x509), EVP_PKEY_free);
162     X509_free(x509);
163     return m_evp;
164 }
165
166 } // namespace SW
167 } // namespace Crypto
168 } // namespace CKM
169