diff options
-rw-r--r-- | doc/Makefile.am | 5 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/auth_rsa.c | 243 | ||||
-rw-r--r-- | lib/auth_x509.h | 11 | ||||
-rwxr-xr-x | lib/cert_asn1.h | 6 | ||||
-rw-r--r-- | lib/gnutls.h.in | 9 | ||||
-rw-r--r-- | lib/gnutls_datum.c | 42 | ||||
-rw-r--r-- | lib/gnutls_datum.h | 4 | ||||
-rw-r--r-- | lib/gnutls_hash_int.c | 4 | ||||
-rw-r--r-- | lib/gnutls_hash_int.h | 4 | ||||
-rw-r--r-- | lib/gnutls_int.h | 56 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 10 |
12 files changed, 341 insertions, 57 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index 7bbe5cc8ff..fed12235a5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,8 +1,5 @@ -EXTRA_DIST = TODO gnutls.3 gnutls-api.txt gnutls-api.html -man_MANS = gnutls.3 +EXTRA_DIST = TODO gnutls-api.txt gnutls-api.html -gnutls.3: - @scripts/gdoc -man ../lib/*.c > gnutls.3 gnutls-api: gnutls-api.html gnutls-api.txt gnutls-api.html: @scripts/gdoc -html ../lib/*.c > gnutls-api.html diff --git a/lib/Makefile.am b/lib/Makefile.am index b69ea0a000..1e81f3857a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,7 +13,7 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h \ gnutls_auth_int.h crypt_bcrypt.h gnutls_random.h crypt_srpsha1.h \ cert_b64.h gnutls_srp.h auth_srp.h auth_srp_passwd.h gnutls_v2_compat.h \ crypt.h libgnutls-config.in libgnutls.m4 gnutls.h.in gnutls_errors_int.h \ - cert_asn1.h cert_der.h + cert_asn1.h cert_der.h gnutls_datum.h auth_x509.c lib_LTLIBRARIES = libgnutls.la libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \ @@ -23,6 +23,6 @@ libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ auth_anon.c auth_dhe_dss.c gnutls_extensions.c ext_srp.c gnutls_auth.c \ crypt_bcrypt.c crypt.c gnutls_random.c crypt_srpsha1.c gnutls_srp.c \ auth_srp.c auth_srp_passwd.c gnutls_v2_compat.c auth_srp_sb64.c \ - cert_ASN.y cert_asn1.c cert_der.c + cert_ASN.y cert_asn1.c cert_der.c gnutls_datum.c auth_rsa.c libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c new file mode 100644 index 0000000000..932c7b2c7b --- /dev/null +++ b/lib/auth_rsa.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2000,2001 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <defines.h> +#include "gnutls_int.h" +#include "gnutls_auth_int.h" +#include "gnutls_errors.h" +#include "gnutls_dh.h" +#include "auth_anon.h" +#include "gnutls_num.h" +#include "cert_asn1.h" +#include "cert_der.h" +#include "gnutls_datum.h" +#include "auth_x509.h" + +int gen_rsa_server_kx(GNUTLS_KEY, opaque **); + +MOD_AUTH_STRUCT rsa_auth_struct = { + "RSA", + gen_rsa_server_kx, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +typedef struct { + gnutls_datum rsa_modulus; + gnutls_datum rsa_exponent; +} RSA_Params; + +/* This function will calculate the SHA/MD5 signature in server kx. + * This is needed by the protocol. + */ +int _gnutls_calc_rsa_signature( GNUTLS_KEY key, const opaque* data, int data_size, opaque* dst) { + void* md5; + void* sha; + int ret = 0; + GNUTLS_MAC_HANDLE td; + + td = gnutls_hash_init(GNUTLS_MAC_MD5); + if (td==GNUTLS_HASH_FAILED) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + gnutls_hash( td, key->client_random, 32); + gnutls_hash( td, key->server_random, 32); + gnutls_hash( td, data, data_size); + + md5 = gnutls_hash_deinit(td); + if (md5==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy( dst, md5, 16); + gnutls_free(md5); + + + td = gnutls_hash_init(GNUTLS_MAC_SHA); + if (td==GNUTLS_HASH_FAILED) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + gnutls_hash( td, key->client_random, 32); + gnutls_hash( td, key->server_random, 32); + gnutls_hash( td, data, data_size); + + sha = gnutls_hash_deinit(td); + if (sha==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + memcpy( &dst[16], sha, 20); + gnutls_free(sha); + + return ret; +} + + +#define dat_set( d,s,len) d.data=gnutls_malloc(len); \ + if (d.data==NULL) return GNUTLS_E_MEMORY_ERROR; \ + memcpy(d.data, s, len); d.size = len; + +/* This function reads the RSA parameters from the given(?) certificate. + */ +static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_datum cert) +{ + int ret = 0, result; + opaque str[5*1024]; + int len = sizeof(str); + + create_structure("certificate2", "PKIX1Explicit88.Certificate"); + + result = get_der("certificate2", cert.data, cert.size); + if (result != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + /* Verify sign */ + result = + read_value("certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm", str, &len); + if (result != ASN_OK) { + gnutls_assert(); + delete_structure("certificate2"); + return GNUTLS_E_PARSING_ERROR; + } + + if (!strcmp(str, "111")) { /* pkix-1 1 - RSA */ + len = sizeof(str); + result = + read_value("certificate2.tbsCertificate.subjectPublicKeyInfo.parameters", str, &len); + delete_structure("certificate2"); + + if (result != ASN_OK) { + gnutls_assert(); + delete_structure("certificate2"); + return GNUTLS_E_PARSING_ERROR; + } + + create_structure("rsapublickey", "PKIX1Explicit88.RSAPublicKey"); + result = get_der("rsapublickey", str, len); + if (result != ASN_OK) { + gnutls_assert(); + delete_structure("rsapublickey"); + return GNUTLS_E_PARSING_ERROR; + } + + result = + read_value("rsapublickey.modulus", str, &len); + if (result != ASN_OK) { + gnutls_assert(); + delete_structure("rsapublickey"); + return GNUTLS_E_PARSING_ERROR; + } + + if (gcry_mpi_scan(&key->A, + GCRYMPI_FMT_USG, str, &len) != 0) { + gnutls_assert(); + delete_structure("rsapublickey"); + return GNUTLS_E_MPI_SCAN_FAILED; + } + dat_set(params->rsa_modulus, str, len); + + len = sizeof(str); + result = + read_value("rsapublickey.publicExponent", str, &len); + if (result != ASN_OK) { + gnutls_assert(); + delete_structure("rsapublickey"); + gnutls_free(params->rsa_modulus.data); + gcry_mpi_release(key->A); + return GNUTLS_E_PARSING_ERROR; + } + + if (gcry_mpi_scan(&key->B, + GCRYMPI_FMT_USG, str, &len) != 0) { + gnutls_assert(); + gcry_mpi_release(key->A); + gnutls_free(params->rsa_modulus.data); + delete_structure("rsapublickey"); + return GNUTLS_E_MPI_SCAN_FAILED; + } + dat_set(params->rsa_exponent, str, len); + + delete_structure("rsapublickey"); + + } + + delete_structure("certificate2"); + + return ret; +} + +int gen_rsa_server_kx(GNUTLS_KEY key, opaque ** data) +{ + RSA_Params params; + const X509PKI_SERVER_CREDENTIALS *cred; + int ret; + opaque* pdata; + + cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFICIENT_CRED; + } + + ret = + _gnutls_get_rsa_params(key, ¶ms, cred->cert_list[0]); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = params.rsa_modulus.size + + params.rsa_modulus.size + 16 + 20 + 4; + (*data) = gnutls_malloc( ret); + + pdata = (*data); + if (pdata == NULL) return GNUTLS_E_MEMORY_ERROR; + + WRITEdatum16(pdata, params.rsa_modulus); + pdata += params.rsa_modulus.size; + + WRITEdatum16(pdata, params.rsa_exponent); + pdata += params.rsa_exponent.size; + + ret = _gnutls_calc_rsa_signature( key, (*data), ret-20-16, pdata); + if (ret< 0) { + gnutls_free((*data)); + gnutls_assert(); + return ret; + } + + return ret; +} + diff --git a/lib/auth_x509.h b/lib/auth_x509.h new file mode 100644 index 0000000000..d7dcd2d3a0 --- /dev/null +++ b/lib/auth_x509.h @@ -0,0 +1,11 @@ +/* this is not to be included by gnutls_anon.c */ +extern MOD_AUTH_STRUCT x509pki_auth_struct; + +typedef struct { + gnutls_datum * cert_list; + int cert_list_size; +} X509PKI_SERVER_CREDENTIALS; + +typedef struct { + int dh_bits; +} X509PKI_AUTH_INFO; diff --git a/lib/cert_asn1.h b/lib/cert_asn1.h index b29a7a80dc..a1d8354294 100755 --- a/lib/cert_asn1.h +++ b/lib/cert_asn1.h @@ -167,5 +167,11 @@ delete_tree2(node_asn *root); int append_sequence_set(node_asn *node); +int +create_structure(char *dest_name,char *source_name); + +int +delete_structure(char *root_name); + #endif diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index e3d1a4759c..174a602928 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -47,6 +47,11 @@ typedef enum AlertDescription { GNUTLS_CLOSE_NOTIFY, GNUTLS_UNEXPECTED_MESSAGE=1 struct GNUTLS_STATE_INT; typedef struct GNUTLS_STATE_INT* GNUTLS_STATE; +typedef struct { + unsigned char * data; + int size; +} gnutls_datum; + /* internal functions */ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end); @@ -136,5 +141,9 @@ typedef struct { int dh_bits; } ANON_AUTH_INFO; +typedef struct { + gnutls_datum * cert_list; + int cert_list_size; +} X509PKI_SERVER_CREDENTIALS; /* error codes appended here */ diff --git a/lib/gnutls_datum.c b/lib/gnutls_datum.c new file mode 100644 index 0000000000..8e137dcb18 --- /dev/null +++ b/lib/gnutls_datum.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <defines.h> +#include <gnutls_int.h> +#include <gnutls_num.h> +#include <gnutls_datum.h> +#include <gnutls_errors.h> + +void WRITEdatum16( opaque* dest, gnutls_datum dat) { + WRITEuint16( dat.size, dest); + memcpy( &dest[2], dat.data, dat.size); +} +void WRITEdatum24( opaque* dest, gnutls_datum dat) { + WRITEuint24( dat.size, dest); + memcpy( &dest[3], dat.data, dat.size); +} +void WRITEdatum32( opaque* dest, gnutls_datum dat) { + WRITEuint32( dat.size, dest); + memcpy( &dest[4], dat.data, dat.size); +} +void WRITEdatum8( opaque* dest, gnutls_datum dat) { + dest[0] = (uint8) dat.size; + memcpy( &dest[1], dat.data, dat.size); +} diff --git a/lib/gnutls_datum.h b/lib/gnutls_datum.h new file mode 100644 index 0000000000..2462acd648 --- /dev/null +++ b/lib/gnutls_datum.h @@ -0,0 +1,4 @@ +void WRITEdatum16( opaque* dest, gnutls_datum dat); +void WRITEdatum24( opaque* dest, gnutls_datum dat); +void WRITEdatum32( opaque* dest, gnutls_datum dat); +void WRITEdatum8( opaque* dest, gnutls_datum dat); diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c index 42e0eaff7b..464baa8aa8 100644 --- a/lib/gnutls_hash_int.c +++ b/lib/gnutls_hash_int.c @@ -99,7 +99,7 @@ int gnutls_hash_get_algo_len(MACAlgorithm algorithm) } -int gnutls_hash(GNUTLS_MAC_HANDLE handle, void *text, int textlen) +int gnutls_hash(GNUTLS_MAC_HANDLE handle, const void *text, int textlen) { #ifdef USE_MHASH mhash(handle->handle, text, textlen); @@ -210,7 +210,7 @@ int gnutls_hmac_get_algo_len(MACAlgorithm algorithm) } -int gnutls_hmac(GNUTLS_MAC_HANDLE handle, void *text, int textlen) +int gnutls_hmac(GNUTLS_MAC_HANDLE handle, const void *text, int textlen) { #ifdef USE_MHASH diff --git a/lib/gnutls_hash_int.h b/lib/gnutls_hash_int.h index dd2b7ce53f..ae516325d3 100644 --- a/lib/gnutls_hash_int.h +++ b/lib/gnutls_hash_int.h @@ -49,7 +49,7 @@ typedef GNUTLS_MAC_HANDLE_INT* GNUTLS_MAC_HANDLE; GNUTLS_MAC_HANDLE gnutls_hmac_init( MACAlgorithm algorithm, void* key, int keylen); int gnutls_hmac_get_algo_len(MACAlgorithm algorithm); -int gnutls_hmac(GNUTLS_MAC_HANDLE handle, void* text, int textlen); +int gnutls_hmac(GNUTLS_MAC_HANDLE handle, const void* text, int textlen); void* gnutls_hmac_deinit( GNUTLS_MAC_HANDLE handle); GNUTLS_MAC_HANDLE gnutls_mac_init_ssl3( MACAlgorithm algorithm, void* key, int keylen); @@ -57,7 +57,7 @@ void* gnutls_mac_deinit_ssl3( GNUTLS_MAC_HANDLE handle); GNUTLS_MAC_HANDLE gnutls_hash_init(MACAlgorithm algorithm); int gnutls_hash_get_algo_len(MACAlgorithm algorithm); -int gnutls_hash(GNUTLS_MAC_HANDLE handle, void* text, int textlen); +int gnutls_hash(GNUTLS_MAC_HANDLE handle, const void* text, int textlen); void* gnutls_hash_deinit(GNUTLS_MAC_HANDLE handle); void *gnutls_ssl3_generate_random(void *secret, int secret_len, void *random, int random_len, int bytes); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 84cef16a69..58b682e461 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -139,6 +139,10 @@ typedef struct { MPI b; MPI a; MPI x; + /* RSA: + * modulus is A + * exponent is B + */ /* this is used to hold the peers authentication data */ @@ -147,6 +151,10 @@ typedef struct { uint8 crypt_algo; + /* These are needed in RSA and DH signature calculation + */ + opaque server_random[32]; + opaque client_random[32]; AUTH_CRED* cred; /* used in srp, etc */ } GNUTLS_KEY_A; typedef GNUTLS_KEY_A* GNUTLS_KEY; @@ -287,24 +295,9 @@ typedef struct { opaque* fragment; } GNUTLSCompressed; -/* This is used for both block ciphers and stream ciphers. In stream ciphers - * the padding is just ignored. - */ -typedef struct { - opaque* content; - opaque* MAC; - uint8* padding; - uint8 padding_length; -} GNUTLS_GenericBlockCipher; - -typedef struct { - opaque* content; - opaque* MAC; -} GNUTLS_GenericStreamCipher; - typedef struct { uint8 type; - ProtocolVersion version; + ProtocolVersion version; uint16 length; void* fragment; /* points GenericStreamCipher * or GenericBlockCipher @@ -312,37 +305,6 @@ typedef struct { } GNUTLSCiphertext; -/* Handshake protocol */ - - -typedef struct { - HandshakeType msg_type; - uint24 length; - void* body; -} GNUTLS_Handshake; - -typedef struct { - uint32 gmt_unix_time; - opaque random_bytes[28]; -} GNUTLS_random; - - -typedef struct { - ProtocolVersion client_version; - GNUTLS_random random; - opaque* session_id; - GNUTLS_CipherSuite* cipher_suites; - CompressionMethod* compression_methods; -} GNUTLS_ClientHello; - -typedef struct { - ProtocolVersion server_version; - GNUTLS_random random; - opaque* session_id; - GNUTLS_CipherSuite cipher_suite; - CompressionMethod compression_method; -} GNUTLS_ServerHello; - /* functions */ int _gnutls_send_alert( int cd, GNUTLS_STATE state, AlertLevel level, AlertDescription desc); int gnutls_close(int cd, GNUTLS_STATE state); diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 3c757c9473..9d6d0a26dd 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -91,6 +91,16 @@ int _gnutls_send_server_kx_message(int cd, GNUTLS_STATE state) #ifdef HARD_DEBUG fprintf(stderr, "Sending server KX message\n"); #endif + + + if (state->gnutls_internals.auth_struct->gnutls_generate_server_kx==NULL) + return 0; + + /* copy random bytes - some algorithms need that. + */ + memcpy( state->gnutls_key->server_random, state->security_parameters.server_random, 32); + memcpy( state->gnutls_key->client_random, state->security_parameters.client_random, 32); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx( state->gnutls_key, &data); if (data_size < 0) { |