botan: Add support for Ed25519 keys
[strongswan.git] / src / libstrongswan / plugins / botan / botan_ed_private_key.c
1 /*
2 * Copyright (C) 2018 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24 #include "botan_ed_private_key.h"
25 #include "botan_ed_public_key.h"
26 #include "botan_util.h"
27
28 #include <botan/build.h>
29
30 #ifdef BOTAN_HAS_ED25519
31
32 #include <asn1/asn1.h>
33 #include <utils/debug.h>
34
35 typedef struct private_private_key_t private_private_key_t;
36
37 #define ED25519_KEY_LEN 32
38
39 /**
40 * Private data
41 */
42 struct private_private_key_t {
43
44 /**
45 * Public interface
46 */
47 private_key_t public;
48
49 /**
50 * Botan private key object
51 */
52 botan_privkey_t key;
53
54 /**
55 * Reference count
56 */
57 refcount_t ref;
58 };
59
60 METHOD(private_key_t, sign, bool,
61 private_private_key_t *this, signature_scheme_t scheme,
62 void *params, chunk_t data, chunk_t *signature)
63 {
64 switch (scheme)
65 {
66 case SIGN_ED25519:
67 return botan_get_signature(this->key, "Pure", data, signature);
68 default:
69 DBG1(DBG_LIB, "signature scheme %N not supported via botan",
70 signature_scheme_names, scheme);
71 return FALSE;
72 }
73 }
74
75 METHOD(private_key_t, decrypt, bool,
76 private_private_key_t *this, encryption_scheme_t scheme,
77 chunk_t crypto, chunk_t *plain)
78 {
79 DBG1(DBG_LIB, "EdDSA private key decryption not implemented");
80 return FALSE;
81 }
82
83 METHOD(private_key_t, get_keysize, int,
84 private_private_key_t *this)
85 {
86 return ED25519_KEY_LEN * 8;
87 }
88
89 METHOD(private_key_t, get_type, key_type_t,
90 private_private_key_t *this)
91 {
92 return KEY_ED25519;
93 }
94
95 METHOD(private_key_t, get_public_key, public_key_t*,
96 private_private_key_t *this)
97 {
98 botan_pubkey_t pubkey;
99
100 if (botan_privkey_export_pubkey(&pubkey, this->key))
101 {
102 return NULL;
103 }
104 return botan_ed_public_key_adopt(pubkey);
105 }
106
107 METHOD(private_key_t, get_fingerprint, bool,
108 private_private_key_t *this, cred_encoding_type_t type,
109 chunk_t *fingerprint)
110 {
111 botan_pubkey_t pubkey;
112 bool success = FALSE;
113
114 /* check the cache before doing the export */
115 if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
116 {
117 return TRUE;
118 }
119
120 if (botan_privkey_export_pubkey(&pubkey, this->key))
121 {
122 return FALSE;
123 }
124 success = botan_get_fingerprint(pubkey, this, type, fingerprint);
125 botan_pubkey_destroy(pubkey);
126 return success;
127 }
128
129 METHOD(private_key_t, get_encoding, bool,
130 private_private_key_t *this, cred_encoding_type_t type,
131 chunk_t *encoding)
132 {
133 return botan_get_privkey_encoding(this->key, type, encoding);
134 }
135
136 METHOD(private_key_t, get_ref, private_key_t*,
137 private_private_key_t *this)
138 {
139 ref_get(&this->ref);
140 return &this->public;
141 }
142
143 METHOD(private_key_t, destroy, void,
144 private_private_key_t *this)
145 {
146 if (ref_put(&this->ref))
147 {
148 lib->encoding->clear_cache(lib->encoding, this);
149 botan_privkey_destroy(this->key);
150 free(this);
151 }
152 }
153
154 /**
155 * Internal generic constructor
156 */
157 static private_private_key_t *create_empty()
158 {
159 private_private_key_t *this;
160
161 INIT(this,
162 .public = {
163 .get_type = _get_type,
164 .sign = _sign,
165 .decrypt = _decrypt,
166 .get_keysize = _get_keysize,
167 .get_public_key = _get_public_key,
168 .equals = private_key_equals,
169 .belongs_to = private_key_belongs_to,
170 .get_fingerprint = _get_fingerprint,
171 .has_fingerprint = private_key_has_fingerprint,
172 .get_encoding = _get_encoding,
173 .get_ref = _get_ref,
174 .destroy = _destroy,
175 },
176 .ref = 1,
177 );
178
179 return this;
180 }
181
182 /*
183 * Described in header
184 */
185 private_key_t *botan_ed_private_key_adopt(botan_privkey_t key)
186 {
187 private_private_key_t *this;
188
189 this = create_empty();
190 this->key = key;
191
192 return &this->public;
193 }
194
195 /*
196 * Described in header
197 */
198 private_key_t *botan_ed_private_key_gen(key_type_t type, va_list args)
199 {
200 private_private_key_t *this;
201 botan_rng_t rng;
202
203 while (TRUE)
204 {
205 switch (va_arg(args, builder_part_t))
206 {
207 case BUILD_KEY_SIZE:
208 /* just ignore the key size */
209 va_arg(args, u_int);
210 continue;
211 case BUILD_END:
212 break;
213 default:
214 return NULL;
215 }
216 break;
217 }
218
219 if (botan_rng_init(&rng, "system"))
220 {
221 return NULL;
222 }
223
224 this = create_empty();
225
226 if (botan_privkey_create(&this->key, "Ed25519", NULL, rng))
227 {
228 DBG1(DBG_LIB, "EdDSA private key generation failed");
229 botan_rng_destroy(rng);
230 free(this);
231 return NULL;
232 }
233
234 botan_rng_destroy(rng);
235 return &this->public;
236 }
237
238 /*
239 * Described in header
240 */
241 private_key_t *botan_ed_private_key_load(key_type_t type, va_list args)
242 {
243 private_private_key_t *this;
244 chunk_t key = chunk_empty;
245
246 while (TRUE)
247 {
248 switch (va_arg(args, builder_part_t))
249 {
250 case BUILD_EDDSA_PRIV_ASN1_DER:
251 key = va_arg(args, chunk_t);
252 continue;
253 case BUILD_END:
254 break;
255 default:
256 return NULL;
257 }
258 break;
259 }
260
261 /* PKCS#8-encoded keys are handled generically, so we only handle the
262 * explicit case */
263 if (asn1_unwrap(&key, &key) != ASN1_OCTET_STRING ||
264 key.len != ED25519_KEY_LEN)
265 {
266 return NULL;
267 }
268
269 this = create_empty();
270
271 if (botan_privkey_load_ed25519(&this->key, key.ptr))
272 {
273 free(this);
274 return NULL;
275 }
276 return &this->public;
277 }
278
279 #endif