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