Annotation of embedaddon/strongswan/src/libstrongswan/plugins/botan/botan_ec_public_key.c, revision 1.1.1.1
1.1 misho 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: 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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>