Annotation of embedaddon/strongswan/src/libstrongswan/plugins/botan/botan_util.c, revision 1.1.1.2
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>