]>
Commit | Line | Data |
---|---|---|
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 | ||
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 { | |
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 | */ | |
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 | { | |
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 | ||
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; | |
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 | ||
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 | { | |
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 | ||
191 | METHOD(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 |
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 | { | |
de2a2431 | 203 | return botan_get_fingerprint(this->key, this, type, fingerprint); |
af26cc4d RK |
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 | { | |
de2a2431 | 210 | return botan_get_encoding(this->key, type, encoding); |
af26cc4d RK |
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 | { | |
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 | 234 | botan_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 RK |
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 | }, | |
607f10dc | 253 | .key = key, |
af26cc4d RK |
254 | .ref = 1, |
255 | ); | |
256 | ||
af26cc4d RK |
257 | return &this->public; |
258 | } | |
259 | ||
260 | #endif |