distinguish between RFC 4754 (concatenated) and RFC 3279 (DER encoded) ECDSA signatures
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_ec_public_key.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "openssl_ec_public_key.h"
18 #include "openssl_util.h"
19
20 #include <debug.h>
21
22 #include <openssl/evp.h>
23 #include <openssl/ecdsa.h>
24 #include <openssl/x509.h>
25
26 typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t;
27
28 /**
29 * Private data structure with signing context.
30 */
31 struct private_openssl_ec_public_key_t {
32 /**
33 * Public interface for this signer.
34 */
35 openssl_ec_public_key_t public;
36
37 /**
38 * EC key object
39 */
40 EC_KEY *ec;
41
42 /**
43 * reference counter
44 */
45 refcount_t ref;
46 };
47
48 /**
49 * Verification of a signature as in RFC 4754
50 */
51 static bool verify_signature(private_openssl_ec_public_key_t *this,
52 int hash_type, chunk_t data, chunk_t signature)
53 {
54 bool valid = FALSE;
55 ECDSA_SIG *sig;
56 chunk_t hash;
57
58 hash = data;
59 if (hash_type != NID_undef)
60 {
61 if (!openssl_hash_chunk(hash_type, data, &hash))
62 {
63 return FALSE;
64 }
65 }
66 sig = ECDSA_SIG_new();
67 if (sig)
68 {
69 /* split the signature chunk in r and s */
70 if (openssl_bn_split(signature, sig->r, sig->s))
71 {
72 valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1);
73 }
74 ECDSA_SIG_free(sig);
75 }
76 if (hash_type != NID_undef)
77 {
78 chunk_free(&hash);
79 }
80 return valid;
81 }
82
83 /**
84 * Verification of a DER encoded signature as in RFC 3279
85 */
86 static bool verify_der_signature(private_openssl_ec_public_key_t *this,
87 int nid, chunk_t data, chunk_t signature)
88 {
89 chunk_t hash;
90 bool valid = FALSE;
91
92 /* remove any preceding 0-bytes from signature */
93 while (signature.len && signature.ptr[0] == 0x00)
94 {
95 signature = chunk_skip(signature, 1);
96 }
97 if (openssl_hash_chunk(nid, data, &hash))
98 {
99 valid = ECDSA_verify(0, hash.ptr, hash.len,
100 signature.ptr, signature.len, this->ec);
101 free(hash.ptr);
102 }
103 return valid;
104 }
105
106 /**
107 * Implementation of public_key_t.get_type.
108 */
109 static key_type_t get_type(private_openssl_ec_public_key_t *this)
110 {
111 return KEY_ECDSA;
112 }
113
114 /**
115 * Implementation of public_key_t.verify.
116 */
117 static bool verify(private_openssl_ec_public_key_t *this, signature_scheme_t scheme,
118 chunk_t data, chunk_t signature)
119 {
120 switch (scheme)
121 {
122 case SIGN_ECDSA_WITH_SHA1_DER:
123 return verify_der_signature(this, NID_sha1, data, signature);
124 case SIGN_ECDSA_WITH_SHA256_DER:
125 return verify_der_signature(this, NID_sha256, data, signature);
126 case SIGN_ECDSA_WITH_SHA384_DER:
127 return verify_der_signature(this, NID_sha384, data, signature);
128 case SIGN_ECDSA_WITH_SHA512_DER:
129 return verify_der_signature(this, NID_sha512, data, signature);
130 case SIGN_ECDSA_WITH_NULL:
131 return verify_signature(this, NID_undef, data, signature);
132 case SIGN_ECDSA_256:
133 return verify_signature(this, NID_sha256, data, signature);
134 case SIGN_ECDSA_384:
135 return verify_signature(this, NID_sha384, data, signature);
136 case SIGN_ECDSA_521:
137 return verify_signature(this, NID_sha512, data, signature);
138 default:
139 DBG1("signature scheme %N not supported in EC",
140 signature_scheme_names, scheme);
141 return FALSE;
142 }
143 }
144
145 /**
146 * Implementation of public_key_t.get_keysize.
147 */
148 static bool encrypt_(private_openssl_ec_public_key_t *this,
149 chunk_t crypto, chunk_t *plain)
150 {
151 DBG1("EC public key encryption not implemented");
152 return FALSE;
153 }
154
155 /**
156 * Implementation of public_key_t.get_keysize.
157 */
158 static size_t get_keysize(private_openssl_ec_public_key_t *this)
159 {
160 return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec));
161 }
162
163 /**
164 * Calculate fingerprint from a EC_KEY, also used in ec private key.
165 */
166 bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
167 {
168 hasher_t *hasher;
169 chunk_t key;
170 u_char *p;
171
172 if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
173 {
174 return TRUE;
175 }
176 switch (type)
177 {
178 case KEY_ID_PUBKEY_SHA1:
179 key = chunk_alloc(i2o_ECPublicKey(ec, NULL));
180 p = key.ptr;
181 i2o_ECPublicKey(ec, &p);
182 break;
183 case KEY_ID_PUBKEY_INFO_SHA1:
184 key = chunk_alloc(i2d_EC_PUBKEY(ec, NULL));
185 p = key.ptr;
186 i2d_EC_PUBKEY(ec, &p);
187 break;
188 default:
189 return FALSE;
190 }
191 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
192 if (!hasher)
193 {
194 DBG1("SHA1 hash algorithm not supported, fingerprinting failed");
195 free(key.ptr);
196 return FALSE;
197 }
198 hasher->allocate_hash(hasher, key, fp);
199 hasher->destroy(hasher);
200 free(key.ptr);
201 lib->encoding->cache(lib->encoding, type, ec, *fp);
202 return TRUE;
203 }
204
205 /**
206 * Implementation of private_key_t.get_fingerprint.
207 */
208 static bool get_fingerprint(private_openssl_ec_public_key_t *this,
209 key_encoding_type_t type, chunk_t *fingerprint)
210 {
211 return openssl_ec_fingerprint(this->ec, type, fingerprint);
212 }
213
214 /**
215 * Implementation of private_key_t.get_encoding.
216 */
217 static bool get_encoding(private_openssl_ec_public_key_t *this,
218 key_encoding_type_t type, chunk_t *encoding)
219 {
220 u_char *p;
221
222 switch (type)
223 {
224 case KEY_PUB_SPKI_ASN1_DER:
225 {
226 *encoding = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
227 p = encoding->ptr;
228 i2d_EC_PUBKEY(this->ec, &p);
229 return TRUE;
230 }
231 default:
232 return FALSE;
233 }
234 }
235
236 /**
237 * Implementation of public_key_t.get_ref.
238 */
239 static public_key_t* get_ref(private_openssl_ec_public_key_t *this)
240 {
241 ref_get(&this->ref);
242 return &this->public.interface;
243 }
244
245 /**
246 * Implementation of openssl_ec_public_key.destroy.
247 */
248 static void destroy(private_openssl_ec_public_key_t *this)
249 {
250 if (ref_put(&this->ref))
251 {
252 if (this->ec)
253 {
254 lib->encoding->clear_cache(lib->encoding, this->ec);
255 EC_KEY_free(this->ec);
256 }
257 free(this);
258 }
259 }
260
261 /**
262 * Generic private constructor
263 */
264 static private_openssl_ec_public_key_t *create_empty()
265 {
266 private_openssl_ec_public_key_t *this = malloc_thing(private_openssl_ec_public_key_t);
267
268 this->public.interface.get_type = (key_type_t (*)(public_key_t *this))get_type;
269 this->public.interface.verify = (bool (*)(public_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t signature))verify;
270 this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
271 this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
272 this->public.interface.equals = public_key_equals;
273 this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
274 this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
275 this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
276 this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
277
278 this->ec = NULL;
279 this->ref = 1;
280
281 return this;
282 }
283
284 /**
285 * Load a public key from an ASN1 encoded blob
286 */
287 static openssl_ec_public_key_t *load(chunk_t blob)
288 {
289 private_openssl_ec_public_key_t *this = create_empty();
290 u_char *p = blob.ptr;
291
292 this->ec = d2i_EC_PUBKEY(NULL, (const u_char**)&p, blob.len);
293
294 if (!this->ec)
295 {
296 destroy(this);
297 return NULL;
298 }
299 return &this->public;
300 }
301
302 typedef struct private_builder_t private_builder_t;
303
304 /**
305 * Builder implementation for key loading
306 */
307 struct private_builder_t {
308 /** implements the builder interface */
309 builder_t public;
310 /** loaded public key */
311 openssl_ec_public_key_t *key;
312 };
313
314 /**
315 * Implementation of builder_t.build
316 */
317 static openssl_ec_public_key_t *build(private_builder_t *this)
318 {
319 openssl_ec_public_key_t *key = this->key;
320
321 free(this);
322 return key;
323 }
324
325 /**
326 * Implementation of builder_t.add
327 */
328 static void add(private_builder_t *this, builder_part_t part, ...)
329 {
330 if (!this->key)
331 {
332 va_list args;
333
334 switch (part)
335 {
336 case BUILD_BLOB_ASN1_DER:
337 {
338 va_start(args, part);
339 this->key = load(va_arg(args, chunk_t));
340 va_end(args);
341 return;
342 }
343 default:
344 break;
345 }
346 }
347 if (this->key)
348 {
349 destroy((private_openssl_ec_public_key_t*)this->key);
350 }
351 builder_cancel(&this->public);
352 }
353
354 /**
355 * Builder construction function
356 */
357 builder_t *openssl_ec_public_key_builder(key_type_t type)
358 {
359 private_builder_t *this;
360
361 if (type != KEY_ECDSA)
362 {
363 return NULL;
364 }
365
366 this = malloc_thing(private_builder_t);
367
368 this->key = NULL;
369 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
370 this->public.build = (void*(*)(builder_t *this))build;
371
372 return &this->public;
373 }
374