Return to botan_util.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / botan |
1.1 misho 1: /* 2: * Copyright (C) 2018 Tobias Brunner 3: * Copyright (C) 2018 Andreas Steffen 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * Copyright (C) 2018 René Korthaus 7: * Rohde & Schwarz Cybersecurity GmbH 8: * 9: * Permission is hereby granted, free of charge, to any person obtaining a copy 10: * of this software and associated documentation files (the "Software"), to deal 11: * in the Software without restriction, including without limitation the rights 12: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13: * copies of the Software, and to permit persons to whom the Software is 14: * furnished to do so, subject to the following conditions: 15: * 16: * The above copyright notice and this permission notice shall be included in 17: * all copies or substantial portions of the Software. 18: * 19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25: * THE SOFTWARE. 26: */ 27: 28: #include "botan_util.h" 29: 30: #include <utils/debug.h> 31: 32: #include <botan/ffi.h> 33: 34: /* 35: * Described in header 36: */ 37: bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp) 38: { 39: if (botan_mp_init(mp)) 40: { 41: return FALSE; 42: } 43: 44: if (botan_mp_from_bin(*mp, value.ptr, value.len)) 45: { 46: botan_mp_destroy(*mp); 47: return FALSE; 48: } 49: return TRUE; 50: } 51: 52: /* 53: * Described in header 54: */ 55: const char *botan_get_hash(hash_algorithm_t hash) 56: { 57: switch (hash) 58: { 59: case HASH_MD5: 60: return "MD5"; 61: case HASH_SHA1: 62: return "SHA-1"; 63: case HASH_SHA224: 64: return "SHA-224"; 65: case HASH_SHA256: 66: return "SHA-256"; 67: case HASH_SHA384: 68: return "SHA-384"; 69: case HASH_SHA512: 70: return "SHA-512"; 71: case HASH_SHA3_224: 72: return "SHA-3(224)"; 73: case HASH_SHA3_256: 74: return "SHA-3(256)"; 75: case HASH_SHA3_384: 76: return "SHA-3(384)"; 77: case HASH_SHA3_512: 78: return "SHA-3(512)"; 79: default: 80: return NULL; 81: } 82: } 83: 84: /* 85: * Described in header 86: */ 87: bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type, 88: chunk_t *encoding) 89: { 90: bool success = TRUE; 91: 92: encoding->len = 0; 93: if (botan_pubkey_export(pubkey, NULL, &encoding->len, 94: BOTAN_PRIVKEY_EXPORT_FLAG_DER) 95: != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) 96: { 97: return FALSE; 98: } 99: 100: *encoding = chunk_alloc(encoding->len); 101: if (botan_pubkey_export(pubkey, encoding->ptr, &encoding->len, 102: BOTAN_PRIVKEY_EXPORT_FLAG_DER)) 103: { 104: chunk_free(encoding); 105: return FALSE; 106: } 107: 108: if (type != PUBKEY_SPKI_ASN1_DER) 109: { 110: chunk_t asn1_encoding = *encoding; 111: 112: success = lib->encoding->encode(lib->encoding, type, NULL, encoding, 113: CRED_PART_ECDSA_PUB_ASN1_DER, 114: asn1_encoding, CRED_PART_END); 115: chunk_free(&asn1_encoding); 116: } 117: return success; 118: } 119: 120: /* 121: * Described in header 122: */ 123: bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type, 124: chunk_t *encoding) 125: { 126: uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER; 127: 128: switch (type) 129: { 130: case PRIVKEY_PEM: 131: format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM; 132: /* fall-through */ 133: case PRIVKEY_ASN1_DER: 134: encoding->len = 0; 135: if (botan_privkey_export(key, NULL, &encoding->len, format) 136: != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) 137: { 138: return FALSE; 139: } 140: *encoding = chunk_alloc(encoding->len); 141: if (botan_privkey_export(key, encoding->ptr, &encoding->len, 142: format)) 143: { 144: chunk_free(encoding); 145: return FALSE; 146: } 147: return TRUE; 148: default: 149: return FALSE; 150: } 151: } 152: 153: /* 154: * Described in header 155: */ 156: bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache, 157: cred_encoding_type_t type, chunk_t *fp) 158: { 159: hasher_t *hasher; 160: chunk_t key; 161: 162: if (cache && 163: lib->encoding->get_cache(lib->encoding, type, cache, fp)) 164: { 165: return TRUE; 166: } 167: 168: switch (type) 169: { 170: case KEYID_PUBKEY_SHA1: 171: /* subjectPublicKey -> use botan_pubkey_fingerprint() */ 172: *fp = chunk_alloc(HASH_SIZE_SHA1); 173: if (botan_pubkey_fingerprint(pubkey, "SHA-1", fp->ptr, &fp->len)) 174: { 175: chunk_free(fp); 176: return FALSE; 177: } 178: break; 179: case KEYID_PUBKEY_INFO_SHA1: 180: /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */ 181: if (!botan_get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &key)) 182: { 183: return FALSE; 184: } 185: 186: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 187: if (!hasher || !hasher->allocate_hash(hasher, key, fp)) 188: { 189: DBG1(DBG_LIB, "SHA1 hash algorithm not supported, " 190: "fingerprinting failed"); 191: DESTROY_IF(hasher); 192: chunk_free(&key); 193: return FALSE; 194: } 195: hasher->destroy(hasher); 196: chunk_free(&key); 197: break; 198: default: 199: return FALSE; 200: } 201: 202: if (cache) 203: { 204: lib->encoding->cache(lib->encoding, type, cache, *fp); 205: } 206: return TRUE; 207: } 208: 209: /* 210: * Described in header 211: */ 212: bool botan_get_signature(botan_privkey_t key, const char *scheme, 213: chunk_t data, chunk_t *signature) 214: { 215: botan_pk_op_sign_t sign_op; 216: botan_rng_t rng; 217: 218: if (!scheme || !signature) 219: { 220: return FALSE; 221: } 222: 223: if (botan_pk_op_sign_create(&sign_op, key, scheme, 0)) 224: { 225: return FALSE; 226: } 227: 228: if (botan_pk_op_sign_update(sign_op, data.ptr, data.len)) 229: { 230: botan_pk_op_sign_destroy(sign_op); 231: return FALSE; 232: } 233: 234: signature->len = 0; 235: if (botan_pk_op_sign_output_length(sign_op, &signature->len)) 236: { 237: botan_pk_op_sign_destroy(sign_op); 238: return FALSE; 239: } 240: 1.1.1.2 ! misho 241: if (!botan_get_rng(&rng, RNG_STRONG)) 1.1 misho 242: { 243: botan_pk_op_sign_destroy(sign_op); 244: return FALSE; 245: } 246: 247: *signature = chunk_alloc(signature->len); 248: if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len)) 249: { 250: chunk_free(signature); 251: botan_rng_destroy(rng); 252: botan_pk_op_sign_destroy(sign_op); 253: return FALSE; 254: } 255: 256: botan_rng_destroy(rng); 257: botan_pk_op_sign_destroy(sign_op); 258: return TRUE; 259: } 260: 261: /* 262: * Described in header 263: */ 264: bool botan_verify_signature(botan_pubkey_t key, const char *scheme, 265: chunk_t data, chunk_t signature) 266: { 267: botan_pk_op_verify_t verify_op; 268: bool valid = FALSE; 269: 270: if (botan_pk_op_verify_create(&verify_op, key, scheme, 0)) 271: { 272: return FALSE; 273: } 274: 275: if (botan_pk_op_verify_update(verify_op, data.ptr, data.len)) 276: { 277: botan_pk_op_verify_destroy(verify_op); 278: return FALSE; 279: } 280: 281: valid = !botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len); 282: 283: botan_pk_op_verify_destroy(verify_op); 284: return valid; 285: } 286: 287: /* 288: * Described in header 289: */ 290: bool botan_dh_key_derivation(botan_privkey_t key, chunk_t pub, chunk_t *secret) 291: { 292: botan_pk_op_ka_t ka; 293: 294: if (botan_pk_op_key_agreement_create(&ka, key, "Raw", 0)) 295: { 296: return FALSE; 297: } 298: 299: if (botan_pk_op_key_agreement_size(ka, &secret->len)) 300: { 301: botan_pk_op_key_agreement_destroy(ka); 302: return FALSE; 303: } 304: 305: *secret = chunk_alloc(secret->len); 306: if (botan_pk_op_key_agreement(ka, secret->ptr, &secret->len, pub.ptr, 307: pub.len, NULL, 0)) 308: { 309: chunk_clear(secret); 310: botan_pk_op_key_agreement_destroy(ka); 311: return FALSE; 312: } 313: botan_pk_op_key_agreement_destroy(ka); 314: return TRUE; 315: } 1.1.1.2 ! misho 316: ! 317: /* ! 318: * Described in header ! 319: */ ! 320: const char *botan_map_rng_quality(rng_quality_t quality) ! 321: { ! 322: const char *rng_name; ! 323: ! 324: switch (quality) ! 325: { ! 326: case RNG_WEAK: ! 327: case RNG_STRONG: ! 328: /* some rng_t instances of this class (e.g. in the ike-sa-manager) ! 329: * may be called concurrently by different threads. the Botan RNGs ! 330: * are not reentrant, by default, so use the threadsafe version. ! 331: * because we build without threading support when running tests ! 332: * with leak-detective (lots of reports of frees of unknown memory) ! 333: * there is a fallback to the default */ ! 334: #ifdef BOTAN_TARGET_OS_HAS_THREADS ! 335: rng_name = "user-threadsafe"; ! 336: #else ! 337: rng_name = "user"; ! 338: #endif ! 339: break; ! 340: case RNG_TRUE: ! 341: rng_name = "system"; ! 342: break; ! 343: default: ! 344: return NULL; ! 345: } ! 346: return rng_name; ! 347: } ! 348: ! 349: #ifdef HAVE_BOTAN_RNG_INIT_CUSTOM ! 350: ! 351: CALLBACK(get_random, int, ! 352: rng_t *rng, uint8_t *out, size_t out_len) ! 353: { ! 354: if (!rng->get_bytes(rng, out_len, out)) ! 355: { ! 356: return -1; ! 357: } ! 358: return 0; ! 359: } ! 360: ! 361: CALLBACK(destroy_rng, void, ! 362: rng_t *rng) ! 363: { ! 364: if (rng) ! 365: { ! 366: rng->destroy(rng); ! 367: } ! 368: } ! 369: ! 370: #endif /* HAVE_BOTAN_RNG_INIT_CUSTOM */ ! 371: ! 372: /* ! 373: * Described in header ! 374: */ ! 375: bool botan_get_rng(botan_rng_t *botan_rng, rng_quality_t quality) ! 376: { ! 377: #ifdef HAVE_BOTAN_RNG_INIT_CUSTOM ! 378: if (!lib->settings->get_bool(lib->settings, ! 379: "%s.plugins.botan.internal_rng_only", FALSE, lib->ns)) ! 380: { ! 381: rng_t *rng = lib->crypto->create_rng(lib->crypto, quality); ! 382: ! 383: if (!rng) ! 384: { ! 385: DBG1(DBG_LIB, "no RNG found for quality %N", rng_quality_names, ! 386: quality); ! 387: return FALSE; ! 388: } ! 389: if (botan_rng_init_custom(botan_rng, "strongswan", rng, ! 390: get_random, NULL, destroy_rng)) ! 391: { ! 392: DBG1(DBG_LIB, "Botan RNG creation failed"); ! 393: return FALSE; ! 394: } ! 395: } ! 396: else ! 397: #endif /* HAVE_BOTAN_RNG_INIT_CUSTOM */ ! 398: { ! 399: const char *rng_name = botan_map_rng_quality(quality); ! 400: ! 401: if (!rng_name || botan_rng_init(botan_rng, rng_name)) ! 402: { ! 403: return FALSE; ! 404: } ! 405: } ! 406: return TRUE; ! 407: }