Line data Source code
1 : /*
2 : * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3 : *
4 : * Authors: Nikos Mavrogiannopoulos, Simon Josefsson, Howard Chu
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 <datum.h>
25 : #include <global.h>
26 : #include "errors.h"
27 : #include <common.h>
28 : #include <gnutls/x509-ext.h>
29 : #include <x509.h>
30 : #include <x509_b64.h>
31 : #include <x509_int.h>
32 : #include <libtasn1.h>
33 : #include <pk.h>
34 : #include <pkcs11_int.h>
35 : #include "urls.h"
36 :
37 : /**
38 : * gnutls_x509_tlsfeatures_init:
39 : * @f: The TLS features
40 : *
41 : * This function will initialize a X.509 TLS features extension structure
42 : *
43 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
44 : * otherwise a negative error value.
45 : *
46 : * Since: 3.5.1
47 : **/
48 1879 : int gnutls_x509_tlsfeatures_init(gnutls_x509_tlsfeatures_t *f)
49 : {
50 1879 : *f = gnutls_calloc(1, sizeof(struct gnutls_x509_tlsfeatures_st));
51 1879 : if (*f == NULL)
52 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
53 :
54 : return 0;
55 : }
56 :
57 : /**
58 : * gnutls_x509_tlsfeatures_deinit:
59 : * @f: The TLS features
60 : *
61 : * This function will deinitialize a X.509 TLS features extension structure
62 : *
63 : * Since: 3.5.1
64 : **/
65 1879 : void gnutls_x509_tlsfeatures_deinit(gnutls_x509_tlsfeatures_t f)
66 : {
67 1879 : gnutls_free(f);
68 1879 : }
69 :
70 : /**
71 : * gnutls_x509_tlsfeatures_get:
72 : * @f: The TLS features
73 : * @idx: The index of the feature to get
74 : * @feature: If the function succeeds, the feature will be stored in this variable
75 : *
76 : * This function will get a feature from the X.509 TLS features
77 : * extension structure.
78 : *
79 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
80 : * otherwise a negative error value.
81 : *
82 : * Since: 3.5.1
83 : **/
84 40 : int gnutls_x509_tlsfeatures_get(gnutls_x509_tlsfeatures_t f, unsigned idx, unsigned int *feature)
85 : {
86 40 : if (f == NULL) {
87 0 : gnutls_assert();
88 0 : return GNUTLS_E_INVALID_REQUEST;
89 : }
90 :
91 40 : if (idx >= f->size) {
92 12 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
93 : }
94 :
95 29 : *feature = f->feature[idx];
96 29 : return 0;
97 : }
98 :
99 : /**
100 : * gnutls_x509_crt_get_tlsfeatures:
101 : * @crt: A X.509 certificate
102 : * @features: If the function succeeds, the
103 : * features will be stored in this variable.
104 : * @flags: zero or %GNUTLS_EXT_FLAG_APPEND
105 : * @critical: the extension status
106 : *
107 : * This function will get the X.509 TLS features
108 : * extension structure from the certificate. The
109 : * returned structure needs to be freed using
110 : * gnutls_x509_tlsfeatures_deinit().
111 : *
112 : * When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
113 : * then if the @features structure is empty this function will behave
114 : * identically as if the flag was not set. Otherwise if there are elements
115 : * in the @features structure then they will be merged with.
116 : *
117 : * Note that @features must be initialized prior to calling this function.
118 : *
119 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
120 : * otherwise a negative error value.
121 : *
122 : * Since: 3.5.1
123 : **/
124 1762 : int gnutls_x509_crt_get_tlsfeatures(gnutls_x509_crt_t crt,
125 : gnutls_x509_tlsfeatures_t features,
126 : unsigned int flags,
127 : unsigned int *critical)
128 : {
129 1762 : int ret;
130 1762 : gnutls_datum_t der;
131 :
132 1762 : if (crt == NULL) {
133 0 : gnutls_assert();
134 0 : return GNUTLS_E_INVALID_REQUEST;
135 : }
136 :
137 3524 : if ((ret =
138 1762 : _gnutls_x509_crt_get_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES, 0,
139 : &der, critical)) < 0)
140 : {
141 : return ret;
142 : }
143 :
144 61 : if (der.size == 0 || der.data == NULL) {
145 0 : gnutls_assert();
146 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
147 : }
148 :
149 61 : ret = gnutls_x509_ext_import_tlsfeatures(&der, features, flags);
150 61 : if (ret < 0) {
151 0 : gnutls_assert();
152 0 : goto cleanup;
153 : }
154 :
155 : ret = 0;
156 61 : cleanup:
157 61 : gnutls_free(der.data);
158 61 : return ret;
159 : }
160 :
161 : /**
162 : * gnutls_x509_crt_set_tlsfeatures:
163 : * @crt: A X.509 certificate
164 : * @features: If the function succeeds, the
165 : * features will be added to the certificate.
166 : *
167 : * This function will set the certificates
168 : * X.509 TLS extension from the given structure.
169 : *
170 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
171 : * otherwise a negative error value.
172 : *
173 : * Since: 3.5.1
174 : **/
175 2 : int gnutls_x509_crt_set_tlsfeatures(gnutls_x509_crt_t crt,
176 : gnutls_x509_tlsfeatures_t features)
177 : {
178 2 : int ret;
179 2 : gnutls_datum_t der;
180 :
181 2 : if (crt == NULL || features == NULL) {
182 0 : gnutls_assert();
183 0 : return GNUTLS_E_INVALID_REQUEST;
184 : }
185 :
186 2 : ret = gnutls_x509_ext_export_tlsfeatures(features, &der);
187 2 : if (ret < 0) {
188 0 : gnutls_assert();
189 0 : return ret;
190 : }
191 :
192 2 : ret = _gnutls_x509_crt_set_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES, &der, 0);
193 :
194 2 : _gnutls_free_datum(&der);
195 :
196 2 : if (ret < 0) {
197 0 : gnutls_assert();
198 : }
199 :
200 : return ret;
201 : }
202 :
203 : /**
204 : * gnutls_x509_tls_features_check_crt:
205 : * @feat: a set of TLSFeatures
206 : * @cert: the certificate to be checked
207 : *
208 : * This function will check the provided certificate against the TLSFeatures
209 : * set in @feat using the RFC7633 p.4.2.2 rules. It will check whether the certificate
210 : * contains the features in @feat or a superset.
211 : *
212 : * Returns: non-zero if the provided certificate complies, and zero otherwise.
213 : *
214 : * Since: 3.5.1
215 : **/
216 1143 : unsigned gnutls_x509_tlsfeatures_check_crt(gnutls_x509_tlsfeatures_t feat,
217 : gnutls_x509_crt_t cert)
218 : {
219 1143 : int ret;
220 1143 : gnutls_x509_tlsfeatures_t cfeat;
221 1143 : unsigned i, j, uret, found;
222 :
223 1143 : if (feat->size == 0)
224 : return 1; /* shortcut; no constraints to check */
225 :
226 31 : ret = gnutls_x509_tlsfeatures_init(&cfeat);
227 31 : if (ret < 0)
228 0 : return gnutls_assert_val(0);
229 :
230 31 : ret = gnutls_x509_crt_get_tlsfeatures(cert, cfeat, 0, NULL);
231 31 : if (ret < 0) {
232 6 : gnutls_assert();
233 6 : uret = 0;
234 6 : goto cleanup;
235 : }
236 :
237 : /* if cert's features cannot be a superset */
238 25 : if (feat->size > cfeat->size) {
239 8 : _gnutls_debug_log("certificate has %u, while issuer has %u tlsfeatures\n", cfeat->size, feat->size);
240 8 : gnutls_assert();
241 8 : uret = 0;
242 8 : goto cleanup;
243 : }
244 :
245 78 : for (i=0;i<feat->size;i++) {
246 165 : found = 0;
247 165 : for (j=0;j<cfeat->size;j++) {
248 164 : if (feat->feature[i] == cfeat->feature[j]) {
249 : found = 1;
250 : break;
251 : }
252 : }
253 :
254 62 : if (found == 0) {
255 1 : _gnutls_debug_log("feature %d was not found in cert\n", (int)feat->feature[i]);
256 1 : uret = 0;
257 1 : goto cleanup;
258 : }
259 : }
260 :
261 : uret = 1;
262 31 : cleanup:
263 31 : gnutls_x509_tlsfeatures_deinit(cfeat);
264 31 : return uret;
265 : }
|