Return to botan_ec_public_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / botan |
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