charon-nm: Set DPD/close action to restart and enable indefinite keying tries
[strongswan.git] / src / libstrongswan / credentials / keys / signature_params.c
1 /*
2 * Copyright (C) 2017 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "signature_params.h"
17
18 #include <asn1/oid.h>
19 #include <asn1/asn1_parser.h>
20
21 /*
22 * Described in header
23 */
24 bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits)
25 {
26 size_t hash_len;
27
28 if (params->salt_len < 0)
29 {
30 hash_len = hasher_hash_size(params->hash);
31 if (!hash_len)
32 {
33 return FALSE;
34 }
35
36 switch (params->salt_len)
37 {
38 case RSA_PSS_SALT_LEN_DEFAULT:
39 params->salt_len = hash_len;
40 break;
41 case RSA_PSS_SALT_LEN_MAX:
42 if (modbits)
43 {
44 /* emBits = modBits - 1 */
45 modbits -= 1;
46 /* emLen = ceil(emBits/8) */
47 modbits = (modbits+7) / BITS_PER_BYTE;
48 /* account for 0x01 separator in DB, 0xbc trailing byte */
49 params->salt_len = max(0, (ssize_t)(modbits - hash_len - 2));
50 break;
51 }
52 return FALSE;
53 default:
54 return FALSE;
55 }
56 }
57 return TRUE;
58 }
59
60 /**
61 * Compare two signature schemes and their parameters
62 */
63 static bool compare_params(signature_params_t *a, signature_params_t *b,
64 bool strict)
65 {
66 if (!a && !b)
67 {
68 return TRUE;
69 }
70 if (!a || !b)
71 {
72 return FALSE;
73 }
74 if (a->scheme != b->scheme)
75 {
76 return FALSE;
77 }
78 if (!a->params && !b->params)
79 {
80 return TRUE;
81 }
82 if (a->params && b->params)
83 {
84 switch (a->scheme)
85 {
86 case SIGN_RSA_EMSA_PSS:
87 {
88 rsa_pss_params_t *pss_a = a->params, *pss_b = b->params;
89
90 return pss_a->hash == pss_b->hash &&
91 pss_a->mgf1_hash == pss_b->mgf1_hash &&
92 (!strict || pss_a->salt_len == pss_b->salt_len);
93 }
94 default:
95 break;
96 }
97 }
98 return FALSE;
99 }
100
101 /*
102 * Described in header
103 */
104 bool signature_params_equal(signature_params_t *a, signature_params_t *b)
105 {
106 return compare_params(a, b, TRUE);
107 }
108
109 /*
110 * Described in header
111 */
112 bool signature_params_comply(signature_params_t *c, signature_params_t *s)
113 { /* the salt is variable, so it does not necessarily have to be the same */
114 return compare_params(c, s, FALSE);
115 }
116
117 /*
118 * Described in header
119 */
120 signature_params_t *signature_params_clone(signature_params_t *this)
121 {
122 signature_params_t *clone;
123
124 if (!this)
125 {
126 return NULL;
127 }
128
129 INIT(clone,
130 .scheme = this->scheme,
131 );
132 if (this->params)
133 {
134 switch (this->scheme)
135 {
136 case SIGN_RSA_EMSA_PSS:
137 {
138 rsa_pss_params_t *pss, *pss_clone;
139
140 pss = this->params;
141 INIT(pss_clone,
142 .hash = pss->hash,
143 .mgf1_hash = pss->mgf1_hash,
144 .salt_len = pss->salt_len,
145 /* ignore salt as only used for unit tests */
146 );
147 clone->params = pss_clone;
148 break;
149 }
150 default:
151 break;
152 }
153 }
154 return clone;
155 }
156
157 /*
158 * Described in header
159 */
160 void signature_params_destroy(signature_params_t *this)
161 {
162 if (this)
163 {
164 free(this->params);
165 free(this);
166 }
167 }
168
169 /*
170 * Described in header
171 */
172 void signature_params_clear(signature_params_t *this)
173 {
174 if (this)
175 {
176 free(this->params);
177 this->params = NULL;
178 this->scheme = SIGN_UNKNOWN;
179 }
180 }
181
182 /*
183 * Described in header
184 */
185 bool signature_params_parse(chunk_t asn1, int level0,
186 signature_params_t *params)
187 {
188 chunk_t parameters = chunk_empty;
189 int oid;
190
191 oid = asn1_parse_algorithmIdentifier(asn1, level0, &parameters);
192 params->scheme = signature_scheme_from_oid(oid);
193 switch (params->scheme)
194 {
195 case SIGN_UNKNOWN:
196 return FALSE;
197 case SIGN_RSA_EMSA_PSS:
198 {
199 rsa_pss_params_t *pss = malloc_thing(rsa_pss_params_t);
200
201 if (!rsa_pss_params_parse(parameters, level0+1, pss))
202 {
203 DBG1(DBG_IKE, "failed parsing RSASSA-PSS parameters");
204 free(pss);
205 return FALSE;
206 }
207 params->params = pss;
208 break;
209 }
210 default:
211 params->params = NULL;
212 break;
213 }
214 return TRUE;
215 }
216
217 /*
218 * Described in header
219 */
220 bool signature_params_build(signature_params_t *params, chunk_t *asn1)
221 {
222 chunk_t parameters = chunk_empty;
223 int oid;
224
225 oid = signature_scheme_to_oid(params->scheme);
226 if (oid == OID_UNKNOWN)
227 {
228 return FALSE;
229 }
230 if (params->scheme == SIGN_RSA_EMSA_PSS &&
231 !rsa_pss_params_build(params->params, &parameters))
232 {
233 return FALSE;
234 }
235 if (parameters.len)
236 {
237 *asn1 = asn1_algorithmIdentifier_params(oid, parameters);
238 }
239 else
240 {
241 *asn1 = asn1_algorithmIdentifier(oid);
242 }
243 return TRUE;
244 }
245
246 /**
247 * ASN.1 definition of RSASSA-PSS-params
248 */
249 static const asn1Object_t RSASSAPSSParamsObjects[] = {
250 { 0, "RSASSA-PSS-params", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
251 { 1, "DEFAULT SHA-1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 1 */
252 { 2, "hashAlgorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
253 { 1, "DEFAULT MGF1SHA1", ASN1_CONTEXT_C_1, ASN1_DEF }, /* 3 */
254 { 2, "maskGenAlgorithm",ASN1_EOC, ASN1_RAW }, /* 4 */
255 { 1, "DEFAULT 20", ASN1_CONTEXT_C_2, ASN1_DEF }, /* 5 */
256 { 2, "saltLength", ASN1_INTEGER, ASN1_BODY }, /* 6 */
257 { 1, "DEFAULT 1", ASN1_CONTEXT_C_3, ASN1_DEF }, /* 7 */
258 { 2, "trailerField", ASN1_INTEGER, ASN1_BODY }, /* 8 */
259 { 0, "exit", ASN1_EOC, ASN1_EXIT }
260 };
261 #define RSASSA_PSS_PARAMS_HASH_ALG 2
262 #define RSASSA_PSS_PARAMS_MGF_ALG 4
263 #define RSASSA_PSS_PARAMS_SALT_LEN 6
264 #define RSASSA_PSS_PARAMS_TRAILER 8
265
266 /*
267 * Described in header
268 */
269 bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params)
270 {
271 asn1_parser_t *parser;
272 chunk_t object;
273 int objectID, alg;
274 bool success = FALSE;
275
276 params->hash = HASH_SHA1;
277 params->mgf1_hash = HASH_SHA1;
278 params->salt_len = HASH_SIZE_SHA1;
279
280 parser = asn1_parser_create(RSASSAPSSParamsObjects, asn1);
281 parser->set_top_level(parser, level0);
282
283 while (parser->iterate(parser, &objectID, &object))
284 {
285 u_int level = parser->get_level(parser)+1;
286
287 switch (objectID)
288 {
289 case RSASSA_PSS_PARAMS_HASH_ALG:
290 if (object.len)
291 {
292 alg = asn1_parse_algorithmIdentifier(object, level, NULL);
293 params->hash = hasher_algorithm_from_oid(alg);
294 if (params->hash == HASH_UNKNOWN)
295 {
296 goto end;
297 }
298 }
299 break;
300 case RSASSA_PSS_PARAMS_MGF_ALG:
301 if (object.len)
302 {
303 chunk_t hash = chunk_empty;
304
305 alg = asn1_parse_algorithmIdentifier(object, level, &hash);
306 if (alg != OID_MGF1)
307 {
308 goto end;
309 }
310 if (!hash.len)
311 {
312 goto end;
313 }
314 alg = asn1_parse_algorithmIdentifier(hash, level+1, NULL);
315 params->mgf1_hash = hasher_algorithm_from_oid(alg);
316 if (params->mgf1_hash == HASH_UNKNOWN)
317 {
318 goto end;
319 }
320 }
321 break;
322 case RSASSA_PSS_PARAMS_SALT_LEN:
323 if (object.len)
324 {
325 params->salt_len = (size_t)asn1_parse_integer_uint64(object);
326 }
327 break;
328 case RSASSA_PSS_PARAMS_TRAILER:
329 if (object.len && (object.len != 1 || *object.ptr != 1))
330 {
331 goto end;
332 }
333 break;
334 default:
335 break;
336 }
337 }
338 success = parser->success(parser);
339
340 end:
341 parser->destroy(parser);
342 return success;
343 }
344
345 /*
346 * Described in header
347 */
348 bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
349 {
350 chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
351 int alg;
352
353 if (params->hash != HASH_SHA1)
354 { /* with SHA-1 we MUST omit the field */
355 alg = hasher_algorithm_to_oid(params->hash);
356 if (alg == OID_UNKNOWN)
357 {
358 return FALSE;
359 }
360 hash = asn1_algorithmIdentifier(alg);
361 }
362 if (params->mgf1_hash != HASH_SHA1)
363 { /* with MGF1-SHA1 we MUST omit the field */
364 alg = hasher_algorithm_to_oid(params->mgf1_hash);
365 if (alg == OID_UNKNOWN)
366 {
367 chunk_free(&hash);
368 return FALSE;
369 }
370 mgf = asn1_algorithmIdentifier_params(OID_MGF1,
371 asn1_algorithmIdentifier(alg));
372 }
373 if (params->salt_len < 0)
374 {
375 chunk_free(&hash);
376 chunk_free(&mgf);
377 return FALSE;
378 }
379 else if (params->salt_len != HASH_SIZE_SHA1)
380 {
381 slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len));
382 }
383 *asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
384 hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
385 mgf.len ? asn1_wrap(ASN1_CONTEXT_C_1, "m", mgf) : chunk_empty,
386 slen.len ? asn1_wrap(ASN1_CONTEXT_C_2, "m", slen) : chunk_empty);
387 return TRUE;
388 }