Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / lib / ext_cert_type.c
blob5a03878ffbe44a323c411870f628705ed07f61e9
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2010 Free Software Foundation,
3 * Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 /* This file contains the code the Certificate Type TLS extension.
27 * This extension is currently gnutls specific.
30 #include "gnutls_int.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_num.h"
33 #include "ext_cert_type.h"
34 #include <gnutls_state.h>
35 #include <gnutls_num.h>
37 /* Maps record size to numbers according to the
38 * extensions draft.
40 inline static int _gnutls_num2cert_type (int num);
41 inline static int _gnutls_cert_type2num (int record_size);
42 static int _gnutls_cert_type_recv_params (gnutls_session_t session,
43 const opaque * data,
44 size_t data_size);
45 static int _gnutls_cert_type_send_params (gnutls_session_t session,
46 gnutls_buffer_st * extdata);
48 extension_entry_st ext_mod_cert_type = {
49 .name = "CERT TYPE",
50 .type = GNUTLS_EXTENSION_CERT_TYPE,
51 .parse_type = GNUTLS_EXT_TLS,
53 .recv_func = _gnutls_cert_type_recv_params,
54 .send_func = _gnutls_cert_type_send_params,
55 .pack_func = NULL,
56 .unpack_func = NULL,
57 .deinit_func = NULL
60 /*
61 * In case of a server: if a CERT_TYPE extension type is received then it stores
62 * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
63 * to access it.
65 * In case of a client: If a cert_types have been specified then we send the extension.
69 static int
70 _gnutls_cert_type_recv_params (gnutls_session_t session,
71 const opaque * data, size_t _data_size)
73 int new_type = -1, ret, i;
74 ssize_t data_size = _data_size;
76 if (session->security_parameters.entity == GNUTLS_CLIENT)
78 if (data_size > 0)
80 if (data_size != 1)
82 gnutls_assert ();
83 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
86 new_type = _gnutls_num2cert_type (data[0]);
88 if (new_type < 0)
90 gnutls_assert ();
91 return new_type;
94 /* Check if we support this cert_type */
95 if ((ret =
96 _gnutls_session_cert_type_supported (session, new_type)) < 0)
98 gnutls_assert ();
99 return ret;
102 _gnutls_session_cert_type_set (session, new_type);
105 else
106 { /* SERVER SIDE - we must check if the sent cert type is the right one
108 if (data_size > 1)
110 uint8_t len;
112 DECR_LEN (data_size, 1);
113 len = data[0];
114 DECR_LEN (data_size, len);
116 for (i = 0; i < len; i++)
118 new_type = _gnutls_num2cert_type (data[i + 1]);
120 if (new_type < 0)
121 continue;
123 /* Check if we support this cert_type */
124 if ((ret =
125 _gnutls_session_cert_type_supported (session,
126 new_type)) < 0)
128 gnutls_assert ();
129 continue;
131 else
132 break;
133 /* new_type is ok */
136 if (new_type < 0)
138 gnutls_assert ();
139 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
142 if ((ret =
143 _gnutls_session_cert_type_supported (session, new_type)) < 0)
145 gnutls_assert ();
146 /* The peer has requested unsupported certificate
147 * types. Instead of failing, procceed normally.
148 * (the ciphersuite selection would fail, or a
149 * non certificate ciphersuite will be selected).
151 return 0;
154 _gnutls_session_cert_type_set (session, new_type);
158 return 0;
161 /* returns data_size or a negative number on failure
163 static int
164 _gnutls_cert_type_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
166 unsigned len, i;
167 int ret;
168 uint8_t p;
170 /* this function sends the client extension data (dnsname) */
171 if (session->security_parameters.entity == GNUTLS_CLIENT)
174 if (session->internals.priorities.cert_type.algorithms > 0)
177 len = session->internals.priorities.cert_type.algorithms;
179 if (len == 1 &&
180 session->internals.priorities.cert_type.priority[0] ==
181 GNUTLS_CRT_X509)
183 /* We don't use this extension if X.509 certificates
184 * are used.
186 return 0;
189 /* this is a vector!
191 p = (uint8_t) len;
192 ret = _gnutls_buffer_append_data(extdata, &p, 1);
193 if (ret < 0)
194 return gnutls_assert_val(ret);
196 for (i = 0; i < len; i++)
199 _gnutls_cert_type2num (session->internals.priorities.
200 cert_type.priority[i]);
201 ret = _gnutls_buffer_append_data(extdata, &p, 1);
202 if (ret < 0)
203 return gnutls_assert_val(ret);
205 return len + 1;
209 else
210 { /* server side */
211 if (session->security_parameters.cert_type != DEFAULT_CERT_TYPE)
213 len = 1;
216 _gnutls_cert_type2num (session->security_parameters.cert_type);
217 ret = _gnutls_buffer_append_data(extdata, &p, 1);
218 if (ret < 0)
219 return gnutls_assert_val(ret);
221 return len;
227 return 0;
230 /* Maps numbers to record sizes according to the
231 * extensions draft.
233 inline static int
234 _gnutls_num2cert_type (int num)
236 switch (num)
238 case 0:
239 return GNUTLS_CRT_X509;
240 case 1:
241 return GNUTLS_CRT_OPENPGP;
242 default:
243 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
247 /* Maps record size to numbers according to the
248 * extensions draft.
250 inline static int
251 _gnutls_cert_type2num (int cert_type)
253 switch (cert_type)
255 case GNUTLS_CRT_X509:
256 return 0;
257 case GNUTLS_CRT_OPENPGP:
258 return 1;
259 default:
260 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;