860d376c3bc17e9c0d25048527c2c4e3e8518d3d
[strongswan.git] / src / libstrongswan / plugins / botan / botan_util.c
1 /*
2 * Copyright (C) 2018 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2018 René Korthaus
6 * Rohde & Schwarz Cybersecurity GmbH
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27 #include "botan_util.h"
28
29 #include <utils/debug.h>
30
31 #include <botan/ffi.h>
32
33 /*
34 * Described in header
35 */
36 bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp)
37 {
38 if (botan_mp_init(mp))
39 {
40 return FALSE;
41 }
42
43 if (botan_mp_from_bin(*mp, value.ptr, value.len))
44 {
45 botan_mp_destroy(*mp);
46 return FALSE;
47 }
48 return TRUE;
49 }
50
51 /*
52 * Described in header
53 */
54 const char *botan_get_hash(hash_algorithm_t hash)
55 {
56 switch (hash)
57 {
58 case HASH_MD5:
59 return "MD5";
60 case HASH_SHA1:
61 return "SHA-1";
62 case HASH_SHA224:
63 return "SHA-224";
64 case HASH_SHA256:
65 return "SHA-256";
66 case HASH_SHA384:
67 return "SHA-384";
68 case HASH_SHA512:
69 return "SHA-512";
70 default:
71 return NULL;
72 }
73 }
74
75 /*
76 * Described in header
77 */
78 bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
79 chunk_t *encoding)
80 {
81 bool success = TRUE;
82
83 encoding->len = 0;
84 if (botan_pubkey_export(pubkey, NULL, &encoding->len,
85 BOTAN_PRIVKEY_EXPORT_FLAG_DER)
86 != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
87 {
88 return FALSE;
89 }
90
91 *encoding = chunk_alloc(encoding->len);
92 if (botan_pubkey_export(pubkey, encoding->ptr, &encoding->len,
93 BOTAN_PRIVKEY_EXPORT_FLAG_DER))
94 {
95 chunk_free(encoding);
96 return FALSE;
97 }
98
99 if (type != PUBKEY_SPKI_ASN1_DER)
100 {
101 chunk_t asn1_encoding = *encoding;
102
103 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
104 CRED_PART_ECDSA_PUB_ASN1_DER,
105 asn1_encoding, CRED_PART_END);
106 chunk_free(&asn1_encoding);
107 }
108 return success;
109 }
110
111 /*
112 * Described in header
113 */
114 bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type,
115 chunk_t *encoding)
116 {
117 uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER;
118
119 switch (type)
120 {
121 case PRIVKEY_PEM:
122 format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM;
123 /* fall-through */
124 case PRIVKEY_ASN1_DER:
125 encoding->len = 0;
126 if (botan_privkey_export(key, NULL, &encoding->len, format)
127 != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
128 {
129 return FALSE;
130 }
131 *encoding = chunk_alloc(encoding->len);
132 if (botan_privkey_export(key, encoding->ptr, &encoding->len,
133 format))
134 {
135 chunk_free(encoding);
136 return FALSE;
137 }
138 return TRUE;
139 default:
140 return FALSE;
141 }
142 }
143
144 /*
145 * Described in header
146 */
147 bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
148 cred_encoding_type_t type, chunk_t *fp)
149 {
150 hasher_t *hasher;
151 chunk_t key;
152
153 if (cache &&
154 lib->encoding->get_cache(lib->encoding, type, cache, fp))
155 {
156 return TRUE;
157 }
158
159 switch (type)
160 {
161 case KEYID_PUBKEY_SHA1:
162 {
163 /* subjectPublicKey -> use botan_pubkey_fingerprint() */
164 fp->len = 0;
165 if (botan_pubkey_fingerprint(pubkey, "SHA-1", NULL, &fp->len)
166 != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
167 {
168 return FALSE;
169 }
170
171 *fp = chunk_alloc(fp->len);
172 if (botan_pubkey_fingerprint(pubkey, "SHA-1", fp->ptr, &fp->len))
173 {
174 chunk_free(fp);
175 return FALSE;
176 }
177 break;
178 }
179 case KEYID_PUBKEY_INFO_SHA1:
180 {
181 /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */
182 if (!botan_get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &key))
183 {
184 return FALSE;
185 }
186
187 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
188 if (!hasher || !hasher->allocate_hash(hasher, key, fp))
189 {
190 DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
191 "fingerprinting failed");
192 DESTROY_IF(hasher);
193 chunk_free(&key);
194 return FALSE;
195 }
196 hasher->destroy(hasher);
197 chunk_free(&key);
198 break;
199 }
200 default:
201 return FALSE;
202 }
203
204 if (cache)
205 {
206 lib->encoding->cache(lib->encoding, type, cache, *fp);
207 }
208 return TRUE;
209 }
210
211 /*
212 * Described in header
213 */
214 bool botan_get_signature(botan_privkey_t key, const char *scheme,
215 chunk_t data, chunk_t *signature)
216 {
217 botan_pk_op_sign_t sign_op;
218 botan_rng_t rng;
219
220 if (!scheme || !signature)
221 {
222 return FALSE;
223 }
224
225 if (botan_pk_op_sign_create(&sign_op, key, scheme, 0))
226 {
227 return FALSE;
228 }
229
230 if (botan_pk_op_sign_update(sign_op, data.ptr, data.len))
231 {
232 botan_pk_op_sign_destroy(sign_op);
233 return FALSE;
234 }
235
236 signature->len = 0;
237 if (botan_pk_op_sign_output_length(sign_op, &signature->len))
238 {
239 botan_pk_op_sign_destroy(sign_op);
240 return FALSE;
241 }
242
243 if (botan_rng_init(&rng, "user"))
244 {
245 botan_pk_op_sign_destroy(sign_op);
246 return FALSE;
247 }
248
249 *signature = chunk_alloc(signature->len);
250 if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len))
251 {
252 chunk_free(signature);
253 botan_rng_destroy(rng);
254 botan_pk_op_sign_destroy(sign_op);
255 return FALSE;
256 }
257
258 botan_rng_destroy(rng);
259 botan_pk_op_sign_destroy(sign_op);
260 return TRUE;
261 }