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>
25 #include <auth_cert.h>
26 #include <gnutls_cert.h>
27 #include <x509_asn1.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>
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
) {
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
);
56 return GNUTLS_E_HASH_FAILED
;
59 _gnutls_hash_deinit(td_sha
, &concat
[16]);
61 switch (cert
->subject_pk_algorithm
) {
63 td_md5
= _gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_md5
);
66 return GNUTLS_E_HASH_FAILED
;
68 _gnutls_hash_deinit(td_md5
, concat
);
70 dconcat
.data
= concat
;
74 dconcat
.data
= &concat
[16];
80 return GNUTLS_E_INTERNAL_ERROR
;
82 ret
= _gnutls_generate_sig( cert
, pkey
, &dconcat
, signature
);
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
)
97 GNUTLS_MAC_HANDLE td_md5
;
98 GNUTLS_MAC_HANDLE td_sha
;
102 td_sha
= _gnutls_hash_init( GNUTLS_MAC_SHA
);
103 if (td_sha
== NULL
) {
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
) {
116 td_md5
= _gnutls_hash_init( GNUTLS_MAC_MD5
);
117 if (td_md5
== NULL
) {
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
;
132 dconcat
.data
= &concat
[16];
138 return GNUTLS_E_INTERNAL_ERROR
;
140 ret
= _gnutls_generate_sig( cert
, pkey
, &dconcat
, signature
);
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
)
156 gnutls_datum tmpdata
;
158 /* If our certificate supports signing
162 if ( cert
->keyUsage
!= 0)
163 if ( !(cert
->keyUsage
& GNUTLS_X509KEY_DIGITAL_SIGNATURE
)) {
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
) {
174 if ((ret
=_gnutls_pkcs1_rsa_encrypt( signature
, tmpdata
, pkey
->params
,
175 pkey
->params_size
, 1)) < 0) {
183 if ((ret
=_gnutls_dsa_sign( signature
, &tmpdata
, pkey
->params
,
184 pkey
->params_size
)) < 0) {
191 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
202 int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert
*cert
, const gnutls_datum
*hash_concat
, gnutls_datum
*signature
) {
206 if (cert
->version
== 0 || cert
==NULL
) { /* this is the only way to check
207 * if it is initialized
210 return GNUTLS_E_X509_CERTIFICATE_ERROR
;
213 /* If the certificate supports signing continue.
216 if ( cert
->keyUsage
!= 0)
217 if ( !(cert
->keyUsage
& GNUTLS_X509KEY_DIGITAL_SIGNATURE
)) {
219 return GNUTLS_E_X509_KEY_USAGE_VIOLATION
;
222 switch(cert
->subject_pk_algorithm
) {
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) {
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) {
252 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
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
) {
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
) {
275 return GNUTLS_E_HASH_FAILED
;
278 td_sha
= _gnutls_hash_copy( state
->gnutls_internals
.handshake_mac_handle_sha
);
279 if (td_sha
== NULL
) {
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
);
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
;
308 GNUTLS_MAC_HANDLE td_md5
;
309 GNUTLS_MAC_HANDLE td_sha
;
312 td_md5
= _gnutls_hash_init( GNUTLS_MAC_MD5
);
313 if (td_md5
== NULL
) {
315 return GNUTLS_E_HASH_FAILED
;
318 td_sha
= _gnutls_hash_init( GNUTLS_MAC_SHA
);
319 if (td_sha
== NULL
) {
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
;
339 ret
= _gnutls_pkcs1_rsa_verify_sig( cert
, &dconcat
, signature
);