Remove win32 support in SoftHSMv2
[aaf/sshsm.git] / SoftHSMv2 / src / lib / crypto / BotanGOSTPrivateKey.cpp
1 /*
2  * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 /*****************************************************************************
28  BotanGOSTPrivateKey.cpp
29
30  Botan GOST R 34.10-2001 private key class
31  *****************************************************************************/
32
33 #include "config.h"
34 #ifdef WITH_GOST
35 #include "log.h"
36 #include "BotanGOSTPrivateKey.h"
37 #include "BotanCryptoFactory.h"
38 #include "BotanRNG.h"
39 #include "BotanUtil.h"
40 #include <string.h>
41 #include <botan/pkcs8.h>
42 #include <botan/ber_dec.h>
43 #include <botan/der_enc.h>
44 #include <botan/asn1_oid.h>
45 #include <botan/oids.h>
46 #include <botan/version.h>
47
48 // Constructors
49 BotanGOSTPrivateKey::BotanGOSTPrivateKey()
50 {
51         eckey = NULL;
52 }
53
54 BotanGOSTPrivateKey::BotanGOSTPrivateKey(const Botan::GOST_3410_PrivateKey* inECKEY)
55 {
56         BotanGOSTPrivateKey();
57
58         setFromBotan(inECKEY);
59 }
60
61 // Destructor
62 BotanGOSTPrivateKey::~BotanGOSTPrivateKey()
63 {
64         delete eckey;
65 }
66
67 // The type
68 /*static*/ const char* BotanGOSTPrivateKey::type = "Botan GOST Private Key";
69
70 // Get the base point order length
71 unsigned long BotanGOSTPrivateKey::getOrderLength() const
72 {
73         try
74         {
75                 Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
76                 return group.get_order().bytes();
77         }
78         catch (...)
79         {
80                 ERROR_MSG("Can't get EC group for order length");
81
82                 return 0;
83         }
84 }
85
86 // Get the output length
87 unsigned long BotanGOSTPrivateKey::getOutputLength() const
88 {
89         return getOrderLength() * 2;
90 }
91
92 // Set from Botan representation
93 void BotanGOSTPrivateKey::setFromBotan(const Botan::GOST_3410_PrivateKey* inECKEY)
94 {
95         ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
96         setEC(inEC);
97         ByteString inD = BotanUtil::bigInt2ByteStringPrefix(inECKEY->private_value(), 32);
98         setD(inD);
99 }
100
101 // Check if the key is of the given type
102 bool BotanGOSTPrivateKey::isOfType(const char* inType)
103 {
104         return !strcmp(type, inType);
105 }
106
107 // Setters for the GOST private key components
108 void BotanGOSTPrivateKey::setD(const ByteString& inD)
109 {
110         GOSTPrivateKey::setD(inD);
111
112         if (eckey)
113         {
114                 delete eckey;
115                 eckey = NULL;
116         }
117 }
118
119
120 // Setters for the GOST public key components
121 void BotanGOSTPrivateKey::setEC(const ByteString& inEC)
122 {
123         GOSTPrivateKey::setEC(inEC);
124
125         if (eckey)
126         {
127                 delete eckey;
128                 eckey = NULL;
129         }
130 }
131
132 // Serialisation
133 ByteString BotanGOSTPrivateKey::serialise() const
134 {
135         return ec.serialise() +
136                d.serialise();
137 }
138
139 bool BotanGOSTPrivateKey::deserialise(ByteString& serialised)
140 {
141         ByteString dEC = ByteString::chainDeserialise(serialised);
142         ByteString dD = ByteString::chainDeserialise(serialised);
143
144         if ((dEC.size() == 0) ||
145             (dD.size() == 0))
146         {
147                 return false;
148         }
149
150         setEC(dEC);
151         setD(dD);
152
153         return true;
154 }
155
156 // Encode into PKCS#8 DER
157 ByteString BotanGOSTPrivateKey::PKCS8Encode()
158 {
159         ByteString der;
160         createBotanKey();
161         if (eckey == NULL) return der;
162         // Force EC_DOMPAR_ENC_OID
163         const size_t PKCS8_VERSION = 0;
164 #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
165         const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
166         const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
167         const Botan::secure_vector<Botan::byte> ber =
168                 Botan::DER_Encoder()
169                 .start_cons(Botan::SEQUENCE)
170                     .encode(PKCS8_VERSION)
171                     .encode(alg_id)
172                     .encode(eckey->private_key_bits(), Botan::OCTET_STRING)
173                 .end_cons()
174             .get_contents();
175 #elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
176         const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
177         const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
178         const Botan::secure_vector<Botan::byte> ber =
179                 Botan::DER_Encoder()
180                 .start_cons(Botan::SEQUENCE)
181                     .encode(PKCS8_VERSION)
182                     .encode(alg_id)
183                     .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
184                 .end_cons()
185             .get_contents();
186 #else
187         const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
188         const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
189         const Botan::SecureVector<Botan::byte> ber =
190                 Botan::DER_Encoder()
191                 .start_cons(Botan::SEQUENCE)
192                 .encode(PKCS8_VERSION)
193                     .encode(alg_id)
194                     .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
195                 .end_cons()
196             .get_contents();
197 #endif
198         der.resize(ber.size());
199         memcpy(&der[0], &ber[0], ber.size());
200         return der;
201 }
202
203 // Decode from PKCS#8 BER
204 bool BotanGOSTPrivateKey::PKCS8Decode(const ByteString& ber)
205 {
206         Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
207         if (source.end_of_data()) return false;
208 #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
209         Botan::secure_vector<Botan::byte> keydata;
210 #else
211         Botan::SecureVector<Botan::byte> keydata;
212 #endif
213         Botan::AlgorithmIdentifier alg_id;
214         Botan::GOST_3410_PrivateKey* key = NULL;
215         try
216         {
217                 Botan::BER_Decoder(source)
218                 .start_cons(Botan::SEQUENCE)
219                         .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
220                         .decode(alg_id)
221                         .decode(keydata, Botan::OCTET_STRING)
222                         .discard_remaining()
223                 .end_cons();
224                 if (keydata.empty())
225                         throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
226                 if (Botan::OIDS::lookup(alg_id.oid).compare("GOST-34.10"))
227                 {
228                         ERROR_MSG("Decoded private key not GOST-34.10");
229
230                         return false;
231                 }
232                 key = new Botan::GOST_3410_PrivateKey(alg_id, keydata);
233                 if (key == NULL) return false;
234
235                 setFromBotan(key);
236
237                 delete key;
238         }
239         catch (std::exception& e)
240         {
241                 ERROR_MSG("Decode failed on %s", e.what());
242
243                 return false;
244         }
245
246         return true;
247 }
248
249 // Retrieve the Botan representation of the key
250 Botan::GOST_3410_PrivateKey* BotanGOSTPrivateKey::getBotanKey()
251 {
252         if (!eckey)
253         {
254                 createBotanKey();
255         }
256
257         return eckey;
258 }
259
260 // Create the Botan representation of the key
261 void BotanGOSTPrivateKey::createBotanKey()
262 {
263         if (ec.size() != 0 &&
264             d.size() != 0)
265         {
266                 if (eckey)
267                 {
268                         delete eckey;
269                         eckey = NULL;
270                 }
271
272                 try
273                 {
274                         BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
275                         Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
276                         eckey = new Botan::GOST_3410_PrivateKey(*rng->getRNG(),
277                                                         group,
278                                                         BotanUtil::byteString2bigInt(d));
279                 }
280                 catch (...)
281                 {
282                         ERROR_MSG("Could not create the Botan public key");
283                 }
284         }
285 }
286 #endif