/src/gnutls/lib/algorithms/secparams.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2011-2012 Free Software Foundation, Inc. |
3 | | * |
4 | | * Author: Nikos Mavrogiannopoulos |
5 | | * |
6 | | * This file is part of GnuTLS. |
7 | | * |
8 | | * The GnuTLS is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public License |
10 | | * as published by the Free Software Foundation; either version 2.1 of |
11 | | * the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, but |
14 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
20 | | * |
21 | | */ |
22 | | |
23 | | #include "gnutls_int.h" |
24 | | #include "algorithms.h" |
25 | | #include "errors.h" |
26 | | #include "x509/common.h" |
27 | | |
28 | | typedef struct { |
29 | | const char *name; |
30 | | gnutls_sec_param_t sec_param; |
31 | | unsigned int bits; /* security level */ |
32 | | unsigned int pk_bits; /* DH, RSA, SRP */ |
33 | | unsigned int dsa_bits; /* bits for DSA. Handled differently since |
34 | | * choice of key size in DSA is political. |
35 | | */ |
36 | | unsigned int subgroup_bits; /* subgroup bits */ |
37 | | unsigned int ecc_bits; /* bits for ECC keys */ |
38 | | unsigned int ml_dsa_bits; |
39 | | } gnutls_sec_params_entry; |
40 | | |
41 | | static const gnutls_sec_params_entry sec_params[] = { |
42 | | { "Insecure", GNUTLS_SEC_PARAM_INSECURE, 0, 0, 0, 0, 0, 0 }, |
43 | | { "Export", GNUTLS_SEC_PARAM_EXPORT, 42, 512, 0, 84, 0, 0 }, |
44 | | { "Very weak", GNUTLS_SEC_PARAM_VERY_WEAK, 64, 767, 0, 128, 0, 0 }, |
45 | | { "Weak", GNUTLS_SEC_PARAM_WEAK, 72, 1008, 1008, 160, 160, 0 }, |
46 | | #ifdef ENABLE_FIPS140 |
47 | | { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160, 0 }, |
48 | | { |
49 | | "Legacy", |
50 | | GNUTLS_SEC_PARAM_LEGACY, |
51 | | 96, |
52 | | 1024, |
53 | | 1024, |
54 | | 192, |
55 | | 192, |
56 | | 0, |
57 | | }, |
58 | | { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 224, 224, 0 }, |
59 | | { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256, 0 }, |
60 | | #else |
61 | | { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160, |
62 | | 0 }, /* ENISA-LEGACY */ |
63 | | { "Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1776, 2048, 192, 192, 0 }, |
64 | | { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 256, 224, 0 }, |
65 | | { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256, 0 }, |
66 | | #endif |
67 | | { "Ultra", GNUTLS_SEC_PARAM_ULTRA, 192, 8192, 8192, 384, 384, |
68 | | MLDSA65_PUBKEY_SIZE }, |
69 | | { "Future", GNUTLS_SEC_PARAM_FUTURE, 256, 15360, 15360, 512, 512, |
70 | | MLDSA87_PUBKEY_SIZE }, |
71 | | { NULL, 0, 0, 0, 0, 0, 0, 0 } |
72 | | }; |
73 | | |
74 | | /** |
75 | | * gnutls_sec_param_to_pk_bits: |
76 | | * @algo: is a public key algorithm |
77 | | * @param: is a security parameter |
78 | | * |
79 | | * When generating private and public key pairs a difficult question |
80 | | * is which size of "bits" the modulus will be in RSA and the group size |
81 | | * in DSA. The easy answer is 1024, which is also wrong. This function |
82 | | * will convert a human understandable security parameter to an |
83 | | * appropriate size for the specific algorithm. |
84 | | * |
85 | | * Returns: The number of bits, or (0). |
86 | | * |
87 | | * Since: 2.12.0 |
88 | | **/ |
89 | | unsigned int gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo, |
90 | | gnutls_sec_param_t param) |
91 | 0 | { |
92 | 0 | unsigned int ret = 0; |
93 | 0 | const gnutls_sec_params_entry *p; |
94 | | |
95 | | /* handle DSA differently */ |
96 | 0 | for (p = sec_params; p->name; p++) { |
97 | 0 | if (p->sec_param == param) { |
98 | 0 | if (algo == GNUTLS_PK_DSA) |
99 | 0 | ret = p->dsa_bits; |
100 | 0 | else if (IS_EC(algo) || IS_GOSTEC(algo)) |
101 | 0 | ret = p->ecc_bits; |
102 | 0 | else if (IS_ML_DSA(algo)) |
103 | 0 | ret = p->ml_dsa_bits; |
104 | 0 | else |
105 | 0 | ret = p->pk_bits; |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | } |
109 | |
|
110 | 0 | return ret; |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * gnutls_sec_param_to_symmetric_bits: |
115 | | * @algo: is a public key algorithm |
116 | | * @param: is a security parameter |
117 | | * |
118 | | * This function will return the number of bits that correspond to |
119 | | * symmetric cipher strength for the given security parameter. |
120 | | * |
121 | | * Returns: The number of bits, or (0). |
122 | | * |
123 | | * Since: 3.3.0 |
124 | | **/ |
125 | | unsigned int gnutls_sec_param_to_symmetric_bits(gnutls_sec_param_t param) |
126 | 0 | { |
127 | 0 | unsigned int ret = 0; |
128 | 0 | const gnutls_sec_params_entry *p; |
129 | | |
130 | | /* handle DSA differently */ |
131 | 0 | for (p = sec_params; p->name; p++) { |
132 | 0 | if (p->sec_param == param) { |
133 | 0 | ret = p->bits; |
134 | 0 | break; |
135 | 0 | } |
136 | 0 | } |
137 | |
|
138 | 0 | return ret; |
139 | 0 | } |
140 | | |
141 | | /* Returns the corresponding size for subgroup bits (q), |
142 | | * given the group bits (p). |
143 | | */ |
144 | | unsigned int _gnutls_pk_bits_to_subgroup_bits(unsigned int pk_bits) |
145 | 0 | { |
146 | 0 | unsigned int ret = 0; |
147 | 0 | const gnutls_sec_params_entry *p; |
148 | |
|
149 | 0 | for (p = sec_params; p->name; p++) { |
150 | 0 | ret = p->subgroup_bits; |
151 | 0 | if (p->pk_bits >= pk_bits) |
152 | 0 | break; |
153 | 0 | } |
154 | |
|
155 | 0 | return ret; |
156 | 0 | } |
157 | | |
158 | | /* Returns a corresponding SHA algorithm size for the |
159 | | * public key bits given. It is based on the NIST mappings. |
160 | | */ |
161 | | gnutls_digest_algorithm_t _gnutls_pk_bits_to_sha_hash(unsigned int pk_bits) |
162 | 0 | { |
163 | 0 | const gnutls_sec_params_entry *p; |
164 | |
|
165 | 0 | for (p = sec_params; p->name; p++) { |
166 | 0 | if (p->pk_bits >= pk_bits) { |
167 | 0 | if (p->bits <= 128) |
168 | 0 | return GNUTLS_DIG_SHA256; |
169 | 0 | else if (p->bits <= 192) |
170 | 0 | return GNUTLS_DIG_SHA384; |
171 | 0 | else |
172 | 0 | return GNUTLS_DIG_SHA512; |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | 0 | return GNUTLS_DIG_SHA256; |
177 | 0 | } |
178 | | |
179 | | /** |
180 | | * gnutls_sec_param_get_name: |
181 | | * @param: is a security parameter |
182 | | * |
183 | | * Convert a #gnutls_sec_param_t value to a string. |
184 | | * |
185 | | * Returns: a pointer to a string that contains the name of the |
186 | | * specified security level, or %NULL. |
187 | | * |
188 | | * Since: 2.12.0 |
189 | | **/ |
190 | | const char *gnutls_sec_param_get_name(gnutls_sec_param_t param) |
191 | 0 | { |
192 | 0 | const char *ret = "Unknown"; |
193 | 0 | const gnutls_sec_params_entry *p; |
194 | |
|
195 | 0 | for (p = sec_params; p->name; p++) { |
196 | 0 | if (p->sec_param == param) { |
197 | 0 | ret = p->name; |
198 | 0 | break; |
199 | 0 | } |
200 | 0 | } |
201 | |
|
202 | 0 | return ret; |
203 | 0 | } |
204 | | |
205 | | /** |
206 | | * gnutls_pk_bits_to_sec_param: |
207 | | * @algo: is a public key algorithm |
208 | | * @bits: is the number of bits |
209 | | * |
210 | | * This is the inverse of gnutls_sec_param_to_pk_bits(). Given an algorithm |
211 | | * and the number of bits, it will return the security parameter. This is |
212 | | * a rough indication. |
213 | | * |
214 | | * Returns: The security parameter. |
215 | | * |
216 | | * Since: 2.12.0 |
217 | | **/ |
218 | | gnutls_sec_param_t gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo, |
219 | | unsigned int bits) |
220 | 0 | { |
221 | 0 | gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_INSECURE; |
222 | 0 | const gnutls_sec_params_entry *p; |
223 | |
|
224 | 0 | if (bits == 0) |
225 | 0 | return GNUTLS_SEC_PARAM_UNKNOWN; |
226 | | |
227 | 0 | if (IS_EC(algo) || IS_GOSTEC(algo)) { |
228 | 0 | for (p = sec_params; p->name; p++) { |
229 | 0 | if (p->ecc_bits > bits) |
230 | 0 | break; |
231 | 0 | ret = p->sec_param; |
232 | 0 | } |
233 | 0 | } else if (IS_ML_DSA(algo)) { |
234 | 0 | for (p = sec_params; p->name; p++) { |
235 | 0 | if (p->ml_dsa_bits > bits) |
236 | 0 | break; |
237 | 0 | ret = p->sec_param; |
238 | 0 | } |
239 | 0 | } else { |
240 | 0 | for (p = sec_params; p->name; p++) { |
241 | 0 | if (p->pk_bits > bits) |
242 | 0 | break; |
243 | 0 | ret = p->sec_param; |
244 | 0 | } |
245 | 0 | } |
246 | |
|
247 | 0 | return ret; |
248 | 0 | } |