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 } gnutls_sec_params_entry;
39
40 static const gnutls_sec_params_entry sec_params[] = {
41 {"Insecure", GNUTLS_SEC_PARAM_INSECURE, 0, 0, 0, 0, 0},
42 {"Export", GNUTLS_SEC_PARAM_EXPORT, 42, 512, 0, 84, 0},
43 {"Very weak", GNUTLS_SEC_PARAM_VERY_WEAK, 64, 767, 0, 128, 0},
44 {"Weak", GNUTLS_SEC_PARAM_WEAK, 72, 1008, 1008, 160, 160},
45 #ifdef ENABLE_FIPS140
46 {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160},
47 {"Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1024, 1024, 192, 192},
48 {"Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 224, 224},
49 {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256},
50 #else
51 {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160}, /* ENISA-LEGACY */
52 {"Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1776, 2048, 192, 192},
53 {"Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 256, 224},
54 {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256},
55 #endif
56 {"Ultra", GNUTLS_SEC_PARAM_ULTRA, 192, 8192, 8192, 384, 384},
57 {"Future", GNUTLS_SEC_PARAM_FUTURE, 256, 15360, 15360, 512, 512},
58 {NULL, 0, 0, 0, 0, 0}
59 };
60
61 #define GNUTLS_SEC_PARAM_LOOP(b) \
62 { const gnutls_sec_params_entry *p; \
63 for(p = sec_params; p->name != NULL; p++) { b ; } }
64
65 /**
66 * gnutls_sec_param_to_pk_bits:
67 * @algo: is a public key algorithm
68 * @param: is a security parameter
69 *
70 * When generating private and public key pairs a difficult question
71 * is which size of "bits" the modulus will be in RSA and the group size
72 * in DSA. The easy answer is 1024, which is also wrong. This function
73 * will convert a human understandable security parameter to an
74 * appropriate size for the specific algorithm.
75 *
76 * Returns: The number of bits, or (0).
77 *
78 * Since: 2.12.0
79 **/
80 unsigned int
gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo,gnutls_sec_param_t param)81 gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo,
82 gnutls_sec_param_t param)
83 {
84 unsigned int ret = 0;
85
86 /* handle DSA differently */
87 GNUTLS_SEC_PARAM_LOOP(
88 if (p->sec_param == param) {
89 if (algo == GNUTLS_PK_DSA)
90 ret = p->dsa_bits;
91 else if (IS_EC(algo)||IS_GOSTEC(algo))
92 ret = p->ecc_bits;
93 else
94 ret = p->pk_bits;
95 break;
96 }
97 );
98 return ret;
99 }
100
101 /**
102 * gnutls_sec_param_to_symmetric_bits:
103 * @algo: is a public key algorithm
104 * @param: is a security parameter
105 *
106 * This function will return the number of bits that correspond to
107 * symmetric cipher strength for the given security parameter.
108 *
109 * Returns: The number of bits, or (0).
110 *
111 * Since: 3.3.0
112 **/
113 unsigned int
gnutls_sec_param_to_symmetric_bits(gnutls_sec_param_t param)114 gnutls_sec_param_to_symmetric_bits(gnutls_sec_param_t param)
115 {
116 unsigned int ret = 0;
117
118 /* handle DSA differently */
119 GNUTLS_SEC_PARAM_LOOP(
120 if (p->sec_param == param) {
121 ret = p->bits; break;
122 }
123 );
124 return ret;
125 }
126
127 /* Returns the corresponding size for subgroup bits (q),
128 * given the group bits (p).
129 */
_gnutls_pk_bits_to_subgroup_bits(unsigned int pk_bits)130 unsigned int _gnutls_pk_bits_to_subgroup_bits(unsigned int pk_bits)
131 {
132 unsigned int ret = 0;
133
134 GNUTLS_SEC_PARAM_LOOP(
135 ret = p->subgroup_bits;
136 if (p->pk_bits >= pk_bits)
137 break;
138 );
139 return ret;
140 }
141
142 /* Returns a corresponding SHA algorithm size for the
143 * public key bits given. It is based on the NIST mappings.
144 */
_gnutls_pk_bits_to_sha_hash(unsigned int pk_bits)145 gnutls_digest_algorithm_t _gnutls_pk_bits_to_sha_hash(unsigned int pk_bits)
146 {
147 GNUTLS_SEC_PARAM_LOOP(
148 if (p->pk_bits >= pk_bits) {
149 if (p->bits <= 128)
150 return GNUTLS_DIG_SHA256;
151 else if (p->bits <= 192)
152 return GNUTLS_DIG_SHA384;
153 else
154 return GNUTLS_DIG_SHA512;
155 }
156 );
157 return GNUTLS_DIG_SHA256;
158 }
159
160 /**
161 * gnutls_sec_param_get_name:
162 * @param: is a security parameter
163 *
164 * Convert a #gnutls_sec_param_t value to a string.
165 *
166 * Returns: a pointer to a string that contains the name of the
167 * specified security level, or %NULL.
168 *
169 * Since: 2.12.0
170 **/
gnutls_sec_param_get_name(gnutls_sec_param_t param)171 const char *gnutls_sec_param_get_name(gnutls_sec_param_t param)
172 {
173 const char *ret = "Unknown";
174
175 GNUTLS_SEC_PARAM_LOOP(
176 if (p->sec_param == param) {
177 ret = p->name;
178 break;
179 }
180 );
181
182 return ret;
183 }
184
185 /**
186 * gnutls_pk_bits_to_sec_param:
187 * @algo: is a public key algorithm
188 * @bits: is the number of bits
189 *
190 * This is the inverse of gnutls_sec_param_to_pk_bits(). Given an algorithm
191 * and the number of bits, it will return the security parameter. This is
192 * a rough indication.
193 *
194 * Returns: The security parameter.
195 *
196 * Since: 2.12.0
197 **/
198 gnutls_sec_param_t
gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo,unsigned int bits)199 gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo, unsigned int bits)
200 {
201 gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_INSECURE;
202
203 if (bits == 0)
204 return GNUTLS_SEC_PARAM_UNKNOWN;
205
206 if (IS_EC(algo)||IS_GOSTEC(algo)) {
207 GNUTLS_SEC_PARAM_LOOP(
208 if (p->ecc_bits > bits) {
209 break;
210 }
211 ret = p->sec_param;
212 );
213 } else {
214 GNUTLS_SEC_PARAM_LOOP(
215 if (p->pk_bits > bits) {
216 break;
217 }
218 ret = p->sec_param;
219 );
220 }
221
222 return ret;
223 }
224