added memory handling section
[gnutls.git] / lib / gnutls_sig.c
blob5fc4938733243c39519ba844a6645f28f4be5958
1 /*
2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <gnutls_int.h>
23 #include <gnutls_errors.h>
24 #include <x509_b64.h>
25 #include <auth_cert.h>
26 #include <gnutls_cert.h>
27 #include <x509_asn1.h>
28 #include <x509_der.h>
29 #include <gnutls_datum.h>
30 #include <gnutls_mpi.h>
31 #include <gnutls_privkey.h>
32 #include <gnutls_global.h>
33 #include <gnutls_pk.h>
34 #include <debug.h>
35 #include <gnutls_buffers.h>
36 #include <gnutls_sig.h>
39 int _gnutls_generate_sig( gnutls_cert* cert, gnutls_private_key *pkey, const gnutls_datum* hash_concat, gnutls_datum *signature);
42 /* Generates a signature of all the previous sent packets in the
43 * handshake procedure.
45 int _gnutls_generate_sig_from_hdata( GNUTLS_STATE state, gnutls_cert* cert, gnutls_private_key *pkey, gnutls_datum *signature) {
46 gnutls_datum dconcat;
47 int ret;
48 opaque concat[36];
49 GNUTLS_MAC_HANDLE td_md5;
50 GNUTLS_MAC_HANDLE td_sha;
53 td_sha = _gnutls_hash_copy( state->gnutls_internals.handshake_mac_handle_sha);
54 if (td_sha == NULL) {
55 gnutls_assert();
56 return GNUTLS_E_HASH_FAILED;
59 _gnutls_hash_deinit(td_sha, &concat[16]);
61 switch (cert->subject_pk_algorithm) {
62 case GNUTLS_PK_RSA:
63 td_md5 = _gnutls_hash_copy( state->gnutls_internals.handshake_mac_handle_md5);
64 if (td_md5 == NULL) {
65 gnutls_assert();
66 return GNUTLS_E_HASH_FAILED;
68 _gnutls_hash_deinit(td_md5, concat);
70 dconcat.data = concat;
71 dconcat.size = 36;
72 break;
73 case GNUTLS_PK_DSA:
74 dconcat.data = &concat[16];
75 dconcat.size = 20;
76 break;
78 default:
79 gnutls_assert();
80 return GNUTLS_E_INTERNAL_ERROR;
82 ret = _gnutls_generate_sig( cert, pkey, &dconcat, signature);
83 if (ret < 0)
84 gnutls_assert();
86 return ret;
90 /* Generates a signature of all the random data and the parameters.
91 * Used in DHE_* ciphersuites.
93 int _gnutls_generate_sig_params( GNUTLS_STATE state, gnutls_cert* cert, gnutls_private_key *pkey, gnutls_datum* params, gnutls_datum *signature)
95 gnutls_datum dconcat;
96 int ret;
97 GNUTLS_MAC_HANDLE td_md5;
98 GNUTLS_MAC_HANDLE td_sha;
99 opaque concat[36];
102 td_sha = _gnutls_hash_init( GNUTLS_MAC_SHA);
103 if (td_sha == NULL) {
104 gnutls_assert();
105 return GNUTLS_E_HASH_FAILED;
108 _gnutls_hash( td_sha, state->security_parameters.client_random, TLS_RANDOM_SIZE);
109 _gnutls_hash( td_sha, state->security_parameters.server_random, TLS_RANDOM_SIZE);
110 _gnutls_hash( td_sha, params->data, params->size);
112 _gnutls_hash_deinit(td_sha, &concat[16]);
114 switch (cert->subject_pk_algorithm) {
115 case GNUTLS_PK_RSA:
116 td_md5 = _gnutls_hash_init( GNUTLS_MAC_MD5);
117 if (td_md5 == NULL) {
118 gnutls_assert();
119 return GNUTLS_E_HASH_FAILED;
122 _gnutls_hash( td_md5, state->security_parameters.client_random, TLS_RANDOM_SIZE);
123 _gnutls_hash( td_md5, state->security_parameters.server_random, TLS_RANDOM_SIZE);
124 _gnutls_hash( td_md5, params->data, params->size);
126 _gnutls_hash_deinit(td_md5, concat);
128 dconcat.data = concat;
129 dconcat.size = 36;
130 break;
131 case GNUTLS_PK_DSA:
132 dconcat.data = &concat[16];
133 dconcat.size = 20;
134 break;
136 default:
137 gnutls_assert();
138 return GNUTLS_E_INTERNAL_ERROR;
140 ret = _gnutls_generate_sig( cert, pkey, &dconcat, signature);
141 if (ret < 0)
142 gnutls_assert();
144 return ret;
149 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
150 * Cert is the certificate of the corresponding private key. It is only checked if
151 * it supports signing.
153 int _gnutls_generate_sig( gnutls_cert* cert, gnutls_private_key *pkey, const gnutls_datum* hash_concat, gnutls_datum *signature)
155 int ret;
156 gnutls_datum tmpdata;
158 /* If our certificate supports signing
161 if ( cert != NULL)
162 if ( cert->keyUsage != 0)
163 if ( !(cert->keyUsage & GNUTLS_X509KEY_DIGITAL_SIGNATURE)) {
164 gnutls_assert();
165 return GNUTLS_E_X509_KEY_USAGE_VIOLATION;
168 tmpdata.data = hash_concat->data;
169 tmpdata.size = hash_concat->size;
171 switch(pkey->pk_algorithm) {
172 case GNUTLS_PK_RSA:
173 /* encrypt */
174 if ((ret=_gnutls_pkcs1_rsa_encrypt( signature, tmpdata, pkey->params,
175 pkey->params_size, 1)) < 0) {
176 gnutls_assert();
177 return ret;
180 break;
181 case GNUTLS_PK_DSA:
182 /* sign */
183 if ((ret=_gnutls_dsa_sign( signature, &tmpdata, pkey->params,
184 pkey->params_size)) < 0) {
185 gnutls_assert();
186 return ret;
188 break;
189 default:
190 gnutls_assert();
191 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
192 break;
197 return 0;
202 int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *hash_concat, gnutls_datum *signature) {
203 int ret;
204 gnutls_datum vdata;
206 if (cert->version == 0 || cert==NULL) { /* this is the only way to check
207 * if it is initialized
209 gnutls_assert();
210 return GNUTLS_E_X509_CERTIFICATE_ERROR;
213 /* If the certificate supports signing continue.
215 if ( cert != NULL)
216 if ( cert->keyUsage != 0)
217 if ( !(cert->keyUsage & GNUTLS_X509KEY_DIGITAL_SIGNATURE)) {
218 gnutls_assert();
219 return GNUTLS_E_X509_KEY_USAGE_VIOLATION;
222 switch(cert->subject_pk_algorithm) {
223 case GNUTLS_PK_RSA:
225 vdata.data = hash_concat->data;
226 vdata.size = hash_concat->size;
228 /* verify signature */
229 if ( (ret=_gnutls_rsa_verify( &vdata, signature, cert->params,
230 cert->params_size, 1)) < 0) {
231 gnutls_assert();
232 return ret;
235 break;
236 case GNUTLS_PK_DSA:
238 vdata.data = &hash_concat->data[16];
239 vdata.size = 20; /* sha1 */
241 /* decrypt signature */
242 if ( (ret=_gnutls_dsa_verify( &vdata, signature, cert->params,
243 cert->params_size)) < 0) {
244 gnutls_assert();
245 return ret;
248 break;
250 default:
251 gnutls_assert();
252 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
257 return 0;
261 /* Verifies a TLS signature (like the one in the client certificate
262 * verify message). ubuffer_size is a buffer to remove from the hash buffer
263 * in order to avoid hashing the last message.
265 int _gnutls_verify_sig_hdata( GNUTLS_STATE state, gnutls_cert *cert, gnutls_datum* signature, int ubuffer_size) {
266 int ret;
267 opaque concat[36];
268 GNUTLS_MAC_HANDLE td_md5;
269 GNUTLS_MAC_HANDLE td_sha;
270 gnutls_datum dconcat;
272 td_md5 = _gnutls_hash_copy( state->gnutls_internals.handshake_mac_handle_md5);
273 if (td_md5 == NULL) {
274 gnutls_assert();
275 return GNUTLS_E_HASH_FAILED;
278 td_sha = _gnutls_hash_copy( state->gnutls_internals.handshake_mac_handle_sha);
279 if (td_sha == NULL) {
280 gnutls_assert();
281 _gnutls_hash_deinit( td_md5, NULL);
282 return GNUTLS_E_HASH_FAILED;
285 _gnutls_hash_deinit(td_md5, concat);
286 _gnutls_hash_deinit(td_sha, &concat[16]);
288 dconcat.data = concat;
289 dconcat.size = 20+16; /* md5+ sha */
291 ret = _gnutls_pkcs1_rsa_verify_sig( cert, &dconcat, signature);
292 if (ret < 0) {
293 gnutls_assert();
294 return ret;
297 return ret;
301 /* Generates a signature of all the random data and the parameters.
302 * Used in DHE_* ciphersuites.
304 int _gnutls_verify_sig_params( GNUTLS_STATE state, gnutls_cert *cert, const gnutls_datum* params, gnutls_datum *signature)
306 gnutls_datum dconcat;
307 int ret;
308 GNUTLS_MAC_HANDLE td_md5;
309 GNUTLS_MAC_HANDLE td_sha;
310 opaque concat[36];
312 td_md5 = _gnutls_hash_init( GNUTLS_MAC_MD5);
313 if (td_md5 == NULL) {
314 gnutls_assert();
315 return GNUTLS_E_HASH_FAILED;
318 td_sha = _gnutls_hash_init( GNUTLS_MAC_SHA);
319 if (td_sha == NULL) {
320 gnutls_assert();
321 _gnutls_hash_deinit( td_md5, NULL);
322 return GNUTLS_E_HASH_FAILED;
325 _gnutls_hash( td_md5, state->security_parameters.client_random, TLS_RANDOM_SIZE);
326 _gnutls_hash( td_md5, state->security_parameters.server_random, TLS_RANDOM_SIZE);
327 _gnutls_hash( td_md5, params->data, params->size);
329 _gnutls_hash( td_sha, state->security_parameters.client_random, TLS_RANDOM_SIZE);
330 _gnutls_hash( td_sha, state->security_parameters.server_random, TLS_RANDOM_SIZE);
331 _gnutls_hash( td_sha, params->data, params->size);
333 _gnutls_hash_deinit(td_md5, concat);
334 _gnutls_hash_deinit(td_sha, &concat[16]);
336 dconcat.data = concat;
337 dconcat.size = 36;
339 ret = _gnutls_pkcs1_rsa_verify_sig( cert, &dconcat, signature);
340 if (ret < 0) {
341 gnutls_assert();
342 return ret;
345 return ret;