]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/botan/botan_ec_public_key.c
botan: Reject EC keys with explicitly encoded parameters
[thirdparty/strongswan.git] / src / libstrongswan / plugins / botan / botan_ec_public_key.c
CommitLineData
af26cc4d
RK
1/*
2 * Copyright (C) 2018 René Korthaus
3 * Copyright (C) 2018 Konstantinos Kolelis
4 * Rohde & Schwarz Cybersecurity GmbH
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "botan_ec_public_key.h"
de2a2431 26#include "botan_util.h"
af26cc4d
RK
27
28#include <botan/build.h>
29
30#ifdef BOTAN_HAS_ECDSA
31
32#include <asn1/asn1.h>
33#include <asn1/asn1_parser.h>
34
35#include <utils/debug.h>
36
37#include <botan/ffi.h>
38
39typedef struct private_botan_ec_public_key_t private_botan_ec_public_key_t;
40
41/**
42 * Private data structure with signing context.
43 */
44struct private_botan_ec_public_key_t {
de2a2431 45
af26cc4d
RK
46 /**
47 * Public interface for this signer
48 */
49 botan_ec_public_key_t public;
50
51 /**
52 * Botan ec public key
53 */
54 botan_pubkey_t key;
55
56 /**
57 * Reference counter
58 */
59 refcount_t ref;
60};
61
62#define SIG_FORMAT_IEEE_1363 0
63#define SIG_FORMAT_DER_SEQUENCE 1
64
65/**
66 * Verification of a DER encoded signature as in RFC 3279 or as in RFC 4754
67 */
68static bool verify_signature(private_botan_ec_public_key_t *this,
69 const char* hash_and_padding, int signature_format, size_t keylen,
70 chunk_t data, chunk_t signature)
71{
de2a2431 72 chunk_t sig = signature;
af26cc4d
RK
73
74 if (signature_format == SIG_FORMAT_DER_SEQUENCE)
75 {
76 /*
77 * botan requires a signature in IEEE 1363 format (r||s)
78 * re-encode from ASN.1 sequence of two integers r,s
79 */
de2a2431 80 chunk_t parse = signature, r, s;
af26cc4d 81
de2a2431
TB
82 if (asn1_unwrap(&parse, &parse) != ASN1_SEQUENCE ||
83 asn1_unwrap(&parse, &r) != ASN1_INTEGER ||
84 asn1_unwrap(&parse, &s) != ASN1_INTEGER)
af26cc4d
RK
85 {
86 return FALSE;
87 }
88
89 r = chunk_skip_zero(r);
90 s = chunk_skip_zero(s);
91
92 /*
93 * r and s must be of size m_order.bytes()/2 each
94 */
95 if (r.len > keylen || s.len > keylen)
96 {
97 return FALSE;
98 }
99
100 sig = chunk_alloca(2 * keylen);
101 memset(sig.ptr, 0, sig.len);
102 memcpy(sig.ptr + (keylen - r.len), r.ptr, r.len);
103 memcpy(sig.ptr + keylen + (keylen - s.len), s.ptr, s.len);
104 }
5cd24d26 105 return botan_verify_signature(this->key, hash_and_padding, data, sig);
af26cc4d
RK
106}
107
108METHOD(public_key_t, get_type, key_type_t,
109 private_botan_ec_public_key_t *this)
110{
111 return KEY_ECDSA;
112}
113
114METHOD(public_key_t, get_keysize, int,
115 private_botan_ec_public_key_t *this)
116{
117 botan_mp_t p;
de2a2431 118 size_t bits = 0;
af26cc4d 119
de2a2431 120 if (botan_mp_init(&p))
af26cc4d 121 {
af26cc4d
RK
122 return 0;
123 }
124
de2a2431
TB
125 if (botan_pubkey_get_field(p, this->key, "p") ||
126 botan_mp_num_bits(p, &bits))
af26cc4d
RK
127 {
128 botan_mp_destroy(p);
129 return 0;
130 }
131
132 botan_mp_destroy(p);
133 return bits;
134}
135
136METHOD(public_key_t, verify, bool,
137 private_botan_ec_public_key_t *this, signature_scheme_t scheme,
138 void *params, chunk_t data, chunk_t signature)
139{
140 size_t keylen = (get_keysize(this) + 7) / 8;
141 const char *hash_and_padding;
142 int sig_format;
143
144 switch (scheme)
145 {
de2a2431 146 /* r||s -> Botan::IEEE_1363, data is the hash already */
af26cc4d 147 case SIGN_ECDSA_WITH_NULL:
af26cc4d
RK
148 hash_and_padding = "Raw";
149 sig_format = SIG_FORMAT_IEEE_1363;
150 break;
de2a2431 151 /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
af26cc4d 152 case SIGN_ECDSA_WITH_SHA1_DER:
af26cc4d
RK
153 hash_and_padding = "EMSA1(SHA-1)";
154 sig_format = SIG_FORMAT_DER_SEQUENCE;
155 break;
156 case SIGN_ECDSA_WITH_SHA256_DER:
157 hash_and_padding = "EMSA1(SHA-256)";
158 sig_format = SIG_FORMAT_DER_SEQUENCE;
159 break;
160 case SIGN_ECDSA_WITH_SHA384_DER:
161 hash_and_padding = "EMSA1(SHA-384)";
162 sig_format = SIG_FORMAT_DER_SEQUENCE;
163 break;
164 case SIGN_ECDSA_WITH_SHA512_DER:
165 hash_and_padding = "EMSA1(SHA-512)";
166 sig_format = SIG_FORMAT_DER_SEQUENCE;
167 break;
de2a2431 168 /* r||s -> Botan::IEEE_1363 */
af26cc4d 169 case SIGN_ECDSA_256:
af26cc4d
RK
170 hash_and_padding = "EMSA1(SHA-256)";
171 sig_format = SIG_FORMAT_IEEE_1363;
172 break;
173 case SIGN_ECDSA_384:
af26cc4d
RK
174 hash_and_padding = "EMSA1(SHA-384)";
175 sig_format = SIG_FORMAT_IEEE_1363;
176 break;
177 case SIGN_ECDSA_521:
af26cc4d
RK
178 hash_and_padding = "EMSA1(SHA-512)";
179 sig_format = SIG_FORMAT_IEEE_1363;
180 break;
181 default:
182 DBG1(DBG_LIB, "signature scheme %N not supported via botan",
183 signature_scheme_names, scheme);
184 return FALSE;
185 }
186
187 return verify_signature(this, hash_and_padding,
188 sig_format, keylen, data, signature);
189}
190
191METHOD(public_key_t, encrypt, bool,
192 private_botan_ec_public_key_t *this, encryption_scheme_t scheme,
4abb29f6 193 void *params, chunk_t crypto, chunk_t *plain)
af26cc4d
RK
194{
195 DBG1(DBG_LIB, "EC public key encryption not implemented");
196 return FALSE;
197}
198
af26cc4d
RK
199METHOD(public_key_t, get_fingerprint, bool,
200 private_botan_ec_public_key_t *this, cred_encoding_type_t type,
201 chunk_t *fingerprint)
202{
de2a2431 203 return botan_get_fingerprint(this->key, this, type, fingerprint);
af26cc4d
RK
204}
205
206METHOD(public_key_t, get_encoding, bool,
207 private_botan_ec_public_key_t *this, cred_encoding_type_t type,
208 chunk_t *encoding)
209{
de2a2431 210 return botan_get_encoding(this->key, type, encoding);
af26cc4d
RK
211}
212
213METHOD(public_key_t, get_ref, public_key_t*,
214 private_botan_ec_public_key_t *this)
215{
216 ref_get(&this->ref);
217 return &this->public.key;
218}
219
220METHOD(public_key_t, destroy, void,
221 private_botan_ec_public_key_t *this)
222{
223 if (ref_put(&this->ref))
224 {
de2a2431 225 lib->encoding->clear_cache(lib->encoding, this);
af26cc4d
RK
226 botan_pubkey_destroy(this->key);
227 free(this);
228 }
229}
230
de2a2431
TB
231/*
232 * Described in header
af26cc4d 233 */
607f10dc 234botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key)
af26cc4d
RK
235{
236 private_botan_ec_public_key_t *this;
af26cc4d 237
0b989c7b
TB
238#ifdef HAVE_BOTAN_PUBKEY_ECC_KEY_USED_EXPLICIT_ENCODING
239 if (botan_pubkey_ecc_key_used_explicit_encoding(key))
240 {
241 botan_pubkey_destroy(key);
242 return NULL;
243 }
244#endif
245
af26cc4d
RK
246 INIT(this,
247 .public = {
248 .key = {
249 .get_type = _get_type,
250 .verify = _verify,
251 .encrypt = _encrypt,
252 .get_keysize = _get_keysize,
253 .equals = public_key_equals,
254 .get_fingerprint = _get_fingerprint,
255 .has_fingerprint = public_key_has_fingerprint,
256 .get_encoding = _get_encoding,
257 .get_ref = _get_ref,
258 .destroy = _destroy,
259 },
260 },
607f10dc 261 .key = key,
af26cc4d
RK
262 .ref = 1,
263 );
264
af26cc4d
RK
265 return &this->public;
266}
267
268#endif