]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/plugins/botan/botan_ec_public_key.c
credentials: Added void *params to public_key encrypt() and private_key decrypt(...
[people/ms/strongswan.git] / src / libstrongswan / plugins / botan / botan_ec_public_key.c
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"
26 #include "botan_util.h"
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
39 typedef struct private_botan_ec_public_key_t private_botan_ec_public_key_t;
40
41 /**
42 * Private data structure with signing context.
43 */
44 struct private_botan_ec_public_key_t {
45
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 */
68 static 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 {
72 chunk_t sig = signature;
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 */
80 chunk_t parse = signature, r, s;
81
82 if (asn1_unwrap(&parse, &parse) != ASN1_SEQUENCE ||
83 asn1_unwrap(&parse, &r) != ASN1_INTEGER ||
84 asn1_unwrap(&parse, &s) != ASN1_INTEGER)
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 }
105 return botan_verify_signature(this->key, hash_and_padding, data, sig);
106 }
107
108 METHOD(public_key_t, get_type, key_type_t,
109 private_botan_ec_public_key_t *this)
110 {
111 return KEY_ECDSA;
112 }
113
114 METHOD(public_key_t, get_keysize, int,
115 private_botan_ec_public_key_t *this)
116 {
117 botan_mp_t p;
118 size_t bits = 0;
119
120 if (botan_mp_init(&p))
121 {
122 return 0;
123 }
124
125 if (botan_pubkey_get_field(p, this->key, "p") ||
126 botan_mp_num_bits(p, &bits))
127 {
128 botan_mp_destroy(p);
129 return 0;
130 }
131
132 botan_mp_destroy(p);
133 return bits;
134 }
135
136 METHOD(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 {
146 /* r||s -> Botan::IEEE_1363, data is the hash already */
147 case SIGN_ECDSA_WITH_NULL:
148 hash_and_padding = "Raw";
149 sig_format = SIG_FORMAT_IEEE_1363;
150 break;
151 /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
152 case SIGN_ECDSA_WITH_SHA1_DER:
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;
168 /* r||s -> Botan::IEEE_1363 */
169 case SIGN_ECDSA_256:
170 hash_and_padding = "EMSA1(SHA-256)";
171 sig_format = SIG_FORMAT_IEEE_1363;
172 break;
173 case SIGN_ECDSA_384:
174 hash_and_padding = "EMSA1(SHA-384)";
175 sig_format = SIG_FORMAT_IEEE_1363;
176 break;
177 case SIGN_ECDSA_521:
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
191 METHOD(public_key_t, encrypt, bool,
192 private_botan_ec_public_key_t *this, encryption_scheme_t scheme,
193 void *params, chunk_t crypto, chunk_t *plain)
194 {
195 DBG1(DBG_LIB, "EC public key encryption not implemented");
196 return FALSE;
197 }
198
199 METHOD(public_key_t, get_fingerprint, bool,
200 private_botan_ec_public_key_t *this, cred_encoding_type_t type,
201 chunk_t *fingerprint)
202 {
203 return botan_get_fingerprint(this->key, this, type, fingerprint);
204 }
205
206 METHOD(public_key_t, get_encoding, bool,
207 private_botan_ec_public_key_t *this, cred_encoding_type_t type,
208 chunk_t *encoding)
209 {
210 return botan_get_encoding(this->key, type, encoding);
211 }
212
213 METHOD(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
220 METHOD(public_key_t, destroy, void,
221 private_botan_ec_public_key_t *this)
222 {
223 if (ref_put(&this->ref))
224 {
225 lib->encoding->clear_cache(lib->encoding, this);
226 botan_pubkey_destroy(this->key);
227 free(this);
228 }
229 }
230
231 /*
232 * Described in header
233 */
234 botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key)
235 {
236 private_botan_ec_public_key_t *this;
237
238 INIT(this,
239 .public = {
240 .key = {
241 .get_type = _get_type,
242 .verify = _verify,
243 .encrypt = _encrypt,
244 .get_keysize = _get_keysize,
245 .equals = public_key_equals,
246 .get_fingerprint = _get_fingerprint,
247 .has_fingerprint = public_key_has_fingerprint,
248 .get_encoding = _get_encoding,
249 .get_ref = _get_ref,
250 .destroy = _destroy,
251 },
252 },
253 .key = key,
254 .ref = 1,
255 );
256
257 return &this->public;
258 }
259
260 #endif