]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
several additions for x509 client authentication
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 6 Aug 2001 13:21:50 +0000 (13:21 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 6 Aug 2001 13:21:50 +0000 (13:21 +0000)
lib/Makefile.am
lib/auth_rsa.c
lib/gnutls_cert.h
lib/gnutls_handshake.c
lib/gnutls_int.h
lib/gnutls_kx.c
lib/gnutls_pk.c
lib/gnutls_sig.c [new file with mode: 0644]
lib/gnutls_sig.h
src/cli.c
src/x509/Makefile.am

index 91b28492b1f0987839b43d73521b72a50a686b99..e68db36a3ad246b389726966ef9f28f54b635e57 100644 (file)
@@ -30,7 +30,7 @@ libgnutls_la_SOURCES = gnutls_record.c gnutls_compress.c debug.c \
        gnutls_gcry.c ext_dnsname.c gnutls_pk.c gnutls_cert.c x509_verify.c\
        gnutls_global.c gnutls_privkey.c gnutls_constate.c gnutls_anon_cred.c \
        gnutls_sig_check.c pkix_asn1_tab.c pkcs1_asn1_tab.c gnutls_mem.c \
-       x509_extensions.c auth_x509.c gnutls_ui.c
+       x509_extensions.c auth_x509.c gnutls_ui.c gnutls_sig.c
 
 libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
index f3fd7bfd49f855d9c249384442aed2460946ddd4..905c7667f3bdef3ab605c07534098803472daeb9 100644 (file)
 #include <gnutls_global.h>
 #include <x509_verify.h>
 #include "debug.h"
+#include <gnutls_sig.h>
 
 int gen_rsa_certificate(GNUTLS_STATE, opaque **);
+int gen_rsa_client_cert_vrfy(GNUTLS_STATE, opaque **);
 int proc_rsa_cert_req(GNUTLS_STATE, opaque *, int);
 int gen_rsa_client_kx(GNUTLS_STATE, opaque **);
 int proc_rsa_client_kx(GNUTLS_STATE, opaque *, int);
 int proc_rsa_certificate(GNUTLS_STATE, opaque *, int);
 
-MOD_AUTH_STRUCT rsa_auth_struct = {
+MOD_AUTH_STRUCT rsa_auth_struct =
+{
        "RSA",
        gen_rsa_certificate,
        NULL,                   /* gen server kx */
        NULL,                   /* gen server kx2 */
        NULL,                   /* gen client kx0 */
        gen_rsa_client_kx,
-       NULL,                   /* gen client cert vrfy */
+       gen_rsa_client_cert_vrfy, /* gen client cert vrfy */
        NULL,
 
        proc_rsa_certificate,
@@ -67,28 +70,25 @@ typedef struct {
 
 /* This function extracts the RSA parameters from the given(?) certificate.
  */
-static int _gnutls_get_rsa_params( RSA_Params * params,
+static int _gnutls_get_rsa_params(RSA_Params * params,
                                  MPI * mod, MPI * exp, gnutls_datum cert)
 {
        int ret = 0, result;
        opaque str[5 * 1024];
        int len = sizeof(str);
        node_asn *srsa, *spk;
-       
-       if (asn1_create_structure( _gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &srsa, "rsa_params")
+
+       if (asn1_create_structure(_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &srsa, "rsa_params")
            != ASN_OK) {
                gnutls_assert();
                return GNUTLS_E_ASN1_ERROR;
        }
-
-       result = asn1_get_der( srsa, cert.data, cert.size);
+       result = asn1_get_der(srsa, cert.data, cert.size);
        if (result != ASN_OK) {
                /* couldn't decode DER */
                gnutls_assert();
                return GNUTLS_E_ASN1_PARSING_ERROR;
        }
-
-
        len = sizeof(str) - 1;
        result =
            asn1_read_value
@@ -100,7 +100,6 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                asn1_delete_structure(srsa);
                return GNUTLS_E_ASN1_PARSING_ERROR;
        }
-
        if (!strcmp(str, "1 2 840 113549 1 1 1")) {     /* pkix-1 1 - RSA */
                len = sizeof(str) - 1;
                result =
@@ -113,20 +112,17 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                        gnutls_assert();
                        return GNUTLS_E_ASN1_PARSING_ERROR;
                }
-
                if (asn1_create_structure
-                   ( _gnutls_get_pkcs(),
+                   (_gnutls_get_pkcs(),
                     "PKCS-1.RSAPublicKey", &spk, "rsa_public_key") != ASN_OK) {
                        gnutls_assert();
                        return GNUTLS_E_ASN1_ERROR;
                }
-
                if (len % 8 != 0) {
                        gnutls_assert();
                        asn1_delete_structure(spk);
                        return GNUTLS_E_UNIMPLEMENTED_FEATURE;
                }
-               
                result = asn1_get_der(spk, str, len / 8);
 
                if (result != ASN_OK) {
@@ -134,7 +130,6 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                        asn1_delete_structure(spk);
                        return GNUTLS_E_ASN1_PARSING_ERROR;
                }
-
                len = sizeof(str) - 1;
                result = asn1_read_value(spk, "rsa_public_key.modulus", str, &len);
                if (result != ASN_OK) {
@@ -142,13 +137,11 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                        asn1_delete_structure(spk);
                        return GNUTLS_E_ASN1_PARSING_ERROR;
                }
-
                if (gcry_mpi_scan(mod, GCRYMPI_FMT_USG, str, &len) != 0) {
                        gnutls_assert();
                        asn1_delete_structure(spk);
                        return GNUTLS_E_MPI_SCAN_FAILED;
                }
-
                if (params != NULL)
                        if (gnutls_set_datum
                            (&params->rsa_modulus, str, len) < 0) {
@@ -156,7 +149,6 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                                asn1_delete_structure(spk);
                                return GNUTLS_E_MEMORY_ERROR;
                        }
-
                len = sizeof(str) - 1;
                result =
                    asn1_read_value(spk, "rsa_public_key.publicExponent", str, &len);
@@ -168,7 +160,6 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                        _gnutls_mpi_release(mod);
                        return GNUTLS_E_ASN1_PARSING_ERROR;
                }
-
                if (gcry_mpi_scan(exp, GCRYMPI_FMT_USG, str, &len) != 0) {
                        gnutls_assert();
                        _gnutls_mpi_release(mod);
@@ -188,7 +179,6 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
                                asn1_delete_structure(spk);
                                return GNUTLS_E_MEMORY_ERROR;
                        }
-
                asn1_delete_structure(spk);
 
                ret = 0;
@@ -214,7 +204,7 @@ static int _gnutls_get_rsa_params( RSA_Params * params,
  * to the gnutls_private_key structure.
  */
 static int _gnutls_get_private_rsa_params(GNUTLS_KEY key,
-                                         gnutls_private_key *pkey)
+                                         gnutls_private_key * pkey)
 {
 
        key->u = gcry_mpi_copy(pkey->params[0]);
@@ -238,16 +228,25 @@ int gen_rsa_certificate(GNUTLS_STATE state, opaque ** data)
                gnutls_assert();
                return GNUTLS_E_INSUFICIENT_CRED;
        }
-
        if (cred->ncerts == 0) {
                apr_cert_list = NULL;
                apr_cert_list_length = 0;
                apr_pkey = NULL;
        } else {
-               ind = _gnutls_find_cert_list_index( cred->cert_list, cred->ncerts, state->security_parameters.extensions.dnsname);
-               apr_cert_list = cred->cert_list[ind];
-               apr_cert_list_length = cred->cert_list_length[ind];
-               apr_pkey = &cred->pkey[ind];
+               if (state->security_parameters.entity == GNUTLS_CLIENT)
+                       ind = state->gnutls_internals.client_certificate_index;
+               else /* server */
+                       ind = _gnutls_find_cert_list_index(cred->cert_list, cred->ncerts, state->security_parameters.extensions.dnsname);
+
+               if (ind < 0) {
+                       apr_cert_list = NULL;
+                       apr_cert_list_length = 0;
+                       apr_pkey = NULL;
+               } else {
+                       apr_cert_list = cred->cert_list[ind];
+                       apr_cert_list_length = cred->cert_list_length[ind];
+                       apr_pkey = &cred->pkey[ind];
+               }
        }
 
        ret = 3;
@@ -264,7 +263,6 @@ int gen_rsa_certificate(GNUTLS_STATE state, opaque ** data)
                gnutls_assert();
                return GNUTLS_E_MEMORY_ERROR;
        }
-
        WRITEuint24(ret - 3, pdata);
        pdata += 3;
        for (i = 0; i < apr_cert_list_length; i++) {
@@ -276,16 +274,15 @@ int gen_rsa_certificate(GNUTLS_STATE state, opaque ** data)
        /* read the rsa parameters now, since later we will
         * not know which certificate we used!
         */
-       if (i!=0) /* if we parsed at least one certificate */
+       if (i != 0)             /* if we parsed at least one certificate */
                ret = _gnutls_get_private_rsa_params(state->gnutls_key, apr_pkey);
        else
                ret = 0;
-               
+
        if (ret < 0) {
                gnutls_assert();
                return ret;
        }
-
        return pdatasize;
 }
 
@@ -301,7 +298,7 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size)
        gnutls_datum ciphertext;
        int ret, dsize;
 
-       if (_gnutls_version_ssl3( gnutls_get_current_version( state)) == 0) {
+       if (_gnutls_version_ssl3(gnutls_get_current_version(state)) == 0) {
                /* SSL 3.0 */
                ciphertext.data = data;
                ciphertext.size = data_size;
@@ -312,7 +309,7 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size)
        }
        ret =
            _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, state->gnutls_key->u,
-                                     state->gnutls_key->A, 2); /* btype==2 */
+                                     state->gnutls_key->A, 2);         /* btype==2 */
 
        if (ret < 0) {
                /* in case decryption fails then don't inform
@@ -327,12 +324,12 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size)
                        RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc);
                } else {
                        GNUTLS_Version ver;
-                       
-                       ver = gnutls_get_current_version( state);
-                       
-                       if ( _gnutls_version_get_major( ver) != plaintext.data[0])
+
+                       ver = gnutls_get_current_version(state);
+
+                       if (_gnutls_version_get_major(ver) != plaintext.data[0])
                                ret = GNUTLS_E_DECRYPTION_FAILED;
-                       if ( _gnutls_version_get_minor( ver) != plaintext.data[1])
+                       if (_gnutls_version_get_minor(ver) != plaintext.data[1])
                                ret = GNUTLS_E_DECRYPTION_FAILED;
                        if (ret != 0) {
                                _gnutls_mpi_release(&state->gnutls_key->B);
@@ -361,18 +358,17 @@ int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size)
        const X509PKI_CREDENTIALS cred;
        int dsize = data_size;
        int i, j;
-       gnutls_certpeer_certificate_list;
+       gnutls_cert *peer_certificate_list;
        int peer_certificate_list_size = 0;
        gnutls_datum tmp;
        CertificateStatus verify;
-       
+
        cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
        if (cred == NULL) {
                gnutls_assert();
                return GNUTLS_E_INSUFICIENT_CRED;
        }
-
-       if (state->gnutls_key->auth_info==NULL)
+       if (state->gnutls_key->auth_info == NULL)
                state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO));
        if (state->gnutls_key->auth_info == NULL) {
                gnutls_assert();
@@ -388,7 +384,6 @@ int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size)
                gnutls_assert();
                return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
        }
-
        info = state->gnutls_key->auth_info;
        i = dsize;
 
@@ -406,19 +401,16 @@ int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size)
                gnutls_assert();
                return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
        }
-
-
        dsize = data_size;
        i = dsize;
        peer_certificate_list =
-           gnutls_malloc( sizeof(gnutls_cert) *
-                         ( peer_certificate_list_size));
+           gnutls_malloc(sizeof(gnutls_cert) *
+                         (peer_certificate_list_size));
 
-       if ( peer_certificate_list == NULL) {
+       if (peer_certificate_list == NULL) {
                gnutls_assert();
                return GNUTLS_E_MEMORY_ERROR;
        }
-
        p = data + 3;
        i = data_size - 3;
        j = 0;
@@ -432,12 +424,11 @@ int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size)
                tmp.size = len;
                tmp.data = p;
 
-               if ( (ret=_gnutls_cert2gnutlsCert( &peer_certificate_list[j], tmp)) < 0) {
+               if ((ret = _gnutls_cert2gnutlsCert(&peer_certificate_list[j], tmp)) < 0) {
                        gnutls_assert();
-                       gnutls_free( peer_certificate_list);
+                       gnutls_free(peer_certificate_list);
                        return ret;
                }
-
                p += len;
                i -= len + 3;
                j++;
@@ -446,22 +437,20 @@ int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size)
        /* store the required parameters for the handshake
         */
        if ((ret =
-            _gnutls_get_rsa_params( NULL, &state->gnutls_key->A, &state->gnutls_key->u,
+            _gnutls_get_rsa_params(NULL, &state->gnutls_key->A, &state->gnutls_key->u,
                                    peer_certificate_list[0].raw)) < 0) {
                gnutls_assert();
-               gnutls_free( peer_certificate_list);
+               gnutls_free(peer_certificate_list);
                return ret;
        }
-
-
        /* Verify certificate 
         */
-       verify = gnutls_verify_certificate( peer_certificate_list, peer_certificate_list_size, 
-               cred->ca_list, cred->ncas, NULL, 0);
-        _gnutls_copy_x509_client_auth_info( info, &peer_certificate_list[0], verify);
+       verify = gnutls_verify_certificate(peer_certificate_list, peer_certificate_list_size,
+                                    cred->ca_list, cred->ncas, NULL, 0);
+
+       _gnutls_copy_x509_client_auth_info(info, &peer_certificate_list[0], verify);
 
-       gnutls_free( peer_certificate_list);
+       gnutls_free(peer_certificate_list);
 
        return 0;
 }
@@ -475,7 +464,7 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data)
        MPI pkey, n;
        int ret;
        GNUTLS_Version ver;
-       
+
        if (auth == NULL) {
                /* this shouldn't have happened. The proc_certificate
                 * function should have detected that.
@@ -483,13 +472,12 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data)
                gnutls_assert();
                return GNUTLS_E_INSUFICIENT_CRED;
        }
-
        RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc);
-       
-       ver = gnutls_get_current_version( state);
-       
-       state->gnutls_key->key.data[0] = _gnutls_version_get_major( ver);
-       state->gnutls_key->key.data[1] = _gnutls_version_get_minor( ver);
+
+       ver = gnutls_get_current_version(state);
+
+       state->gnutls_key->key.data[0] = _gnutls_version_get_major(ver);
+       state->gnutls_key->key.data[1] = _gnutls_version_get_minor(ver);
 
        if ((ret =
             _gnutls_pkcs1_rsa_encrypt(&sdata, state->gnutls_key->key, state->gnutls_key->u, state->gnutls_key->A, 2)) < 0) {
@@ -498,11 +486,10 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data)
                _gnutls_mpi_release(&n);
                return ret;
        }
-
        _gnutls_mpi_release(&state->gnutls_key->A);
        _gnutls_mpi_release(&state->gnutls_key->u);
 
-       if (_gnutls_version_ssl3( ver) == 0) {
+       if (_gnutls_version_ssl3(ver) == 0) {
                /* SSL 3.0 */
                *data = sdata.data;
                return sdata.size;
@@ -521,26 +508,103 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data)
 
 }
 
-#define RSA_SIGN 1
+/* Finds the appropriate certificate depending on the cA Distinguished name
+ * advertized by the server
+ */
+static int _gnutls_find_acceptable_client_cert( const X509PKI_CREDENTIALS cred, const opaque* data, 
+       int data_size, int *ind) {
+node_asn *dn;
+int result, size;
+int indx = -1;
+int start, end, len, i, j;
+
+
+       do {
+
+               DECR_LEN(data_size, 2);
+               size = READuint16(data);
+               data += 2;
+
+               for(i=0;i<cred->ncerts;i++) {
+                       
+                       for (j=0;j<cred->cert_list_length[i];j++) {
+                               if (asn1_create_structure(_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &dn, "dn") != ASN_OK) {
+                                       gnutls_assert();
+                                       return GNUTLS_E_ASN1_ERROR;
+                               }
+
+                               result = asn1_get_der( dn, cred->cert_list[i][j].raw.data, cred->cert_list[i][j].raw.size);
+                               if (result != ASN_OK) {
+                                       /* couldn't decode DER */
+                                       gnutls_assert();
+                                       asn1_delete_structure( dn);
+                                       return GNUTLS_E_ASN1_PARSING_ERROR;
+                               }
+                               
+                               result = asn1_get_start_end_der( dn, cred->cert_list[i][j].raw.data, cred->cert_list[i][j].raw.size,
+                                               "dn.tbsCertificate.issuer", &start, &end);
+                                               
+                               if (result != ASN_OK) {
+                                       /* couldn't decode DER */
+                                       gnutls_assert();
+                                       asn1_delete_structure( dn);
+                                       return GNUTLS_E_ASN1_PARSING_ERROR;
+                               }
+                               asn1_delete_structure( dn);
+
+                               len = end - start + 1;
+
+                               if ( len != size) continue;
+                       
+                               if (memcmp( 
+                                       &cred->cert_list[i][j].raw.data[start],
+                                       data, len) == 0 ) {
+                                       indx = i;
+                                       break;
+                               }
+                       }
+                       if (indx != -1)
+                               break;
+               }
+
+               if (indx != -1)
+                       break;
 
+               /* move to next record */
+               data_size -= size;
+               if (data_size <= 0)
+                       break;
+
+               data += size;
+
+       } while (1);
+
+       if (indx==-1 && cred->ncerts > 0) /* use the first certificate */
+               indx = 0;
+               
+       *ind = indx;
+       return 0;
+}
+
+#define RSA_SIGN 1
 int proc_rsa_cert_req(GNUTLS_STATE state, opaque * data, int data_size)
 {
-       int size;
+       int size, ret;
        opaque *p = data;
        const X509PKI_CREDENTIALS cred;
        int dsize = data_size;
        int i;
        int found;
-       
+       int ind;
+
        cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
        if (cred == NULL) {
                gnutls_assert();
                return GNUTLS_E_INSUFICIENT_CRED;
        }
-
        state->gnutls_key->certificate_requested = 1;
 
-       if (state->gnutls_key->auth_info==NULL)
+       if (state->gnutls_key->auth_info == NULL)
                state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO));
        if (state->gnutls_key->auth_info == NULL) {
                gnutls_assert();
@@ -553,29 +617,87 @@ int proc_rsa_cert_req(GNUTLS_STATE state, opaque * data, int data_size)
        p += 1;
 
        found = 0;
-       for (i=0;i<size;i++,p++) {
-               DECR_LEN( dsize, 1);
-               if (*p==RSA_SIGN) found=1;
+       for (i = 0; i < size; i++, p++) {
+               DECR_LEN(dsize, 1);
+               if (*p == RSA_SIGN)
+                       found = 1;
        }
-       
-       if (found==0) {
+
+       if (found == 0) {
                gnutls_assert();
                return GNUTLS_E_UNKNOWN_KX_ALGORITHM;
        }
-
-
-
        DECR_LEN(dsize, 2);
        size = READuint16(p);
        p += 2;
-fprintf(stderr, "DN size: %d\n", size);
 
        if (size == 0) {
                return 0;
        }
 
-#warning "FIND CERTIFICATE TO SEND"
-//fprintf(stderr, "DN: %s\n", _gnutls_bin2hex( p, size));
+       if ( (ret = _gnutls_find_acceptable_client_cert( cred, p, size, &ind)) < 0) {
+               gnutls_assert();
+               return ret;
+       }
+
+       /* put the index of the client certificate to use
+        */
+       state->gnutls_internals.client_certificate_index = ind;
 
        return 0;
 }
+
+int gen_rsa_client_cert_vrfy(GNUTLS_STATE state, opaque ** data)
+{
+       const X509PKI_CREDENTIALS cred;
+       int ret, ind;
+       gnutls_cert *apr_cert_list;
+       gnutls_private_key *apr_pkey;
+       int apr_cert_list_length, size;
+       gnutls_datum signature;
+
+       cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL);
+       if (cred == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INSUFICIENT_CRED;
+       }
+       if (cred->ncerts == 0) {
+               apr_cert_list = NULL;
+               apr_cert_list_length = 0;
+               apr_pkey = NULL;
+       } else {
+               ind = state->gnutls_internals.client_certificate_index;
+               if (ind < 0) {
+                       apr_cert_list = NULL;
+                       apr_cert_list_length = 0;
+                       apr_pkey = NULL;
+               } else {
+                       apr_cert_list = cred->cert_list[ind];
+                       apr_cert_list_length = cred->cert_list_length[ind];
+                       apr_pkey = &cred->pkey[ind];
+               }
+       }
+
+       if (apr_pkey != NULL) {
+               if ( (ret=_gnutls_generate_sig( state, apr_pkey, &signature)) < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+       } else {
+               gnutls_assert();
+               return 0;
+       }
+
+       *data = gnutls_malloc(signature.size+2);
+       if (*data==NULL) {
+               gnutls_free_datum( &signature);
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+       size = signature.size;
+       WRITEuint16( size, *data);
+
+       memcpy( &(*data)[2], signature.data, size);
+
+       gnutls_free_datum( &signature);
+       return size+2;
+}
index b0bd67ab0b44c5d0a4295c8e6532f1d2661512bd..7cbb54fd93a89fe3fe5cb0b93764228aa50bfd69 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <gnutls_ui.h>
 
-typedef struct {
+typedef struct gnutls_cert {
        MPI *params;            /* the size of params depends on the public 
                                 * key algorithm 
                                 */
index 3842a0930356e6892dd58009939a383842a914fc..4ccbe83124efd7ed7c29bf55a45ccb4a0d7171f0 100644 (file)
@@ -1481,8 +1481,8 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) {
                        return ret;
                }
 
-#warning "FIX THIS REQUEST"
-               /* receive the server certificate request */
+               /* receive the server certificate request - if any 
+                */
                if (state->gnutls_internals.resumed == RESUME_FALSE)    /* if we are not resuming */
                        ret = _gnutls_recv_server_certificate_request(cd, state);
                if (ret < 0) {
@@ -1492,7 +1492,8 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) {
                        return ret;
                }
 
-               /* receive the server key exchange (B) (SRP only) */
+               /* receive the server key exchange (B) (SRP only) 
+                */
                if (state->gnutls_internals.resumed == RESUME_FALSE)    /* if we are not resuming */
                        ret = _gnutls_recv_server_kx_message2(cd, state);
                if (ret < 0) {
@@ -1532,6 +1533,7 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) {
                        gnutls_clearHashDataBuffer(state);
                        return ret;
                }
+
                /* send client certificate verify */
                if (state->gnutls_internals.resumed == RESUME_FALSE)    /* if we are not resuming */
                        ret =
index 25defee7694d7fd96efb594779f0904b144adec2..1841181125186fc7c470d322d73bbda853759331 100644 (file)
@@ -326,6 +326,11 @@ typedef struct {
        /* keeps the headers of the handshake packet 
         */
        HANDSHAKE_HEADER_BUFFER         handshake_header_buffer;
+       int                             client_certificate_index; /* holds
+                                               * the index of the client
+                                               * certificate to use. -1
+                                               * if none.
+                                               */
 } GNUTLS_INTERNALS;
 
 struct GNUTLS_STATE_INT {
index 21d6e5a5c731669ea93e24d9cd726aecb6e24b1d..14a4dc52e28dafb66b0be57d5aa1373fc4462c8d 100644 (file)
@@ -236,8 +236,10 @@ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state)
        _gnutls_log( "Sending client certificate verify message\n");
 #endif
        data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy( state, &data);
-       if (data_size < 0) 
+       if (data_size < 0) {
+               gnutls_assert();
                return data_size;
+       }
        ret =
            _gnutls_send_handshake(cd, state, data,
                                   data_size,
index 4c957a63cb2ef7148de82d6a7a326943010b471d..0d42dd4f8db4b99b61639b6565c0d688f067c707 100644 (file)
@@ -29,6 +29,7 @@
 #include <gnutls_datum.h>
 #include "debug.h"
 
+
 /* Do PKCS-1 RSA encryption. 
  * pkey is the public key and n the modulus.
  */
@@ -63,11 +64,30 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext,
        psize = k - 3 - plaintext.size;
 
        ps = &edata[2];
-       _gnutls_get_random(ps, psize, GNUTLS_WEAK_RANDOM);
-       for (i = 0; i < psize; i++) {
-               if (ps[i] == 0)
+       switch(btype) {
+           case 2:
+               _gnutls_get_random(ps, psize, GNUTLS_WEAK_RANDOM);
+               for (i = 0; i < psize; i++) {
+                       if (ps[i] == 0)
+                               ps[i] = 0xff;
+               }
+               break;
+           case 1:
+               for (i = 0; i < psize; i++)
                        ps[i] = 0xff;
+               break;
+#ifdef ALLOW_BLOCK_0
+           case 0:
+               for (i = 0; i < psize; i++) {
+                       ps[i] = 0x00;
+               }
+               break;
+#endif
+           default:
+               gnutls_assert();
+               return GNUTLS_E_UNKNOWN_ERROR;
        }
+       
        ps[psize] = 0;
        memcpy(&ps[psize + 1], plaintext.data, plaintext.size);
 
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
new file mode 100644 (file)
index 0000000..5ee2a33
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *      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 <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <x509_b64.h>
+#include <auth_x509.h>
+#include <gnutls_cert.h>
+#include <x509_asn1.h>
+#include <x509_der.h>
+#include <gnutls_datum.h>
+#include <gnutls_gcry.h>
+#include <gnutls_privkey.h>
+#include <gnutls_global.h>
+#include <gnutls_pk.h>
+#include <debug.h>
+#include <gnutls_buffers.h>
+#include <gnutls_sig.h>
+
+int _gnutls_generate_sig( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature) {
+opaque digest[20+16];
+gnutls_datum data;
+GNUTLS_HASH_HANDLE td;
+int size = gnutls_getHashDataBufferSize( state);
+int ret;
+
+       data.data = gnutls_malloc(size);
+       data.size = size;
+       if (data.data==NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+                       
+       gnutls_readHashDataFromBuffer( state, data.data, data.size);
+
+       switch(pkey->pk_algorithm) {
+               case GNUTLS_PK_RSA:
+                       
+                       td = gnutls_hash_init( GNUTLS_MAC_MD5);
+                       if (td==NULL) {
+                               gnutls_assert();
+                               gnutls_free_datum( &data);
+                               return GNUTLS_E_MEMORY_ERROR;
+                       }
+                       gnutls_hash( td, data.data, data.size);
+                       gnutls_hash_deinit( td, digest);
+
+                       td = gnutls_hash_init( GNUTLS_MAC_SHA);
+                       if (td==NULL) {
+                               gnutls_assert();
+                               gnutls_free_datum( &data);
+                               return GNUTLS_E_MEMORY_ERROR;
+                       }
+                       gnutls_hash( td, data.data, data.size);
+                       gnutls_hash_deinit( td, &digest[16]);
+                       gnutls_free_datum( &data);
+                       
+                       data.data = digest;
+                       data.size = 20+16; /* md5 + sha */      
+                       ret = _gnutls_pkcs1_rsa_generate_sig( GNUTLS_MAC_MD5, pkey, &data, signature);
+                       break;
+               default:
+                       gnutls_free_datum( &data);
+                       ret = GNUTLS_E_UNIMPLEMENTED_FEATURE;
+                       break;
+       }
+
+       return ret;
+
+}
+
+static int _gnutls_digestinfo_encode( opaque* data, int data_size, char* OID, gnutls_datum* der) {
+node_asn *di;
+int result;
+
+       if (asn1_create_structure( _gnutls_get_pkcs(),
+                    "PKCS-1.DigestInfo", &di, "di") != ASN_OK) {
+               gnutls_assert();
+               return GNUTLS_E_ASN1_ERROR;
+       }
+       
+       result = asn1_write_value( di, "di.digestAlgorithm.algorithm", OID, 1);
+       if (result!=ASN_OK) {
+               gnutls_assert();
+               return GNUTLS_E_ASN1_ERROR;
+       }
+
+       result = asn1_write_value( di, "di.digestAlgorithm.parameters", NULL, 0);
+       if (result!=ASN_OK) {
+               gnutls_assert();
+               return GNUTLS_E_ASN1_ERROR;
+       }
+
+       result = asn1_write_value( di, "di.digest", data, data_size);
+       if (result!=ASN_OK) {
+               gnutls_assert();
+               return GNUTLS_E_ASN1_ERROR;
+       }
+
+       der->size = data_size + 200;
+       der->data = gnutls_malloc( der->size);
+       if (der->data==NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+       
+       result = asn1_create_der( di, "di", der->data, &der->size);
+       if (result!=ASN_OK) {
+               gnutls_assert();
+               gnutls_free_datum( der);
+               return GNUTLS_E_ASN1_ERROR;
+       }
+
+       return 0;
+}
+
+int _gnutls_pkcs1_rsa_generate_sig( MACAlgorithm hash_algo, gnutls_private_key *pkey, const gnutls_datum *data, gnutls_datum *signature) {
+       GNUTLS_HASH_HANDLE hd;
+       opaque digest[MAX_HASH_SIZE];
+       int digest_size =  gnutls_hash_get_algo_len( hash_algo), ret;
+       char OID[40];
+       gnutls_datum der;
+       
+       if (hash_algo==GNUTLS_MAC_MD5)
+               strcpy(OID, "1 2 840 113549 2 5");
+       else if (hash_algo==GNUTLS_MAC_SHA)
+               strcpy(OID, "1 3 14 3 2 26");
+       else {
+               gnutls_assert();
+               return GNUTLS_E_UNKNOWN_MAC_ALGORITHM;
+       }
+       
+       /* hash data */
+       hd = gnutls_hash_init( hash_algo);
+       if (hd==NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+       gnutls_hash( hd, data->data, data->size);
+       gnutls_hash_deinit( hd, digest);
+       
+
+       /* encode digest to DigestInfo (der) */
+       if ( (ret=_gnutls_digestinfo_encode( digest, digest_size, OID, &der)) < 0) {
+               gnutls_assert();
+               return ret;
+       }       
+       
+       /* encrypt der */
+       if ( (ret=_gnutls_pkcs1_rsa_encrypt( signature, der, pkey->params[0], pkey->params[1], 1)) < 0) {
+            gnutls_assert();
+            return ret;
+       }
+       
+       gnutls_free_datum( &der);
+       return 0;
+}
index c8a759884f3a23d0b7881f78f6a2f5ee74c066b6..6253060a3182ed3c6cbcadfb8ffec8b12d00c724 100644 (file)
@@ -1,3 +1,4 @@
 int _gnutls_pkcs1_rsa_verify_sig( gnutls_datum* signature, gnutls_datum *text, MPI m, MPI e);
 CertificateStatus gnutls_verify_signature(gnutls_cert* cert, gnutls_cert* issuer);
-
+int _gnutls_pkcs1_rsa_generate_sig( MACAlgorithm hash_algo, gnutls_private_key *pkey, const gnutls_datum *data, gnutls_datum *signature);
+int _gnutls_generate_sig( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature);
index be62a3310f7d097382585cf0aedb0ecc011cbd67..c1e567d161878654eb69ebe6de1e1760b45c2422 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -39,6 +39,8 @@
 #define MAX(X,Y) (X >= Y ? X : Y);
 #define CAFILE "x509/ca.pem"
 #define CRLFILE NULL
+#define CLIKEYFILE "x509/clikey.pem"
+#define CLICERTFILE "x509/clicert.pem"
 
 #define PRINTX(x,y) if (y[0]!=0) printf(" -   %s %s\n", x, y)
 #define PRINT_DN(X) PRINTX( "CN:", X->common_name); \
@@ -144,11 +146,12 @@ int main(int argc, char** argv)
 
 
        /* X509 stuff */
-       if (gnutls_allocate_x509_client_sc( &xcred, 0) < 0) { /* no priv key */
+       if (gnutls_allocate_x509_client_sc( &xcred, 1) < 0) { 
                fprintf(stderr, "memory error\n");
                exit(1);
        }
        gnutls_set_x509_client_trust( xcred, CAFILE, CRLFILE);
+       gnutls_set_x509_client_key( xcred, CLICERTFILE, CLIKEYFILE);
 
        /* SRP stuff */
        if (gnutls_allocate_srp_client_sc( &cred)<0) {
index 2dec0d7d63148f56e69c240e6def0d8b85aa9627..f6168077cfc5004791af5be4e7ba58563c521a7f 100644 (file)
@@ -1 +1,2 @@
-EXTRA_DIST = ca.pem cert.pem key.pem
+EXTRA_DIST = ca.pem cert.pem key.pem clikey.pem clicert.pem
+