summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--lib/auth_cert.c2
-rw-r--r--lib/gnutls.h.in.in2
-rw-r--r--lib/gnutls_algorithms.c47
-rw-r--r--lib/gnutls_algorithms.h4
-rw-r--r--lib/gnutls_auth.c17
-rw-r--r--lib/gnutls_auth_int.h2
-rw-r--r--lib/gnutls_cert.c1
-rw-r--r--lib/gnutls_handshake.c24
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/gnutls_v2_compat.c2
-rw-r--r--lib/gnutls_x509.c9
-rw-r--r--libextra/Makefile.am3
-rw-r--r--libextra/auth_srp.c43
-rw-r--r--libextra/auth_srp.h16
-rw-r--r--libextra/auth_srp_rsa.c205
-rw-r--r--libextra/ext_srp.c27
-rw-r--r--libextra/gnutls_extra.c11
-rw-r--r--libextra/gnutls_extra.h2
-rw-r--r--src/cli.c4
-rw-r--r--src/common.c1
-rw-r--r--src/serv.c4
22 files changed, 357 insertions, 72 deletions
diff --git a/NEWS b/NEWS
index d20de755c0..1ad473bdf6 100644
--- a/NEWS
+++ b/NEWS
@@ -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);
diff --git a/src/cli.c b/src/cli.c
index f5b166f45d..027c47fd30 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -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)