]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/botan/botan_rsa_public_key.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / plugins / botan / botan_rsa_public_key.c
1 /*
2 * Copyright (C) 2018 Tobias Brunner
3 * Copyright (C) 2018 Andreas Steffen
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_rsa_public_key.h"
28
29 #include <botan/build.h>
30
31 #ifdef BOTAN_HAS_RSA
32
33 #include "botan_util.h"
34
35 #include <asn1/oid.h>
36 #include <asn1/asn1.h>
37 #include <asn1/asn1_parser.h>
38
39 #include <utils/debug.h>
40
41 #include <botan/ffi.h>
42
43 typedef struct private_botan_rsa_public_key_t private_botan_rsa_public_key_t;
44
45 /**
46 * Private data structure with signing context.
47 */
48 struct private_botan_rsa_public_key_t {
49
50 /**
51 * Public interface for this signer
52 */
53 botan_rsa_public_key_t public;
54
55 /**
56 * Botan public key
57 */
58 botan_pubkey_t key;
59
60 /**
61 * Reference counter
62 */
63 refcount_t ref;
64 };
65
66 /**
67 * Defined in botan_rsa_private_key.c
68 */
69 bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len);
70
71 /**
72 * Verification of an EMSA PSS signature described in PKCS#1
73 */
74 static bool verify_emsa_pss_signature(private_botan_rsa_public_key_t *this,
75 rsa_pss_params_t *params, chunk_t data,
76 chunk_t signature)
77 {
78 char hash_and_padding[BUF_LEN];
79
80 if (!botan_emsa_pss_identifier(params, hash_and_padding,
81 sizeof(hash_and_padding)))
82 {
83 return FALSE;
84 }
85 return botan_verify_signature(this->key, hash_and_padding, data, signature);
86 }
87
88 METHOD(public_key_t, get_type, key_type_t,
89 private_botan_rsa_public_key_t *this)
90 {
91 return KEY_RSA;
92 }
93
94 METHOD(public_key_t, verify, bool,
95 private_botan_rsa_public_key_t *this, signature_scheme_t scheme,
96 void *params, chunk_t data, chunk_t signature)
97 {
98 switch (scheme)
99 {
100 case SIGN_RSA_EMSA_PKCS1_NULL:
101 return botan_verify_signature(this->key, "EMSA_PKCS1(Raw)", data,
102 signature);
103 case SIGN_RSA_EMSA_PKCS1_SHA1:
104 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-1)", data,
105 signature);
106 case SIGN_RSA_EMSA_PKCS1_SHA2_224:
107 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-224)",
108 data, signature);
109 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
110 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-256)",
111 data, signature);
112 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
113 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-384)",
114 data, signature);
115 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
116 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-512)",
117 data, signature);
118 case SIGN_RSA_EMSA_PKCS1_SHA3_224:
119 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(224)",
120 data, signature);
121 case SIGN_RSA_EMSA_PKCS1_SHA3_256:
122 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(256))",
123 data, signature);
124 case SIGN_RSA_EMSA_PKCS1_SHA3_384:
125 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(384))",
126 data, signature);
127 case SIGN_RSA_EMSA_PKCS1_SHA3_512:
128 return botan_verify_signature(this->key, "EMSA_PKCS1(SHA-3(512))",
129 data, signature);
130 case SIGN_RSA_EMSA_PSS:
131 return verify_emsa_pss_signature(this, params, data, signature);
132 default:
133 DBG1(DBG_LIB, "signature scheme %N not supported via botan",
134 signature_scheme_names, scheme);
135 return FALSE;
136 }
137 }
138
139 METHOD(public_key_t, encrypt, bool,
140 private_botan_rsa_public_key_t *this, encryption_scheme_t scheme,
141 void *params, chunk_t plain, chunk_t *crypto)
142 {
143 botan_pk_op_encrypt_t encrypt_op;
144 botan_rng_t rng;
145 chunk_t label = chunk_empty;
146 const char* padding;
147
148 switch (scheme)
149 {
150 case ENCRYPT_RSA_PKCS1:
151 padding = "PKCS1v15";
152 break;
153 case ENCRYPT_RSA_OAEP_SHA1:
154 padding = "OAEP(SHA-1)";
155 break;
156 case ENCRYPT_RSA_OAEP_SHA224:
157 padding = "OAEP(SHA-224)";
158 break;
159 case ENCRYPT_RSA_OAEP_SHA256:
160 padding = "OAEP(SHA-256)";
161 break;
162 case ENCRYPT_RSA_OAEP_SHA384:
163 padding = "OAEP(SHA-384)";
164 break;
165 case ENCRYPT_RSA_OAEP_SHA512:
166 padding = "OAEP(SHA-512)";
167 break;
168 default:
169 DBG1(DBG_LIB, "encryption scheme %N not supported via botan",
170 encryption_scheme_names, scheme);
171 return FALSE;
172 }
173
174 if (scheme != ENCRYPT_RSA_PKCS1 && params != NULL)
175 {
176 label = *(chunk_t *)params;
177 if (label.len > 0)
178 {
179 DBG1(DBG_LIB, "RSA OAEP encryption with a label not supported");
180 return FALSE;
181 }
182 }
183
184 if (!botan_get_rng(&rng, RNG_STRONG))
185 {
186 return FALSE;
187 }
188
189 if (botan_pk_op_encrypt_create(&encrypt_op, this->key, padding, 0))
190 {
191 botan_rng_destroy(rng);
192 return FALSE;
193 }
194
195 crypto->len = 0;
196 if (botan_pk_op_encrypt_output_length(encrypt_op, plain.len, &crypto->len))
197 {
198 botan_rng_destroy(rng);
199 botan_pk_op_encrypt_destroy(encrypt_op);
200 return FALSE;
201 }
202
203 *crypto = chunk_alloc(crypto->len);
204 if (botan_pk_op_encrypt(encrypt_op, rng, crypto->ptr, &crypto->len,
205 plain.ptr, plain.len))
206 {
207 chunk_free(crypto);
208 botan_rng_destroy(rng);
209 botan_pk_op_encrypt_destroy(encrypt_op);
210 return FALSE;
211 }
212 botan_rng_destroy(rng);
213 botan_pk_op_encrypt_destroy(encrypt_op);
214 return TRUE;
215 }
216
217 METHOD(public_key_t, get_keysize, int,
218 private_botan_rsa_public_key_t *this)
219 {
220 botan_mp_t n;
221 size_t bits = 0;
222
223 if (botan_mp_init(&n))
224 {
225 return 0;
226 }
227
228 if (botan_pubkey_get_field(n, this->key, "n") ||
229 botan_mp_num_bits(n, &bits))
230 {
231 botan_mp_destroy(n);
232 return 0;
233 }
234
235 botan_mp_destroy(n);
236 return bits;
237 }
238
239 METHOD(public_key_t, get_fingerprint, bool,
240 private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
241 chunk_t *fp)
242 {
243 return botan_get_fingerprint(this->key, this, type, fp);
244 }
245
246 METHOD(public_key_t, get_encoding, bool,
247 private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
248 chunk_t *encoding)
249 {
250 return botan_get_encoding(this->key, type, encoding);
251 }
252
253 METHOD(public_key_t, get_ref, public_key_t*,
254 private_botan_rsa_public_key_t *this)
255 {
256 ref_get(&this->ref);
257 return &this->public.key;
258 }
259
260 METHOD(public_key_t, destroy, void,
261 private_botan_rsa_public_key_t *this)
262 {
263 if (ref_put(&this->ref))
264 {
265 lib->encoding->clear_cache(lib->encoding, this);
266 botan_pubkey_destroy(this->key);
267 free(this);
268 }
269 }
270
271 /**
272 * Internal generic constructor
273 */
274 static private_botan_rsa_public_key_t *create_empty()
275 {
276 private_botan_rsa_public_key_t *this;
277
278 INIT(this,
279 .public = {
280 .key = {
281 .get_type = _get_type,
282 .verify = _verify,
283 .encrypt = _encrypt,
284 .equals = public_key_equals,
285 .get_keysize = _get_keysize,
286 .get_fingerprint = _get_fingerprint,
287 .has_fingerprint = public_key_has_fingerprint,
288 .get_encoding = _get_encoding,
289 .get_ref = _get_ref,
290 .destroy = _destroy,
291 },
292 },
293 .ref = 1,
294 );
295
296 return this;
297 }
298
299 /*
300 * Described in header
301 */
302 botan_rsa_public_key_t *botan_rsa_public_key_adopt(botan_pubkey_t key)
303 {
304 private_botan_rsa_public_key_t *this;
305
306 this = create_empty();
307 this->key = key;
308
309 return &this->public;
310 }
311
312 /*
313 * Described in header
314 */
315 botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
316 va_list args)
317 {
318 private_botan_rsa_public_key_t *this = NULL;
319 chunk_t n, e;
320
321 n = e = chunk_empty;
322 while (TRUE)
323 {
324 switch (va_arg(args, builder_part_t))
325 {
326 case BUILD_RSA_MODULUS:
327 n = va_arg(args, chunk_t);
328 continue;
329 case BUILD_RSA_PUB_EXP:
330 e = va_arg(args, chunk_t);
331 continue;
332 case BUILD_END:
333 break;
334 default:
335 return NULL;
336 }
337 break;
338 }
339
340 if (n.ptr && e.ptr && type == KEY_RSA)
341 {
342 botan_mp_t mp_n, mp_e;
343
344 if (!chunk_to_botan_mp(n, &mp_n))
345 {
346 return NULL;
347 }
348
349 if (!chunk_to_botan_mp(e, &mp_e))
350 {
351 botan_mp_destroy(mp_n);
352 return NULL;
353 }
354
355 this = create_empty();
356
357 if (botan_pubkey_load_rsa(&this->key, mp_n, mp_e))
358 {
359 botan_mp_destroy(mp_n);
360 botan_mp_destroy(mp_e);
361 free(this);
362 return NULL;
363 }
364
365 botan_mp_destroy(mp_n);
366 botan_mp_destroy(mp_e);
367 }
368
369 return &this->public;
370 }
371
372 #endif