diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | lib/auth_cert.c | 2 | ||||
-rw-r--r-- | lib/gnutls.h.in.in | 2 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 47 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 4 | ||||
-rw-r--r-- | lib/gnutls_auth.c | 17 | ||||
-rw-r--r-- | lib/gnutls_auth_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 1 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 24 | ||||
-rw-r--r-- | lib/gnutls_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_v2_compat.c | 2 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 9 | ||||
-rw-r--r-- | libextra/Makefile.am | 3 | ||||
-rw-r--r-- | libextra/auth_srp.c | 43 | ||||
-rw-r--r-- | libextra/auth_srp.h | 16 | ||||
-rw-r--r-- | libextra/auth_srp_rsa.c | 205 | ||||
-rw-r--r-- | libextra/ext_srp.c | 27 | ||||
-rw-r--r-- | libextra/gnutls_extra.c | 11 | ||||
-rw-r--r-- | libextra/gnutls_extra.h | 2 | ||||
-rw-r--r-- | src/cli.c | 4 | ||||
-rw-r--r-- | src/common.c | 1 | ||||
-rw-r--r-- | src/serv.c | 4 |
22 files changed, 357 insertions, 72 deletions
@@ -2,6 +2,7 @@ Version 0.?.? - Added "gnutls/compat.h" header which must be included if the obsolete 0.4.x API is to be used. - Example programs are now stored in doc/examples/ +- Added certificate authenticated SRP cipher suites. Version 0.5.11 (5/11/2002) - Some fixes in 'gnutls-cli' client program to prevent some segmentation diff --git a/lib/auth_cert.c b/lib/auth_cert.c index f7c57aa7f3..5c5774336f 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -1255,7 +1255,7 @@ int _gnutls_find_apr_cert(gnutls_session session, gnutls_cert ** apr_cert_list, int ind; cred = - _gnutls_get_kx_cred(session->key, GNUTLS_CRD_CERTIFICATE, + _gnutls_get_kx_cred(session, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in index 8f759dbd74..97e7b5644f 100644 --- a/lib/gnutls.h.in.in +++ b/lib/gnutls.h.in.in @@ -44,7 +44,7 @@ typedef enum gnutls_cipher_algorithm { GNUTLS_CIPHER_NULL=1, typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, - GNUTLS_KX_RSA_EXPORT + GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA } gnutls_kx_algorithm; typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } gnutls_credentials_type; diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index ca05423d02..f05a3cb4c2 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -28,25 +28,31 @@ /* Cred type mappings to KX algorithms */ typedef struct { gnutls_kx_algorithm algorithm; - gnutls_credentials_type type; + gnutls_credentials_type client_type; + gnutls_credentials_type server_type; /* The type of credentials a server + * needs to set */ } gnutls_cred_map; static const gnutls_cred_map cred_mappings[] = { - { GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON }, - { GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE }, - { GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE }, - { GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE }, - { GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE }, - { GNUTLS_KX_SRP, GNUTLS_CRD_SRP }, + { GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON }, + { GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE }, + { GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE }, + { GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE }, + { GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE }, + { GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP }, + { GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE }, { 0 } }; #define GNUTLS_KX_MAP_LOOP(b) \ const gnutls_cred_map *p; \ - for(p = cred_mappings; p->type != 0; p++) { b ; } + for(p = cred_mappings; p->algorithm != 0; p++) { b ; } -#define GNUTLS_KX_MAP_ALG_LOOP(a) \ - GNUTLS_KX_MAP_LOOP( if(p->type == type) { a; break; }) +#define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \ + GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; break; }) + +#define GNUTLS_KX_MAP_ALG_LOOP_CLIENT(a) \ + GNUTLS_KX_MAP_LOOP( if(p->client_type == type) { a; break; }) /* TLS Versions */ @@ -234,6 +240,7 @@ typedef struct { #define GNUTLS_SRP_SHA_RIJNDAEL_128_CBC_SHA { 0x00, 0x53 } #define GNUTLS_SRP_SHA_RIJNDAEL_256_CBC_SHA { 0x00, 0x56 } +#define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA { 0x00, 0x51 } /** RSA **/ @@ -316,6 +323,10 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = { GNUTLS_CIPHER_RIJNDAEL_256_CBC, GNUTLS_KX_SRP, GNUTLS_MAC_SHA, GNUTLS_TLS1), + GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA, + GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP_RSA, + GNUTLS_MAC_SHA, GNUTLS_TLS1), + /* DHE_DSS */ GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_DHE_DSS_ARCFOUR_SHA, GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_KX_DHE_DSS, @@ -805,18 +816,26 @@ int ret=0; } /* Type to KX mappings */ -gnutls_kx_algorithm _gnutls_map_kx_get_kx(gnutls_credentials_type type) +gnutls_kx_algorithm _gnutls_map_kx_get_kx(gnutls_credentials_type type, int server) { gnutls_kx_algorithm ret = -1; - GNUTLS_KX_MAP_ALG_LOOP(ret = p->algorithm); + if (server) { + GNUTLS_KX_MAP_ALG_LOOP_SERVER(ret = p->algorithm); + } else { + GNUTLS_KX_MAP_ALG_LOOP_SERVER(ret = p->algorithm); + } return ret; } -gnutls_credentials_type _gnutls_map_kx_get_cred(gnutls_kx_algorithm algorithm) +gnutls_credentials_type _gnutls_map_kx_get_cred(gnutls_kx_algorithm algorithm, int server) { gnutls_credentials_type ret = -1; - GNUTLS_KX_MAP_LOOP(if (p->algorithm==algorithm) ret = p->type); + if (server) { + GNUTLS_KX_MAP_LOOP(if (p->algorithm==algorithm) ret = p->server_type); + } else { + GNUTLS_KX_MAP_LOOP(if (p->algorithm==algorithm) ret = p->client_type); + } return ret; } diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index 944996ae57..b3b041802e 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -77,8 +77,8 @@ int _gnutls_compression_get_comp_level(gnutls_compression_method algorithm); int _gnutls_compression_get_wbits(gnutls_compression_method algorithm); /* Type to KX mappings */ -gnutls_kx_algorithm _gnutls_map_kx_get_kx(gnutls_credentials_type type); -gnutls_credentials_type _gnutls_map_kx_get_cred(gnutls_kx_algorithm algorithm); +gnutls_kx_algorithm _gnutls_map_kx_get_kx(gnutls_credentials_type type, int server); +gnutls_credentials_type _gnutls_map_kx_get_cred(gnutls_kx_algorithm algorithm, int server); struct gnutls_kx_algo_entry { const char *name; diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c index c23b6fc1c3..5bed7f9c52 100644 --- a/lib/gnutls_auth.c +++ b/lib/gnutls_auth.c @@ -137,20 +137,29 @@ int gnutls_credentials_set( gnutls_session session, gnutls_credentials_type type * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA), * the same function are to be used to access the authentication data. **/ -gnutls_credentials_type gnutls_auth_get_type( gnutls_session session) { +gnutls_credentials_type gnutls_auth_get_type( gnutls_session session) +{ +/* This is not the credentials we must set, but the authentication data + * we get by the peer, so it should be reversed. + */ +int server = session->security_parameters.entity==GNUTLS_SERVER?0:1; return _gnutls_map_kx_get_cred( _gnutls_cipher_suite_get_kx_algo - (session->security_parameters.current_cipher_suite)); + (session->security_parameters.current_cipher_suite), server); } /* * This returns an pointer to the linked list. Don't * free that!!! */ -const void *_gnutls_get_kx_cred( GNUTLS_KEY key, gnutls_kx_algorithm algo, int *err) { - return _gnutls_get_cred( key, _gnutls_map_kx_get_cred(algo), err); +const void *_gnutls_get_kx_cred( gnutls_session session, gnutls_kx_algorithm algo, int *err) +{ +int server = session->security_parameters.entity==GNUTLS_SERVER?1:0; + + return _gnutls_get_cred( session->key, _gnutls_map_kx_get_cred(algo, server), err); } + const void *_gnutls_get_cred( GNUTLS_KEY key, gnutls_credentials_type type, int *err) { AUTH_CRED * ccred; diff --git a/lib/gnutls_auth_int.h b/lib/gnutls_auth_int.h index a91d03d226..a62de07565 100644 --- a/lib/gnutls_auth_int.h +++ b/lib/gnutls_auth_int.h @@ -1,7 +1,7 @@ int gnutls_clear_creds( gnutls_session session); int gnutls_credentials_set( gnutls_session session, gnutls_credentials_type type, void* cred); const void *_gnutls_get_cred( GNUTLS_KEY key, gnutls_credentials_type kx, int* err); -const void *_gnutls_get_kx_cred( GNUTLS_KEY key, gnutls_kx_algorithm algo, int *err); +const void *_gnutls_get_kx_cred( gnutls_session session, gnutls_kx_algorithm algo, int *err); int _gnutls_generate_key(GNUTLS_KEY key); gnutls_credentials_type gnutls_auth_get_type( gnutls_session session); void* _gnutls_get_auth_info( gnutls_session session); diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 4deab906a9..2ddf17b937 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -57,6 +57,7 @@ static const gnutls_pk_map pk_mappings[] = { {GNUTLS_KX_RSA, GNUTLS_PK_RSA}, {GNUTLS_KX_RSA_EXPORT, GNUTLS_PK_RSA}, {GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA}, + {GNUTLS_KX_SRP_RSA, GNUTLS_PK_RSA}, {GNUTLS_KX_DHE_DSS, GNUTLS_PK_DSA}, {0} }; diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 8c484e8d17..6771fcb8a7 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -505,7 +505,7 @@ int _gnutls_recv_finished(gnutls_session session) /* returns PK_RSA if the given cipher suite list only supports, * RSA algorithms, PK_DSA if DSS, and -1 if both or none. */ -int _gnutls_find_pk_algos_in_ciphersuites( opaque* data, int datalen) { +int _gnutls_server_find_pk_algos_in_ciphersuites( opaque* data, int datalen) { int j; gnutls_pk_algorithm algo=-1, prev_algo = 0; gnutls_kx_algorithm kx; @@ -513,7 +513,7 @@ gnutls_kx_algorithm kx; for (j = 0; j < datalen; j += 2) { kx = _gnutls_cipher_suite_get_kx_algo(*((GNUTLS_CipherSuite *) & data[j])); - if ( _gnutls_map_kx_get_cred( kx) == GNUTLS_CRD_CERTIFICATE) { + if ( _gnutls_map_kx_get_cred( kx, 1) == GNUTLS_CRD_CERTIFICATE) { algo = _gnutls_map_pk_get_pk( kx); if (algo!=prev_algo && prev_algo!=0) return -1; @@ -537,7 +537,7 @@ int _gnutls_server_select_suite(gnutls_session session, opaque *data, int datale * supported by the peer. */ - pk_algo = _gnutls_find_pk_algos_in_ciphersuites( data, datalen); + pk_algo = _gnutls_server_find_pk_algos_in_ciphersuites( data, datalen); x = _gnutls_supported_ciphersuites(session, &ciphers); if (x < 0) { /* the case x==0 is handled within the function. */ @@ -597,8 +597,7 @@ int _gnutls_server_select_suite(gnutls_session session, opaque *data, int datale /* check if the credentials (username, public key etc. are ok) */ if (_gnutls_get_kx_cred - (session->key, - _gnutls_cipher_suite_get_kx_algo(session->security_parameters. + (session, _gnutls_cipher_suite_get_kx_algo(session->security_parameters. current_cipher_suite), &err) == NULL && err != 0) { gnutls_assert(); @@ -1108,8 +1107,7 @@ static int _gnutls_client_set_ciphersuite(gnutls_session session, * Actually checks if they exist. */ if (_gnutls_get_kx_cred - (session->key, - _gnutls_cipher_suite_get_kx_algo(session-> + (session, _gnutls_cipher_suite_get_kx_algo(session-> security_parameters. current_cipher_suite), &err) == NULL && err != 0) { @@ -2335,7 +2333,7 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session, gnutls_kx_algorithm *alg; int alg_size; gnutls_kx_algorithm kx; - + int server = session->security_parameters.entity==GNUTLS_SERVER?1:0; /* if we should use a specific certificate, * we should remove all algorithms that are not supported @@ -2390,22 +2388,22 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session, /* if it is defined but had no credentials */ - if (_gnutls_get_kx_cred - (session->key, kx, NULL) == NULL) { + if (_gnutls_get_kx_cred(session, kx, NULL) == NULL) { keep = 1; } else /* If there was no credentials to use with the specified * key exchange method, then just remove it. */ - if (_gnutls_map_kx_get_cred(kx) == GNUTLS_CRD_CERTIFICATE) { + if (_gnutls_map_kx_get_cred(kx, server) == GNUTLS_CRD_CERTIFICATE) { keep = 1; /* do not keep */ if (x509_cred != NULL) { - if (session->security_parameters.entity == - GNUTLS_SERVER) { + if (server) { /* here we check if the KX algorithm * is compatible with the certificate. */ +fprintf(stderr, "KX: %d\n", kx); for (j = 0; j < alg_size; j++) { +fprintf(stderr, "ALG: %d\n", alg[j]); if (alg[j] == kx) { keep = 0; break; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 260f6d318b..281ba655c8 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -159,7 +159,7 @@ typedef enum gnutls_cipher_algorithm { GNUTLS_CIPHER_NULL=1, typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_ANON_DH, GNUTLS_KX_SRP, - GNUTLS_KX_RSA_EXPORT + GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA } gnutls_kx_algorithm; typedef enum gnutls_mac_algorithm { GNUTLS_MAC_NULL=1, GNUTLS_MAC_MD5, GNUTLS_MAC_SHA } gnutls_mac_algorithm; diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c index 8271672719..01225468f1 100644 --- a/lib/gnutls_v2_compat.c +++ b/lib/gnutls_v2_compat.c @@ -156,7 +156,7 @@ int _gnutls_read_client_hello_v2(gnutls_session session, opaque * data, /* check if the credentials (username, public key etc. are ok) */ - if (_gnutls_get_kx_cred( session->key, _gnutls_cipher_suite_get_kx_algo(session->security_parameters.current_cipher_suite), &err) == NULL && err != 0) { + if (_gnutls_get_kx_cred( session, _gnutls_cipher_suite_get_kx_algo(session->security_parameters.current_cipher_suite), &err) == NULL && err != 0) { gnutls_assert(); return GNUTLS_E_INSUFICIENT_CREDENTIALS; } diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 5b8a285fd9..59f46a47ee 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -2212,10 +2212,14 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert, /* Returns 0 if it's ok to use the gnutls_kx_algorithm with this * certificate (uses the KeyUsage field). */ -int _gnutls_check_x509_key_usage(const gnutls_cert * cert, +int _gnutls_check_x509_key_usage( const gnutls_cert * cert, gnutls_kx_algorithm alg) { - if (_gnutls_map_kx_get_cred(alg) == GNUTLS_CRD_CERTIFICATE) { + + /* FIXME: check here */ + if (_gnutls_map_kx_get_cred(alg, 1) == GNUTLS_CRD_CERTIFICATE || + _gnutls_map_kx_get_cred(alg, 0) == GNUTLS_CRD_CERTIFICATE) + { switch (alg) { case GNUTLS_KX_RSA: if (cert->keyUsage != 0) { @@ -2228,6 +2232,7 @@ int _gnutls_check_x509_key_usage(const gnutls_cert * cert, return 0; } return 0; + case GNUTLS_KX_SRP_RSA: case GNUTLS_KX_DHE_RSA: case GNUTLS_KX_DHE_DSS: case GNUTLS_KX_RSA_EXPORT: diff --git a/libextra/Makefile.am b/libextra/Makefile.am index 4825a71985..6caf8869f4 100644 --- a/libextra/Makefile.am +++ b/libextra/Makefile.am @@ -15,7 +15,8 @@ lib_LTLIBRARIES = libgnutls-extra.la COBJECTS_EXTRA = crypt.c crypt_srpsha1.c ext_srp.c \ gnutls_srp.c auth_srp.c auth_srp_passwd.c auth_srp_sb64.c \ - gnutls_openpgp.c gnutls_extra.c gnutls_openssl.c minilzo.c + gnutls_openpgp.c gnutls_extra.c gnutls_openssl.c minilzo.c \ + auth_srp_rsa.c libgnutls_extra_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ $(LIBOPENCDK_LIBS) diff --git a/libextra/auth_srp.c b/libextra/auth_srp.c index 7333b6942e..7d01073222 100644 --- a/libextra/auth_srp.c +++ b/libextra/auth_srp.c @@ -32,19 +32,19 @@ #include "auth_srp.h" #include <gnutls_str.h> -int gen_srp_server_kx2(gnutls_session, opaque **); -int gen_srp_client_kx0(gnutls_session, opaque **); +int _gnutls_gen_srp_server_kx2(gnutls_session, opaque **); +int _gnutls_gen_srp_client_kx0(gnutls_session, opaque **); -int proc_srp_server_kx2(gnutls_session, opaque *, size_t); -int proc_srp_client_kx0(gnutls_session, opaque *, size_t); +int _gnutls_proc_srp_server_kx2(gnutls_session, opaque *, size_t); +int _gnutls_proc_srp_client_kx0(gnutls_session, opaque *, size_t); const MOD_AUTH_STRUCT srp_auth_struct = { "SRP", NULL, NULL, NULL, - gen_srp_server_kx2, - gen_srp_client_kx0, + _gnutls_gen_srp_server_kx2, + _gnutls_gen_srp_client_kx0, NULL, NULL, NULL, @@ -52,8 +52,8 @@ const MOD_AUTH_STRUCT srp_auth_struct = { NULL, NULL, /* certificate */ NULL, - proc_srp_server_kx2, - proc_srp_client_kx0, + _gnutls_proc_srp_server_kx2, + _gnutls_proc_srp_client_kx0, NULL, NULL, NULL @@ -72,7 +72,7 @@ const MOD_AUTH_STRUCT srp_auth_struct = { /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ -int gen_srp_server_hello(gnutls_session state, opaque * data, size_t _data_size) +int _gnutls_gen_srp_server_hello(gnutls_session state, opaque * data, size_t _data_size) { size_t n_g, n_n, n_s; int ret; @@ -170,7 +170,7 @@ int gen_srp_server_hello(gnutls_session state, opaque * data, size_t _data_size) } /* send the second key exchange message */ -int gen_srp_server_kx2(gnutls_session state, opaque ** data) +int _gnutls_gen_srp_server_kx2(gnutls_session state, opaque ** data) { int ret; size_t n_b; @@ -232,7 +232,7 @@ int gen_srp_server_kx2(gnutls_session state, opaque ** data) /* return A = g^a % N */ -int gen_srp_client_kx0(gnutls_session state, opaque ** data) +int _gnutls_gen_srp_client_kx0(gnutls_session state, opaque ** data) { size_t n_a; uint8 *data_a; @@ -249,10 +249,13 @@ int gen_srp_client_kx0(gnutls_session state, opaque ** data) username = cred->username; password = cred->password; - if (username == NULL || password == NULL) + if (username == NULL || password == NULL) { + gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; + } - /* calc A = g^a % N */ + /* calc A = g^a % N + */ if (G == NULL || N == NULL) { gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; @@ -264,8 +267,10 @@ int gen_srp_client_kx0(gnutls_session state, opaque ** data) return GNUTLS_E_MEMORY_ERROR; } - if (_gnutls_mpi_print( NULL, &n_a, A)!=0) + if (_gnutls_mpi_print( NULL, &n_a, A)!=0) { + gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; + } (*data) = gnutls_malloc(n_a + 2); if ( (*data) == NULL) { @@ -286,7 +291,7 @@ int gen_srp_client_kx0(gnutls_session state, opaque ** data) } /* receive the first key exchange message ( g, n, s) */ -int proc_srp_server_hello(gnutls_session state, const opaque * data, size_t _data_size) +int _gnutls_proc_srp_server_hello(gnutls_session state, const opaque * data, size_t _data_size) { uint8 n_s; uint16 n_g, n_n; @@ -372,7 +377,7 @@ int proc_srp_server_hello(gnutls_session state, const opaque * data, size_t _dat } /* just read A and put it to state */ -int proc_srp_client_kx0(gnutls_session state, opaque * data, size_t _data_size) +int _gnutls_proc_srp_client_kx0(gnutls_session state, opaque * data, size_t _data_size) { size_t _n_A; ssize_t data_size = _data_size; @@ -390,7 +395,7 @@ int proc_srp_client_kx0(gnutls_session state, opaque * data, size_t _data_size) } -int proc_srp_server_kx2(gnutls_session state, opaque * data, size_t _data_size) +int _gnutls_proc_srp_server_kx2(gnutls_session state, opaque * data, size_t _data_size) { size_t _n_B; ssize_t data_size = _data_size; @@ -432,7 +437,9 @@ int proc_srp_server_kx2(gnutls_session state, opaque * data, size_t _data_size) if (ret < 0) return ret; - return 0; + return _data_size - data_size; /* return the remaining data + * needed in auth_srp_rsa. + */ } #endif /* ENABLE_SRP */ diff --git a/libextra/auth_srp.h b/libextra/auth_srp.h index 988e24f5ef..463ce94340 100644 --- a/libextra/auth_srp.h +++ b/libextra/auth_srp.h @@ -1,5 +1,7 @@ -#include <gnutls_auth.h> +#ifndef AUTH_SRP_H +# define AUTH_SRP_H +#include <gnutls_auth.h> typedef struct { char* username; @@ -23,9 +25,17 @@ typedef struct SRP_SERVER_AUTH_INFO_INT { #ifdef ENABLE_SRP -int proc_srp_server_hello(gnutls_session state, const opaque * data, size_t data_size); -int gen_srp_server_hello(gnutls_session state, opaque * data, size_t data_size); +int _gnutls_proc_srp_server_hello(gnutls_session state, const opaque * data, size_t data_size); +int _gnutls_gen_srp_server_hello(gnutls_session state, opaque * data, size_t data_size); + +int _gnutls_gen_srp_server_kx2(gnutls_session, opaque **); +int _gnutls_gen_srp_client_kx0(gnutls_session, opaque **); + +int _gnutls_proc_srp_server_kx2(gnutls_session, opaque *, size_t); +int _gnutls_proc_srp_client_kx0(gnutls_session, opaque *, size_t); typedef struct SRP_SERVER_AUTH_INFO_INT SRP_SERVER_AUTH_INFO_INT; #endif /* ENABLE_SRP */ + +#endif diff --git a/libextra/auth_srp_rsa.c b/libextra/auth_srp_rsa.c new file mode 100644 index 0000000000..466482a2cc --- /dev/null +++ b/libextra/auth_srp_rsa.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2001,2002 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS-EXTRA 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-EXTRA 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 "gnutls_int.h" + +#ifdef ENABLE_SRP + +#include "gnutls_errors.h" +#include "auth_srp_passwd.h" +#include "gnutls_auth.h" +#include "gnutls_auth_int.h" +#include "gnutls_srp.h" +#include "debug.h" +#include "gnutls_num.h" +#include "auth_srp.h" +#include <gnutls_str.h> +#include <auth_cert.h> +#include <x509_verify.h> +#include <gnutls_datum.h> +#include <gnutls_sig.h> +#include <auth_srp.h> +#include <gnutls_x509.h> +#include <gnutls_extra.h> + +static int gen_srp_rsa_server_kx2(gnutls_session, opaque **); +static int proc_srp_rsa_server_kx2(gnutls_session, opaque *, size_t); + +const MOD_AUTH_STRUCT srp_rsa_auth_struct = { + "SRP", + _gnutls_gen_cert_server_certificate, + NULL, + NULL, + gen_srp_rsa_server_kx2, + _gnutls_gen_srp_client_kx0, + NULL, + NULL, + NULL, + + _gnutls_proc_cert_server_certificate, + NULL, /* certificate */ + NULL, + proc_srp_rsa_server_kx2, + _gnutls_proc_srp_client_kx0, + NULL, + NULL, + NULL +}; + + +static int gen_srp_rsa_server_kx2(gnutls_session session, opaque ** data) +{ +ssize_t ret, data_size; +gnutls_datum signature, ddata; +const gnutls_certificate_credentials cred; +gnutls_cert *apr_cert_list; +gnutls_private_key *apr_pkey; +int apr_cert_list_length; + + ret = _gnutls_gen_srp_server_kx2( session, data); + + if (ret < 0) return ret; + + data_size = ret; + ddata.data = *data; + ddata.size = data_size; + + cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFICIENT_CREDENTIALS; + } + + /* find the appropriate certificate */ + if ((ret = + _gnutls_find_apr_cert(session, &apr_cert_list, + &apr_cert_list_length, + &apr_pkey)) < 0) { + gnutls_assert(); + return ret; + } + + if ((ret = + _gnutls_generate_sig_params(session, &apr_cert_list[0], + apr_pkey, &ddata, &signature)) < 0) + { + gnutls_assert(); + gnutls_free(*data); + return ret; + } + + *data = gnutls_realloc_fast(*data, data_size + signature.size + 2); + if (*data == NULL) { + gnutls_free_datum(&signature); + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gnutls_write_datum16(&(*data)[data_size], signature); + data_size += signature.size + 2; + + gnutls_free_datum(&signature); + + return data_size; + +} + +extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; + +static int proc_srp_rsa_server_kx2(gnutls_session session, opaque * data, size_t _data_size) +{ +ssize_t ret; +int i, sigsize; +gnutls_datum vparams, signature; +ssize_t data_size; +CERTIFICATE_AUTH_INFO info; +gnutls_cert peer_cert; +opaque* p; + + ret = _gnutls_proc_srp_server_kx2( session, data, _data_size); + if (ret < 0) return ret; + + data_size = _data_size - ret; + + info = _gnutls_get_auth_info( session); + if (info == NULL || info->ncerts==0) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_INTERNAL_ERROR; + } + + /* VERIFY SIGNATURE */ + + vparams.size = ret; /* all the data minus the signature */ + vparams.data = data; + + p = &data[vparams.size]; + + DECR_LEN( data_size, 2); + sigsize = _gnutls_read_uint16( p); + + DECR_LEN( data_size, sigsize); + signature.data = &p[2]; + signature.size = sigsize; + + switch( session->security_parameters.cert_type) { + case GNUTLS_CRT_X509: + if ((ret = + _gnutls_x509_cert2gnutls_cert( &peer_cert, + info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { + gnutls_assert(); + return ret; + } + break; + + case GNUTLS_CRT_OPENPGP: + if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { + gnutls_assert(); + return GNUTLS_E_INIT_LIBEXTRA; + } + if ((ret = + _E_gnutls_openpgp_cert2gnutls_cert( &peer_cert, + info->raw_certificate_list[0])) < 0) { + gnutls_assert(); + return ret; + } + break; + + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + ret = + _gnutls_verify_sig_params(session, + &peer_cert, + &vparams, &signature); + + _gnutls_free_cert( peer_cert); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + + +#endif /* ENABLE_SRP */ diff --git a/libextra/ext_srp.c b/libextra/ext_srp.c index 3ebd31cf16..957ec92529 100644 --- a/libextra/ext_srp.c +++ b/libextra/ext_srp.c @@ -32,8 +32,9 @@ int _gnutls_srp_recv_params( gnutls_session state, const opaque* data, size_t _d uint8 len; ssize_t data_size = _data_size; - if (_gnutls_kx_priority( state, GNUTLS_KX_SRP) < 0) { - /* algorithm was not allowed in this state + if (_gnutls_kx_priority( state, GNUTLS_KX_SRP) < 0 && + _gnutls_kx_priority( state, GNUTLS_KX_SRP_RSA) < 0) { + /* algorithm was not allowed in this session */ return 0; } @@ -52,7 +53,7 @@ int _gnutls_srp_recv_params( gnutls_session state, const opaque* data, size_t _d } } else { /* client side reading server hello extensions */ if (state->internals.resumed==RESUME_FALSE) - return proc_srp_server_hello( state, data, data_size); + return _gnutls_proc_srp_server_hello( state, data, data_size); else /* we do not need to process this if * we are resuming. */ @@ -61,14 +62,25 @@ int _gnutls_srp_recv_params( gnutls_session state, const opaque* data, size_t _d return 0; } +/* Checks if the given cipher suite is an SRP one + */ +inline static int is_srp( GNUTLS_CipherSuite suite) { + int kx = _gnutls_cipher_suite_get_kx_algo( suite); + + if (kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA)) return 1; + + return 0; +} + /* returns data_size or a negative number on failure * data is allocated localy */ int _gnutls_srp_send_params( gnutls_session state, opaque* data, size_t data_size) { uint len; - if (_gnutls_kx_priority( state, GNUTLS_KX_SRP) < 0) { - /* algorithm was not allowed in this state + if (_gnutls_kx_priority( state, GNUTLS_KX_SRP) < 0 && + _gnutls_kx_priority( state, GNUTLS_KX_SRP_RSA) < 0) { + /* algorithm was not allowed in this session */ return 0; } @@ -97,11 +109,12 @@ int _gnutls_srp_send_params( gnutls_session state, opaque* data, size_t data_siz /* note that security parameters are not fully established */ - if ( _gnutls_cipher_suite_get_kx_algo(state->security_parameters.current_cipher_suite) != GNUTLS_KX_SRP) + + if ( !is_srp(state->security_parameters.current_cipher_suite)) return 0; /* no data to send */ if (state->internals.resumed==RESUME_FALSE) - return gen_srp_server_hello( state, data, data_size); + return _gnutls_gen_srp_server_hello( state, data, data_size); else return 0; } diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c index 2dab1b5d09..608266ac32 100644 --- a/libextra/gnutls_extra.c +++ b/libextra/gnutls_extra.c @@ -57,6 +57,7 @@ int i; extern const int _gnutls_kx_algorithms_size; extern gnutls_kx_algo_entry _gnutls_kx_algorithms[]; extern MOD_AUTH_STRUCT srp_auth_struct; +extern MOD_AUTH_STRUCT srp_rsa_auth_struct; static int _gnutls_add_srp_auth_struct(void) { int i; @@ -73,6 +74,16 @@ int i; _gnutls_kx_algorithms[i+1].name = 0; + } + i++; + + if (_gnutls_kx_algorithms[i].name==NULL && (i < _gnutls_kx_algorithms_size-1)) { + _gnutls_kx_algorithms[i].name = "SRP_RSA"; + _gnutls_kx_algorithms[i].algorithm = GNUTLS_KX_SRP_RSA; + _gnutls_kx_algorithms[i].auth_struct = &srp_rsa_auth_struct; + + _gnutls_kx_algorithms[i+1].name = 0; + return 0; /* ok */ } diff --git a/libextra/gnutls_extra.h b/libextra/gnutls_extra.h index 3793363001..e1f6d67bdc 100644 --- a/libextra/gnutls_extra.h +++ b/libextra/gnutls_extra.h @@ -5,5 +5,5 @@ typedef int (*OPENPGP_VERIFY_KEY_FUNC)( const char *, typedef time_t (*OPENPGP_KEY_CREATION_TIME_FUNC)( const gnutls_datum*); typedef time_t (*OPENPGP_KEY_EXPIRATION_TIME_FUNC)( const gnutls_datum*); typedef int (*OPENPGP_KEY_REQUEST)(gnutls_datum*, const gnutls_certificate_credentials, opaque*,int); -typedef int (*OPENPGP_FINGERPRINT)(const gnutls_datum*, char*, size_t*); +typedef int (*OPENPGP_FINGERPRINT)(const gnutls_datum*, unsigned char*, size_t*); typedef int (*OPENPGP_CERT2GNUTLS_CERT)(gnutls_cert*, gnutls_datum); @@ -506,8 +506,10 @@ void gaa_parser(int argc, char **argv) if (info.kx != NULL && info.nkx > 0) { for (j = i = 0; i < info.nkx; i++) { - if (strncasecmp(info.kx[i], "SRP", 3) == 0) + if (strcasecmp(info.kx[i], "SRP") == 0) kx_priority[j++] = GNUTLS_KX_SRP; + if (strcasecmp(info.kx[i], "SRP-RSA") == 0) + kx_priority[j++] = GNUTLS_KX_SRP_RSA; if (strcasecmp(info.kx[i], "RSA") == 0) kx_priority[j++] = GNUTLS_KX_RSA; if (strcasecmp(info.kx[i], "RSA-EXPORT") == 0) diff --git a/src/common.c b/src/common.c index bb0febbd33..9038bcb811 100644 --- a/src/common.c +++ b/src/common.c @@ -373,6 +373,7 @@ void print_list(void) printf(", DHE-DSS"); printf(", DHE-RSA"); printf(", SRP"); + printf(", SRP-RSA"); printf(", ANON-DH\n"); printf("Compression methods:"); diff --git a/src/serv.c b/src/serv.c index 48828ae4a0..f0a508f68b 100644 --- a/src/serv.c +++ b/src/serv.c @@ -986,8 +986,10 @@ void gaa_parser(int argc, char **argv) if (info.kx != NULL && info.nkx > 0) { for (j = i = 0; i < info.nkx; i++) { - if (strncasecmp(info.kx[i], "SRP", 3) == 0) + if (strcasecmp(info.kx[i], "SRP") == 0) kx_priority[j++] = GNUTLS_KX_SRP; + if (strcasecmp(info.kx[i], "SRP-RSA") == 0) + kx_priority[j++] = GNUTLS_KX_SRP_RSA; if (strcasecmp(info.kx[i], "RSA") == 0) kx_priority[j++] = GNUTLS_KX_RSA; if (strcasecmp(info.kx[i], "RSA-EXPORT") == 0) |