2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include <gnutls_int.h>
22 #include <gnutls_errors.h>
24 #include <auth_x509.h>
25 #include <gnutls_cert.h>
26 #include <x509_asn1.h>
28 #include <gnutls_datum.h>
29 #include <gnutls_gcry.h>
30 #include <gnutls_privkey.h>
31 #include <gnutls_global.h>
32 #include <gnutls_pk.h>
34 #include <gnutls_buffers.h>
35 #include <gnutls_sig.h>
39 /* Generates a signature of all the previous sent packets in the
40 * handshake procedure.
42 int _gnutls_generate_sig_from_hdata( GNUTLS_STATE state
, gnutls_cert
* cert
, gnutls_private_key
*pkey
, gnutls_datum
*signature
) {
46 GNUTLS_MAC_HANDLE td_md5
;
47 GNUTLS_MAC_HANDLE td_sha
;
49 td_md5
= gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_md5
);
52 return GNUTLS_E_HASH_FAILED
;
55 td_sha
= gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_sha
);
58 gnutls_hash_deinit( td_md5
, NULL
);
59 return GNUTLS_E_HASH_FAILED
;
62 gnutls_hash_deinit(td_md5
, concat
);
63 gnutls_hash_deinit(td_sha
, &concat
[16]);
65 dconcat
.data
= concat
;
68 ret
= _gnutls_generate_sig( cert
, pkey
, &dconcat
, signature
);
76 /* Generates a signature of all the random data and the parameters.
77 * Used in DHE_* ciphersuites.
79 int _gnutls_generate_sig_params( GNUTLS_STATE state
, gnutls_cert
* cert
, gnutls_private_key
*pkey
, gnutls_datum
* params
, gnutls_datum
*signature
)
83 GNUTLS_MAC_HANDLE td_md5
;
84 GNUTLS_MAC_HANDLE td_sha
;
87 td_md5
= gnutls_hash_init( GNUTLS_MAC_MD5
);
90 return GNUTLS_E_HASH_FAILED
;
93 td_sha
= gnutls_hash_init( GNUTLS_MAC_SHA
);
96 gnutls_hash_deinit( td_md5
, NULL
);
97 return GNUTLS_E_HASH_FAILED
;
100 gnutls_hash( td_md5
, state
->security_parameters
.client_random
, TLS_RANDOM_SIZE
);
101 gnutls_hash( td_md5
, state
->security_parameters
.server_random
, TLS_RANDOM_SIZE
);
102 gnutls_hash( td_md5
, params
->data
, params
->size
);
104 gnutls_hash( td_sha
, state
->security_parameters
.client_random
, TLS_RANDOM_SIZE
);
105 gnutls_hash( td_sha
, state
->security_parameters
.server_random
, TLS_RANDOM_SIZE
);
106 gnutls_hash( td_sha
, params
->data
, params
->size
);
108 gnutls_hash_deinit(td_md5
, concat
);
109 gnutls_hash_deinit(td_sha
, &concat
[16]);
111 dconcat
.data
= concat
;
114 ret
= _gnutls_generate_sig( cert
, pkey
, &dconcat
, signature
);
123 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
124 * Cert is the certificate of the corresponding private key. It is only checked if
125 * it supports signing.
127 int _gnutls_generate_sig( gnutls_cert
* cert
, gnutls_private_key
*pkey
, const gnutls_datum
* hash_concat
, gnutls_datum
*signature
)
130 gnutls_datum tmpdata
;
132 /* If our certificate supports signing
136 if ( cert
->keyUsage
!= 0)
137 if ( !(cert
->keyUsage
& GNUTLS_X509KEY_DIGITAL_SIGNATURE
)) {
139 return GNUTLS_E_X509_KEY_USAGE_VIOLATION
;
142 switch(pkey
->pk_algorithm
) {
144 tmpdata
.data
= hash_concat
->data
;
145 tmpdata
.size
= hash_concat
->size
; /* md5 + sha */
148 if ((ret
=_gnutls_pkcs1_rsa_encrypt( signature
, tmpdata
, pkey
->params
[0], pkey
->params
[1], 1)) < 0) {
155 /* Ok this is silly. We have calculated
158 tmpdata
.data
= &hash_concat
->data
[16];
159 tmpdata
.size
= 20; /* sha */
162 if ((ret
=_gnutls_dsa_sign( signature
, tmpdata
, pkey
->params
[0], pkey
->params
[1], pkey
->params
[2], pkey
->params
[3])) < 0) {
169 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
180 int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert
*cert
, const gnutls_datum
*hash_concat
, gnutls_datum
*signature
) {
184 if (cert
->version
== 0 || cert
==NULL
) { /* this is the only way to check
185 * if it is initialized
188 return GNUTLS_E_X509_CERTIFICATE_ERROR
;
191 /* If the certificate supports signing continue.
194 if ( cert
->keyUsage
!= 0)
195 if ( !(cert
->keyUsage
& GNUTLS_X509KEY_DIGITAL_SIGNATURE
)) {
197 return GNUTLS_E_X509_KEY_USAGE_VIOLATION
;
200 switch(cert
->subject_pk_algorithm
) {
203 vdata
.data
= hash_concat
->data
;
204 vdata
.size
= hash_concat
->size
;
206 /* verify signature */
207 if ( (ret
=_gnutls_rsa_verify( &vdata
, signature
, cert
->params
[1], cert
->params
[0], 1)) < 0) {
215 vdata
.data
= &hash_concat
->data
[16];
216 vdata
.size
= 20; /* sha1 */
218 /* decrypt signature */
219 if ( (ret
=_gnutls_dsa_verify( &vdata
, *signature
, cert
->params
[0],
220 cert
->params
[1], cert
->params
[2], cert
->params
[3])) < 0) {
228 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
237 /* Verifies a TLS signature (like the one in the client certificate
238 * verify message). ubuffer_size is a buffer to remove from the hash buffer
239 * in order to avoid hashing the last message.
241 int _gnutls_verify_sig_hdata( GNUTLS_STATE state
, gnutls_cert
*cert
, gnutls_datum
* signature
, int ubuffer_size
) {
244 GNUTLS_MAC_HANDLE td_md5
;
245 GNUTLS_MAC_HANDLE td_sha
;
246 gnutls_datum dconcat
;
248 td_md5
= gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_md5
);
249 if (td_md5
== NULL
) {
251 return GNUTLS_E_HASH_FAILED
;
254 td_sha
= gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_sha
);
255 if (td_sha
== NULL
) {
257 gnutls_hash_deinit( td_md5
, NULL
);
258 return GNUTLS_E_HASH_FAILED
;
261 gnutls_hash_deinit(td_md5
, concat
);
262 gnutls_hash_deinit(td_sha
, &concat
[16]);
264 dconcat
.data
= concat
;
265 dconcat
.size
= 20+16; /* md5+ sha */
267 ret
= _gnutls_pkcs1_rsa_verify_sig( cert
, &dconcat
, signature
);
277 /* Generates a signature of all the random data and the parameters.
278 * Used in DHE_* ciphersuites.
280 int _gnutls_verify_sig_params( GNUTLS_STATE state
, gnutls_cert
*cert
, const gnutls_datum
* params
, gnutls_datum
*signature
)
282 gnutls_datum dconcat
;
284 GNUTLS_MAC_HANDLE td_md5
;
285 GNUTLS_MAC_HANDLE td_sha
;
288 td_md5
= gnutls_hash_init( GNUTLS_MAC_MD5
);
289 if (td_md5
== NULL
) {
291 return GNUTLS_E_HASH_FAILED
;
294 td_sha
= gnutls_hash_init( GNUTLS_MAC_SHA
);
295 if (td_sha
== NULL
) {
297 gnutls_hash_deinit( td_md5
, NULL
);
298 return GNUTLS_E_HASH_FAILED
;
301 gnutls_hash( td_md5
, state
->security_parameters
.client_random
, TLS_RANDOM_SIZE
);
302 gnutls_hash( td_md5
, state
->security_parameters
.server_random
, TLS_RANDOM_SIZE
);
303 gnutls_hash( td_md5
, params
->data
, params
->size
);
305 gnutls_hash( td_sha
, state
->security_parameters
.client_random
, TLS_RANDOM_SIZE
);
306 gnutls_hash( td_sha
, state
->security_parameters
.server_random
, TLS_RANDOM_SIZE
);
307 gnutls_hash( td_sha
, params
->data
, params
->size
);
309 gnutls_hash_deinit(td_md5
, concat
);
310 gnutls_hash_deinit(td_sha
, &concat
[16]);
312 dconcat
.data
= concat
;
315 ret
= _gnutls_pkcs1_rsa_verify_sig( cert
, &dconcat
, signature
);