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>