1 /*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #include <gnutls/gnutls.h>
18 
19 #include "libdnssec/error.h"
20 #include "libdnssec/key.h"
21 #include "libdnssec/key/algorithm.h"
22 #include "libdnssec/shared/shared.h"
23 
24 /* -- internal ------------------------------------------------------------- */
25 
26 struct limits {
27 	unsigned min;
28 	unsigned max;
29 	unsigned def;
30 	bool (*validate)(unsigned bits);
31 };
32 
get_limits(dnssec_key_algorithm_t algorithm)33 static const struct limits *get_limits(dnssec_key_algorithm_t algorithm)
34 {
35 	static const struct limits RSA = {
36 		.min = 1024,
37 		.max = 4096,
38 		.def = 2048,
39 	};
40 
41 	static const struct limits EC256 = {
42 		.min = 256,
43 		.max = 256,
44 		.def = 256,
45 	};
46 
47 	static const struct limits EC384 = {
48 		.min = 384,
49 		.max = 384,
50 		.def = 384,
51 	};
52 
53 	static const struct limits ED25519 = {
54 		.min = 256,
55 		.max = 256,
56 		.def = 256,
57 	};
58 
59 	static const struct limits ED448 = {
60 		.min = 456,
61 		.max = 456,
62 		.def = 456,
63 	};
64 
65 	switch (algorithm) {
66 	case DNSSEC_KEY_ALGORITHM_RSA_SHA1:
67 	case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3:
68 	case DNSSEC_KEY_ALGORITHM_RSA_SHA256:
69 	case DNSSEC_KEY_ALGORITHM_RSA_SHA512:
70 		return &RSA;
71 	case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256:
72 		return &EC256;
73 	case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
74 		return &EC384;
75 	case DNSSEC_KEY_ALGORITHM_ED25519:
76 		return &ED25519;
77 	case DNSSEC_KEY_ALGORITHM_ED448:
78 		return &ED448;
79 	default:
80 		return NULL;
81 	}
82 }
83 
84 /* -- internal API --------------------------------------------------------- */
85 
algorithm_to_gnutls(dnssec_key_algorithm_t dnssec)86 gnutls_pk_algorithm_t algorithm_to_gnutls(dnssec_key_algorithm_t dnssec)
87 {
88 	switch (dnssec) {
89 	case DNSSEC_KEY_ALGORITHM_RSA_SHA1:
90 	case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3:
91 	case DNSSEC_KEY_ALGORITHM_RSA_SHA256:
92 	case DNSSEC_KEY_ALGORITHM_RSA_SHA512:
93 		return GNUTLS_PK_RSA;
94 	case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256:
95 	case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
96 		return GNUTLS_PK_EC;
97 #ifdef HAVE_ED25519
98 	case DNSSEC_KEY_ALGORITHM_ED25519:
99 		return GNUTLS_PK_EDDSA_ED25519;
100 #endif
101 #ifdef HAVE_ED448
102 	case DNSSEC_KEY_ALGORITHM_ED448:
103 		return GNUTLS_PK_EDDSA_ED448;
104 #endif
105 	default:
106 		return GNUTLS_PK_UNKNOWN;
107 	}
108 }
109 
110 /* -- public API ----------------------------------------------------------- */
111 
112 _public_
dnssec_algorithm_reproducible(dnssec_key_algorithm_t algorithm,bool enabled)113 bool dnssec_algorithm_reproducible(dnssec_key_algorithm_t algorithm, bool enabled)
114 {
115 	(void)enabled;
116 	switch (algorithm) {
117 	case DNSSEC_KEY_ALGORITHM_ED25519:
118 	case DNSSEC_KEY_ALGORITHM_ED448:
119 		return true; // those are always reproducible
120 	case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256:
121 	case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
122 #ifdef HAVE_GLNUTLS_REPRODUCIBLE
123 		return enabled; // Reproducible only if GnuTLS supports && enabled
124 #else
125 		return false;
126 #endif
127 	default:
128 		return false;
129 	}
130 }
131 
132 _public_
dnssec_algorithm_key_size_range(dnssec_key_algorithm_t algorithm,unsigned * min_ptr,unsigned * max_ptr)133 int dnssec_algorithm_key_size_range(dnssec_key_algorithm_t algorithm,
134 				    unsigned *min_ptr, unsigned *max_ptr)
135 {
136 	if (!min_ptr && !max_ptr) {
137 		return DNSSEC_EINVAL;
138 	}
139 
140 	const struct limits *limits = get_limits(algorithm);
141 	if (!limits) {
142 		return DNSSEC_INVALID_KEY_ALGORITHM;
143 	}
144 
145 	if (min_ptr) {
146 		*min_ptr = limits->min;
147 	}
148 	if (max_ptr) {
149 		*max_ptr = limits->max;
150 	}
151 
152 	return DNSSEC_EOK;
153 }
154 
155 _public_
dnssec_algorithm_key_size_check(dnssec_key_algorithm_t algorithm,unsigned bits)156 bool dnssec_algorithm_key_size_check(dnssec_key_algorithm_t algorithm,
157 				     unsigned bits)
158 {
159 	const struct limits *limits = get_limits(algorithm);
160 	if (!limits) {
161 		return false;
162 	}
163 
164 	if (bits < limits->min || bits > limits->max) {
165 		return false;
166 	}
167 
168 	if (limits->validate && !limits->validate(bits)) {
169 		return false;
170 	}
171 
172 	return true;
173 }
174 
175 _public_
dnssec_algorithm_key_size_default(dnssec_key_algorithm_t algorithm)176 int dnssec_algorithm_key_size_default(dnssec_key_algorithm_t algorithm)
177 {
178 	const struct limits *limits = get_limits(algorithm);
179 	return limits ? limits->def : 0;
180 }
181