Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/x509/tls_features.c
Line
Count
Source (jump to first uncovered line)
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
int gnutls_x509_tlsfeatures_init(gnutls_x509_tlsfeatures_t * f)
49
0
{
50
0
  *f = gnutls_calloc(1, sizeof(struct gnutls_x509_tlsfeatures_st));
51
0
  if (*f == NULL)
52
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
53
54
0
  return 0;
55
0
}
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
void gnutls_x509_tlsfeatures_deinit(gnutls_x509_tlsfeatures_t f)
66
0
{
67
0
  gnutls_free(f);
68
0
}
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
int gnutls_x509_tlsfeatures_get(gnutls_x509_tlsfeatures_t f, unsigned idx,
85
        unsigned int *feature)
86
0
{
87
0
  if (f == NULL) {
88
0
    gnutls_assert();
89
0
    return GNUTLS_E_INVALID_REQUEST;
90
0
  }
91
92
0
  if (idx >= f->size) {
93
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
94
0
  }
95
96
0
  *feature = f->feature[idx];
97
0
  return 0;
98
0
}
99
100
/**
101
 * gnutls_x509_crt_get_tlsfeatures:
102
 * @crt: A X.509 certificate
103
 * @features: If the function succeeds, the
104
 *   features will be stored in this variable.
105
 * @flags: zero or %GNUTLS_EXT_FLAG_APPEND
106
 * @critical: the extension status
107
 *
108
 * This function will get the X.509 TLS features
109
 * extension structure from the certificate. The
110
 * returned structure needs to be freed using
111
 * gnutls_x509_tlsfeatures_deinit().
112
 *
113
 * When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
114
 * then if the @features structure is empty this function will behave
115
 * identically as if the flag was not set. Otherwise if there are elements 
116
 * in the @features structure then they will be merged with.
117
 *
118
 * Note that @features must be initialized prior to calling this function.
119
 *
120
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
121
 *   otherwise a negative error value.
122
 *
123
 * Since: 3.5.1
124
 **/
125
int gnutls_x509_crt_get_tlsfeatures(gnutls_x509_crt_t crt,
126
            gnutls_x509_tlsfeatures_t features,
127
            unsigned int flags, unsigned int *critical)
128
0
{
129
0
  int ret;
130
0
  gnutls_datum_t der;
131
132
0
  if (crt == NULL) {
133
0
    gnutls_assert();
134
0
    return GNUTLS_E_INVALID_REQUEST;
135
0
  }
136
137
0
  if ((ret =
138
0
       _gnutls_x509_crt_get_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES,
139
0
              0, &der, critical)) < 0) {
140
0
    return ret;
141
0
  }
142
143
0
  if (der.size == 0 || der.data == NULL) {
144
0
    gnutls_assert();
145
0
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
146
0
  }
147
148
0
  ret = gnutls_x509_ext_import_tlsfeatures(&der, features, flags);
149
0
  if (ret < 0) {
150
0
    gnutls_assert();
151
0
    goto cleanup;
152
0
  }
153
154
0
  ret = 0;
155
0
 cleanup:
156
0
  gnutls_free(der.data);
157
0
  return ret;
158
0
}
159
160
/**
161
 * gnutls_x509_crt_set_tlsfeatures:
162
 * @crt: A X.509 certificate
163
 * @features: If the function succeeds, the
164
 *   features will be added to the certificate.
165
 *
166
 * This function will set the certificates
167
 * X.509 TLS extension from the given structure.
168
 *
169
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
170
 *   otherwise a negative error value.
171
 *
172
 * Since: 3.5.1
173
 **/
174
int gnutls_x509_crt_set_tlsfeatures(gnutls_x509_crt_t crt,
175
            gnutls_x509_tlsfeatures_t features)
176
0
{
177
0
  int ret;
178
0
  gnutls_datum_t der;
179
180
0
  if (crt == NULL || features == NULL) {
181
0
    gnutls_assert();
182
0
    return GNUTLS_E_INVALID_REQUEST;
183
0
  }
184
185
0
  ret = gnutls_x509_ext_export_tlsfeatures(features, &der);
186
0
  if (ret < 0) {
187
0
    gnutls_assert();
188
0
    return ret;
189
0
  }
190
191
0
  ret =
192
0
      _gnutls_x509_crt_set_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES,
193
0
             &der, 0);
194
195
0
  _gnutls_free_datum(&der);
196
197
0
  if (ret < 0) {
198
0
    gnutls_assert();
199
0
  }
200
201
0
  return ret;
202
0
}
203
204
/**
205
 * gnutls_x509_tls_features_check_crt:
206
 * @feat: a set of TLSFeatures
207
 * @cert: the certificate to be checked
208
 *
209
 * This function will check the provided certificate against the TLSFeatures
210
 * set in @feat using the RFC7633 p.4.2.2 rules. It will check whether the certificate
211
 * contains the features in @feat or a superset.
212
 *
213
 * Returns: non-zero if the provided certificate complies, and zero otherwise.
214
 *
215
 * Since: 3.5.1
216
 **/
217
unsigned gnutls_x509_tlsfeatures_check_crt(gnutls_x509_tlsfeatures_t feat,
218
             gnutls_x509_crt_t cert)
219
0
{
220
0
  int ret;
221
0
  gnutls_x509_tlsfeatures_t cfeat;
222
0
  unsigned i, j, uret, found;
223
224
0
  if (feat->size == 0)
225
0
    return 1; /* shortcut; no constraints to check */
226
227
0
  ret = gnutls_x509_tlsfeatures_init(&cfeat);
228
0
  if (ret < 0)
229
0
    return gnutls_assert_val(0);
230
231
0
  ret = gnutls_x509_crt_get_tlsfeatures(cert, cfeat, 0, NULL);
232
0
  if (ret < 0) {
233
0
    gnutls_assert();
234
0
    uret = 0;
235
0
    goto cleanup;
236
0
  }
237
238
  /* if cert's features cannot be a superset */
239
0
  if (feat->size > cfeat->size) {
240
0
    _gnutls_debug_log
241
0
        ("certificate has %u, while issuer has %u tlsfeatures\n",
242
0
         cfeat->size, feat->size);
243
0
    gnutls_assert();
244
0
    uret = 0;
245
0
    goto cleanup;
246
0
  }
247
248
0
  for (i = 0; i < feat->size; i++) {
249
0
    found = 0;
250
0
    for (j = 0; j < cfeat->size; j++) {
251
0
      if (feat->feature[i] == cfeat->feature[j]) {
252
0
        found = 1;
253
0
        break;
254
0
      }
255
0
    }
256
257
0
    if (found == 0) {
258
0
      _gnutls_debug_log("feature %d was not found in cert\n",
259
0
            (int)feat->feature[i]);
260
0
      uret = 0;
261
0
      goto cleanup;
262
0
    }
263
0
  }
264
265
0
  uret = 1;
266
0
 cleanup:
267
0
  gnutls_x509_tlsfeatures_deinit(cfeat);
268
0
  return uret;
269
0
}