]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/botan/botan_ec_private_key.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / plugins / botan / botan_ec_private_key.c
CommitLineData
af26cc4d 1/*
72491b78 2 * Copyright (C) 2018 Tobias Brunner
72491b78 3 *
af26cc4d
RK
4 * Copyright (C) 2018 René Korthaus
5 * Copyright (C) 2018 Konstantinos Kolelis
6 * Rohde & Schwarz Cybersecurity GmbH
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27
28#include "botan_ec_private_key.h"
607f10dc 29#include "botan_ec_public_key.h"
de2a2431 30#include "botan_util.h"
af26cc4d
RK
31
32#include <botan/build.h>
33
34#ifdef BOTAN_HAS_ECDSA
35
36#include <asn1/asn1.h>
37#include <asn1/oid.h>
af26cc4d
RK
38
39#include <utils/debug.h>
40
41#include <botan/ffi.h>
42
43typedef struct private_botan_ec_private_key_t private_botan_ec_private_key_t;
44
45/**
46 * Private data of a botan_ec_private_key_t object.
47 */
48struct private_botan_ec_private_key_t {
de2a2431 49
af26cc4d 50 /**
de2a2431 51 * Public interface
af26cc4d
RK
52 */
53 botan_ec_private_key_t public;
54
55 /**
56 * Botan ec private key
57 */
58 botan_privkey_t key;
59
72491b78
TB
60 /**
61 * OID of the curve
62 */
63 int oid;
64
af26cc4d
RK
65 /**
66 * Reference count
67 */
68 refcount_t ref;
69};
70
71#define SIG_FORMAT_IEEE_1363 0
72#define SIG_FORMAT_DER_SEQUENCE 1
73
af26cc4d
RK
74/**
75 * Build a DER encoded signature as in RFC 3279 or as in RFC 4754
76 */
77static bool build_signature(botan_privkey_t key, const char *hash_and_padding,
78 int signature_format, chunk_t data,
79 chunk_t *signature)
80{
de2a2431 81 if (!botan_get_signature(key, hash_and_padding, data, signature))
af26cc4d
RK
82 {
83 return FALSE;
84 }
85
af26cc4d
RK
86 if (signature_format == SIG_FORMAT_DER_SEQUENCE)
87 {
88 /* format as ASN.1 sequence of two integers r,s */
de2a2431
TB
89 chunk_t r = chunk_empty, s = chunk_empty;
90
af26cc4d 91 chunk_split(*signature, "aa", signature->len / 2, &r,
de2a2431 92 signature->len / 2, &s);
af26cc4d
RK
93
94 chunk_free(signature);
de2a2431
TB
95 *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("m", r),
96 asn1_integer("m", s));
af26cc4d 97 }
af26cc4d
RK
98 return TRUE;
99}
100
101METHOD(private_key_t, sign, bool,
102 private_botan_ec_private_key_t *this, signature_scheme_t scheme,
103 void *params, chunk_t data, chunk_t *signature)
104{
105 switch (scheme)
106 {
de2a2431 107 /* r||s -> Botan::IEEE_1363, data is the hash already */
af26cc4d 108 case SIGN_ECDSA_WITH_NULL:
af26cc4d 109 return build_signature(this->key, "Raw",
de2a2431
TB
110 SIG_FORMAT_IEEE_1363, data, signature);
111 /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
af26cc4d 112 case SIGN_ECDSA_WITH_SHA1_DER:
af26cc4d
RK
113 return build_signature(this->key, "EMSA1(SHA-1)",
114 SIG_FORMAT_DER_SEQUENCE, data, signature);
115 case SIGN_ECDSA_WITH_SHA256_DER:
116 return build_signature(this->key, "EMSA1(SHA-256)",
117 SIG_FORMAT_DER_SEQUENCE, data, signature);
118 case SIGN_ECDSA_WITH_SHA384_DER:
119 return build_signature(this->key, "EMSA1(SHA-384)",
120 SIG_FORMAT_DER_SEQUENCE, data, signature);
121 case SIGN_ECDSA_WITH_SHA512_DER:
122 return build_signature(this->key, "EMSA1(SHA-512)",
123 SIG_FORMAT_DER_SEQUENCE, data, signature);
de2a2431 124 /* r||s -> Botan::IEEE_1363 */
af26cc4d 125 case SIGN_ECDSA_256:
af26cc4d
RK
126 return build_signature(this->key, "EMSA1(SHA-256)",
127 SIG_FORMAT_IEEE_1363, data, signature);
128 case SIGN_ECDSA_384:
af26cc4d
RK
129 return build_signature(this->key, "EMSA1(SHA-384)",
130 SIG_FORMAT_IEEE_1363, data, signature);
131 case SIGN_ECDSA_521:
af26cc4d
RK
132 return build_signature(this->key, "EMSA1(SHA-512)",
133 SIG_FORMAT_IEEE_1363, data, signature);
134 default:
135 DBG1(DBG_LIB, "signature scheme %N not supported via botan",
136 signature_scheme_names, scheme);
137 return FALSE;
138 }
139}
140
141METHOD(private_key_t, decrypt, bool,
142 private_botan_ec_private_key_t *this, encryption_scheme_t scheme,
4abb29f6 143 void *params, chunk_t crypto, chunk_t *plain)
af26cc4d
RK
144{
145 DBG1(DBG_LIB, "EC private key decryption not implemented");
146 return FALSE;
147}
148
149METHOD(private_key_t, get_keysize, int,
150 private_botan_ec_private_key_t *this)
151{
152 botan_mp_t p;
de2a2431 153 size_t bits = 0;
af26cc4d 154
de2a2431 155 if (botan_mp_init(&p))
af26cc4d 156 {
af26cc4d
RK
157 return 0;
158 }
159
de2a2431
TB
160 if (botan_privkey_get_field(p, this->key, "p") ||
161 botan_mp_num_bits(p, &bits))
af26cc4d
RK
162 {
163 botan_mp_destroy(p);
164 return 0;
165 }
166
167 botan_mp_destroy(p);
168 return bits;
169}
170
171METHOD(private_key_t, get_type, key_type_t,
172 private_botan_ec_private_key_t *this)
173{
174 return KEY_ECDSA;
175}
176
177METHOD(private_key_t, get_public_key, public_key_t*,
178 private_botan_ec_private_key_t *this)
179{
de2a2431 180 botan_pubkey_t pubkey;
af26cc4d 181
af26cc4d
RK
182 if (botan_privkey_export_pubkey(&pubkey, this->key))
183 {
607f10dc 184 return NULL;
af26cc4d 185 }
607f10dc 186 return (public_key_t*)botan_ec_public_key_adopt(pubkey);
af26cc4d
RK
187}
188
189METHOD(private_key_t, get_fingerprint, bool,
190 private_botan_ec_private_key_t *this, cred_encoding_type_t type,
191 chunk_t *fingerprint)
192{
de2a2431 193 botan_pubkey_t pubkey;
af26cc4d
RK
194 bool success = FALSE;
195
de2a2431
TB
196 /* check the cache before doing the export */
197 if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
198 {
199 return TRUE;
200 }
201
af26cc4d
RK
202 if (botan_privkey_export_pubkey(&pubkey, this->key))
203 {
204 return FALSE;
205 }
de2a2431 206 success = botan_get_fingerprint(pubkey, this, type, fingerprint);
af26cc4d
RK
207 botan_pubkey_destroy(pubkey);
208 return success;
209}
210
211METHOD(private_key_t, get_encoding, bool,
212 private_botan_ec_private_key_t *this, cred_encoding_type_t type,
213 chunk_t *encoding)
214{
bd267c86 215 return botan_get_privkey_encoding(this->key, type, encoding);
af26cc4d
RK
216}
217
218METHOD(private_key_t, get_ref, private_key_t*,
219 private_botan_ec_private_key_t *this)
220{
221 ref_get(&this->ref);
222 return &this->public.key;
223}
224
225METHOD(private_key_t, destroy, void,
226 private_botan_ec_private_key_t *this)
227{
228 if (ref_put(&this->ref))
229 {
de2a2431
TB
230 lib->encoding->clear_cache(lib->encoding, this);
231 botan_privkey_destroy(this->key);
af26cc4d
RK
232 free(this);
233 }
234}
235
236/**
237 * Internal generic constructor
238 */
72491b78 239static private_botan_ec_private_key_t *create_empty(int oid)
af26cc4d
RK
240{
241 private_botan_ec_private_key_t *this;
242
243 INIT(this,
244 .public = {
245 .key = {
246 .get_type = _get_type,
247 .sign = _sign,
248 .decrypt = _decrypt,
249 .get_keysize = _get_keysize,
250 .get_public_key = _get_public_key,
251 .equals = private_key_equals,
252 .belongs_to = private_key_belongs_to,
253 .get_fingerprint = _get_fingerprint,
254 .has_fingerprint = private_key_has_fingerprint,
255 .get_encoding = _get_encoding,
256 .get_ref = _get_ref,
257 .destroy = _destroy,
258 },
259 },
72491b78 260 .oid = oid,
af26cc4d
RK
261 .ref = 1,
262 );
263
264 return this;
265}
266
607f10dc
TB
267/*
268 * Described in header
269 */
270botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key, int oid)
271{
272 private_botan_ec_private_key_t *this;
273
274 this = create_empty(oid);
275 this->key = key;
276
277 return &this->public;
278}
279
af26cc4d 280/*
de2a2431 281 * Described in header
af26cc4d
RK
282 */
283botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args)
284{
285 private_botan_ec_private_key_t *this;
de2a2431 286 botan_rng_t rng;
af26cc4d 287 u_int key_size = 0;
72491b78 288 int oid;
de2a2431 289 const char *curve;
af26cc4d
RK
290
291 while (TRUE)
292 {
293 switch (va_arg(args, builder_part_t))
294 {
295 case BUILD_KEY_SIZE:
296 key_size = va_arg(args, u_int);
297 continue;
298 case BUILD_END:
299 break;
300 default:
301 return NULL;
302 }
303 break;
304 }
305
306 if (!key_size)
307 {
308 return NULL;
309 }
310
311 switch (key_size)
312 {
313 case 256:
314 curve = "secp256r1";
72491b78 315 oid = OID_PRIME256V1;
af26cc4d
RK
316 break;
317 case 384:
318 curve = "secp384r1";
72491b78 319 oid = OID_SECT384R1;
af26cc4d
RK
320 break;
321 case 521:
322 curve = "secp521r1";
72491b78 323 oid = OID_SECT521R1;
af26cc4d
RK
324 break;
325 default:
326 DBG1(DBG_LIB, "EC private key size %d not supported via botan",
327 key_size);
328 return NULL;
329 }
330
4261fced 331 if (!botan_get_rng(&rng, RNG_TRUE))
af26cc4d
RK
332 {
333 return NULL;
334 }
335
72491b78 336 this = create_empty(oid);
af26cc4d 337
6051d9b5 338 if (botan_privkey_create(&this->key, "ECDSA", curve, rng))
af26cc4d 339 {
de2a2431 340 DBG1(DBG_LIB, "EC private key generation failed");
af26cc4d 341 botan_rng_destroy(rng);
de2a2431 342 free(this);
af26cc4d
RK
343 return NULL;
344 }
345
346 botan_rng_destroy(rng);
347 return &this->public;
348}
349
de2a2431
TB
350/*
351 * Described in header
af26cc4d
RK
352 */
353botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
354{
355 private_botan_ec_private_key_t *this;
356 chunk_t params = chunk_empty, key = chunk_empty;
72491b78 357 chunk_t alg_id = chunk_empty, pkcs8 = chunk_empty;
de2a2431 358 botan_rng_t rng;
72491b78 359 int oid = OID_UNKNOWN;
af26cc4d
RK
360
361 while (TRUE)
362 {
363 switch (va_arg(args, builder_part_t))
364 {
365 case BUILD_BLOB_ALGID_PARAMS:
366 params = va_arg(args, chunk_t);
367 continue;
368 case BUILD_BLOB_ASN1_DER:
369 key = va_arg(args, chunk_t);
370 continue;
371 case BUILD_END:
372 break;
373 default:
374 return NULL;
375 }
376 break;
377 }
378
af26cc4d 379 /*
72491b78
TB
380 * Botan expects a PKCS#8 private key, so we build one, if necessary.
381 * RFC 5480 mandates ECParameters as part of the algorithmIdentifier, which
382 * we should get from e.g. the pkcs8 plugin.
af26cc4d 383 */
72491b78 384 if (params.len != 0 && type == KEY_ECDSA)
af26cc4d 385 {
72491b78 386 /* if ECParameters is passed, just use it */
de2a2431
TB
387 alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
388 chunk_clone(params));
72491b78
TB
389 if (asn1_unwrap(&params, &params) == ASN1_OID)
390 {
391 oid = asn1_known_oid(params);
392 }
af26cc4d
RK
393 }
394 else
395 {
396 /*
72491b78
TB
397 * no explicit ECParameters passed, try to extract them from the
398 * ECPrivateKey structure and create an algorithmIdentifier
af26cc4d 399 */
72491b78
TB
400 chunk_t unwrap = key, inner;
401
402 if (asn1_unwrap(&unwrap, &unwrap) == ASN1_SEQUENCE &&
403 asn1_unwrap(&unwrap, &inner) == ASN1_INTEGER &&
404 asn1_parse_integer_uint64(inner) == 1 &&
405 asn1_unwrap(&unwrap, &inner) == ASN1_OCTET_STRING &&
406 asn1_unwrap(&unwrap, &inner) == ASN1_CONTEXT_C_0 &&
407 asn1_unwrap(&inner, &inner) == ASN1_OID)
af26cc4d 408 {
72491b78
TB
409 oid = asn1_known_oid(inner);
410 if (oid != OID_UNKNOWN)
af26cc4d 411 {
72491b78
TB
412 alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
413 asn1_simple_object(ASN1_OID, inner));
af26cc4d
RK
414 }
415 }
72491b78 416 }
af26cc4d 417
72491b78
TB
418 if (oid == OID_UNKNOWN)
419 {
420 chunk_free(&alg_id);
421 return NULL;
af26cc4d
RK
422 }
423
de2a2431 424 pkcs8 = asn1_wrap(ASN1_SEQUENCE, "mms",
af26cc4d
RK
425 asn1_integer("c", chunk_from_chars(0x00)),
426 alg_id,
427 asn1_wrap(ASN1_OCTET_STRING, "c", key));
428
72491b78 429 this = create_empty(oid);
de2a2431 430
4261fced 431 if (!botan_get_rng(&rng, RNG_STRONG))
af26cc4d
RK
432 {
433 chunk_clear(&pkcs8);
de2a2431 434 free(this);
af26cc4d
RK
435 return NULL;
436 }
437
438 if (botan_privkey_load(&this->key, rng, pkcs8.ptr, pkcs8.len, NULL))
439 {
440 chunk_clear(&pkcs8);
441 botan_rng_destroy(rng);
de2a2431 442 free(this);
af26cc4d
RK
443 return NULL;
444 }
445
446 chunk_clear(&pkcs8);
447 botan_rng_destroy(rng);
448 return &this->public;
449}
450
de2a2431 451#endif