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 BotanDSAPrivateKey.cpp
29
30 Botan DSA private key class
31 *****************************************************************************/
32
33 #include "config.h"
34 #include "log.h"
35 #include "BotanDSAPrivateKey.h"
36 #include "BotanCryptoFactory.h"
37 #include "BotanRNG.h"
38 #include "BotanUtil.h"
39 #include <string.h>
40 #include <botan/pkcs8.h>
41 #include <botan/ber_dec.h>
42 #include <botan/der_enc.h>
43 #include <botan/oids.h>
44 #include <botan/version.h>
45
46 // Constructors
BotanDSAPrivateKey()47 BotanDSAPrivateKey::BotanDSAPrivateKey()
48 {
49 dsa = NULL;
50 }
51
BotanDSAPrivateKey(const Botan::DSA_PrivateKey * inDSA)52 BotanDSAPrivateKey::BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA)
53 {
54 dsa = NULL;
55
56 setFromBotan(inDSA);
57 }
58
59 // Destructor
~BotanDSAPrivateKey()60 BotanDSAPrivateKey::~BotanDSAPrivateKey()
61 {
62 delete dsa;
63 }
64
65 // The type
66 /*static*/ const char* BotanDSAPrivateKey::type = "Botan DSA Private Key";
67
68 // Set from Botan representation
setFromBotan(const Botan::DSA_PrivateKey * inDSA)69 void BotanDSAPrivateKey::setFromBotan(const Botan::DSA_PrivateKey* inDSA)
70 {
71 ByteString inP = BotanUtil::bigInt2ByteString(inDSA->group_p());
72 setP(inP);
73 ByteString inQ = BotanUtil::bigInt2ByteString(inDSA->group_q());
74 setQ(inQ);
75 ByteString inG = BotanUtil::bigInt2ByteString(inDSA->group_g());
76 setG(inG);
77 ByteString inX = BotanUtil::bigInt2ByteString(inDSA->get_x());
78 setX(inX);
79 }
80
81 // Check if the key is of the given type
isOfType(const char * inType)82 bool BotanDSAPrivateKey::isOfType(const char* inType)
83 {
84 return !strcmp(type, inType);
85 }
86
87 // Setters for the DSA private key components
setX(const ByteString & inX)88 void BotanDSAPrivateKey::setX(const ByteString& inX)
89 {
90 DSAPrivateKey::setX(inX);
91
92 if (dsa)
93 {
94 delete dsa;
95 dsa = NULL;
96 }
97 }
98
99
100 // Setters for the DSA domain parameters
setP(const ByteString & inP)101 void BotanDSAPrivateKey::setP(const ByteString& inP)
102 {
103 DSAPrivateKey::setP(inP);
104
105 if (dsa)
106 {
107 delete dsa;
108 dsa = NULL;
109 }
110 }
111
setQ(const ByteString & inQ)112 void BotanDSAPrivateKey::setQ(const ByteString& inQ)
113 {
114 DSAPrivateKey::setQ(inQ);
115
116 if (dsa)
117 {
118 delete dsa;
119 dsa = NULL;
120 }
121 }
122
setG(const ByteString & inG)123 void BotanDSAPrivateKey::setG(const ByteString& inG)
124 {
125 DSAPrivateKey::setG(inG);
126
127 if (dsa)
128 {
129 delete dsa;
130 dsa = NULL;
131 }
132 }
133
134 // Encode into PKCS#8 DER
PKCS8Encode()135 ByteString BotanDSAPrivateKey::PKCS8Encode()
136 {
137 ByteString der;
138 createBotanKey();
139 if (dsa == NULL) return der;
140 const auto ber = Botan::PKCS8::BER_encode(*dsa);
141 der.resize(ber.size());
142 memcpy(&der[0], &ber[0], ber.size());
143 return der;
144 }
145
146 // Decode from PKCS#8 BER
PKCS8Decode(const ByteString & ber)147 bool BotanDSAPrivateKey::PKCS8Decode(const ByteString& ber)
148 {
149 Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
150 if (source.end_of_data()) return false;
151 Botan::secure_vector<uint8_t> keydata;
152 Botan::AlgorithmIdentifier alg_id;
153 Botan::DSA_PrivateKey* key = NULL;
154 try
155 {
156
157 Botan::BER_Decoder(source)
158 .start_cons(Botan::SEQUENCE)
159 .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
160 .decode(alg_id)
161 .decode(keydata, Botan::OCTET_STRING)
162 .discard_remaining()
163 .end_cons();
164 if (keydata.empty())
165 throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
166 if (Botan::OIDS::lookup(alg_id.oid).compare("DSA"))
167 {
168 ERROR_MSG("Decoded private key not DSA");
169
170 return false;
171 }
172 key = new Botan::DSA_PrivateKey(alg_id, keydata);
173 if (key == NULL) return false;
174
175 setFromBotan(key);
176
177 delete key;
178 }
179 catch (std::exception& e)
180 {
181 ERROR_MSG("Decode failed on %s", e.what());
182
183 return false;
184 }
185
186 return true;
187 }
188
189 // Retrieve the Botan representation of the key
getBotanKey()190 Botan::DSA_PrivateKey* BotanDSAPrivateKey::getBotanKey()
191 {
192 if (!dsa)
193 {
194 createBotanKey();
195 }
196
197 return dsa;
198 }
199
200 // Create the Botan representation of the key
createBotanKey()201 void BotanDSAPrivateKey::createBotanKey()
202 {
203 // y is not needed
204 // Todo: Either q or x is needed. Both is not needed
205 if (p.size() != 0 &&
206 q.size() != 0 &&
207 g.size() != 0 &&
208 x.size() != 0)
209 {
210 if (dsa)
211 {
212 delete dsa;
213 dsa = NULL;
214 }
215
216 try
217 {
218 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
219 dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
220 Botan::DL_Group(BotanUtil::byteString2bigInt(p),
221 BotanUtil::byteString2bigInt(q),
222 BotanUtil::byteString2bigInt(g)),
223 BotanUtil::byteString2bigInt(x));
224 }
225 catch (...)
226 {
227 ERROR_MSG("Could not create the Botan private key");
228 }
229 }
230 }
231