2 * Copyright (C) 2018 René Korthaus
3 * Copyright (C) 2018 Konstantinos Kolelis
4 * Rohde & Schwarz Cybersecurity GmbH
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 #include "botan_ec_public_key.h"
26 #include "botan_util.h"
28 #include <botan/build.h>
30 #ifdef BOTAN_HAS_ECDSA
32 #include <asn1/asn1.h>
33 #include <asn1/asn1_parser.h>
35 #include <utils/debug.h>
37 #include <botan/ffi.h>
39 typedef struct private_botan_ec_public_key_t private_botan_ec_public_key_t
;
42 * Private data structure with signing context.
44 struct private_botan_ec_public_key_t
{
47 * Public interface for this signer
49 botan_ec_public_key_t
public;
62 #define SIG_FORMAT_IEEE_1363 0
63 #define SIG_FORMAT_DER_SEQUENCE 1
66 * Verification of a DER encoded signature as in RFC 3279 or as in RFC 4754
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
)
72 chunk_t sig
= signature
;
74 if (signature_format
== SIG_FORMAT_DER_SEQUENCE
)
77 * botan requires a signature in IEEE 1363 format (r||s)
78 * re-encode from ASN.1 sequence of two integers r,s
80 chunk_t parse
= signature
, r
, s
;
82 if (asn1_unwrap(&parse
, &parse
) != ASN1_SEQUENCE
||
83 asn1_unwrap(&parse
, &r
) != ASN1_INTEGER
||
84 asn1_unwrap(&parse
, &s
) != ASN1_INTEGER
)
89 r
= chunk_skip_zero(r
);
90 s
= chunk_skip_zero(s
);
93 * r and s must be of size m_order.bytes()/2 each
95 if (r
.len
> keylen
|| s
.len
> keylen
)
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
);
105 return botan_verify_signature(this->key
, hash_and_padding
, data
, sig
);
108 METHOD(public_key_t
, get_type
, key_type_t
,
109 private_botan_ec_public_key_t
*this)
114 METHOD(public_key_t
, get_keysize
, int,
115 private_botan_ec_public_key_t
*this)
120 if (botan_mp_init(&p
))
125 if (botan_pubkey_get_field(p
, this->key
, "p") ||
126 botan_mp_num_bits(p
, &bits
))
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
)
140 size_t keylen
= (get_keysize(this) + 7) / 8;
141 const char *hash_and_padding
;
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
;
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
;
156 case SIGN_ECDSA_WITH_SHA256_DER
:
157 hash_and_padding
= "EMSA1(SHA-256)";
158 sig_format
= SIG_FORMAT_DER_SEQUENCE
;
160 case SIGN_ECDSA_WITH_SHA384_DER
:
161 hash_and_padding
= "EMSA1(SHA-384)";
162 sig_format
= SIG_FORMAT_DER_SEQUENCE
;
164 case SIGN_ECDSA_WITH_SHA512_DER
:
165 hash_and_padding
= "EMSA1(SHA-512)";
166 sig_format
= SIG_FORMAT_DER_SEQUENCE
;
168 /* r||s -> Botan::IEEE_1363 */
170 hash_and_padding
= "EMSA1(SHA-256)";
171 sig_format
= SIG_FORMAT_IEEE_1363
;
174 hash_and_padding
= "EMSA1(SHA-384)";
175 sig_format
= SIG_FORMAT_IEEE_1363
;
178 hash_and_padding
= "EMSA1(SHA-512)";
179 sig_format
= SIG_FORMAT_IEEE_1363
;
182 DBG1(DBG_LIB
, "signature scheme %N not supported via botan",
183 signature_scheme_names
, scheme
);
187 return verify_signature(this, hash_and_padding
,
188 sig_format
, keylen
, data
, signature
);
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
)
195 DBG1(DBG_LIB
, "EC public key encryption not implemented");
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
)
203 return botan_get_fingerprint(this->key
, this, type
, fingerprint
);
206 METHOD(public_key_t
, get_encoding
, bool,
207 private_botan_ec_public_key_t
*this, cred_encoding_type_t type
,
210 return botan_get_encoding(this->key
, type
, encoding
);
213 METHOD(public_key_t
, get_ref
, public_key_t
*,
214 private_botan_ec_public_key_t
*this)
217 return &this->public.key
;
220 METHOD(public_key_t
, destroy
, void,
221 private_botan_ec_public_key_t
*this)
223 if (ref_put(&this->ref
))
225 lib
->encoding
->clear_cache(lib
->encoding
, this);
226 botan_pubkey_destroy(this->key
);
232 * Described in header
234 botan_ec_public_key_t
*botan_ec_public_key_adopt(botan_pubkey_t key
)
236 private_botan_ec_public_key_t
*this;
241 .get_type
= _get_type
,
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
,
257 return &this->public;