summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2004-02-12 09:57:12 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2004-02-12 09:57:12 +0000
commit843af6e703f9e8d0a67c8bea707a63536e78bbfa (patch)
tree7c34577e2b09319cc8f131f47961d7966d1df4ac
parentc174501b7dd3ed405fbfe60df1248db58e33407a (diff)
downloadgnutls-843af6e703f9e8d0a67c8bea707a63536e78bbfa.tar.gz
backported all the changes from the development branch to 1.0.x, except for TLS 1.1 which is untested.
-rw-r--r--NEWS31
-rw-r--r--configure.in4
-rw-r--r--doc/tex/Makefile.am2
-rw-r--r--doc/tex/auth.tex91
-rw-r--r--doc/tex/certificate.tex20
-rw-r--r--doc/tex/ciphers.tex2
-rw-r--r--doc/tex/ciphersuites.tex9
-rw-r--r--doc/tex/compression.tex6
-rw-r--r--doc/tex/ex-cert-select.tex209
-rw-r--r--doc/tex/examples.tex5
-rw-r--r--doc/tex/gnutls.bib13
-rw-r--r--doc/tex/handshake.tex6
-rw-r--r--doc/tex/library.tex4
-rw-r--r--doc/tex/macros.tex1
-rw-r--r--doc/tex/preparation.tex6
-rw-r--r--doc/tex/programs.tex2
-rw-r--r--doc/tex/record_weaknesses.tex14
-rw-r--r--doc/tex/tls_extensions.tex4
-rw-r--r--includes/gnutls/openpgp.h22
-rw-r--r--includes/gnutls/openssl.h1
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/auth_anon.c35
-rw-r--r--lib/auth_cert.c944
-rw-r--r--lib/auth_cert.h37
-rw-r--r--lib/auth_dh_common.c1
-rw-r--r--lib/auth_dhe.c61
-rw-r--r--lib/auth_rsa.c53
-rw-r--r--lib/auth_rsa_export.c76
-rw-r--r--lib/debug.c3
-rw-r--r--lib/dh_compat.c149
-rw-r--r--lib/ext_cert_type.c1
-rw-r--r--lib/ext_max_record.c3
-rw-r--r--lib/ext_server_name.c12
-rw-r--r--lib/gnutls.h.in.in8
-rw-r--r--lib/gnutls_alert.c1
-rw-r--r--lib/gnutls_algorithms.c59
-rw-r--r--lib/gnutls_algorithms.h8
-rw-r--r--lib/gnutls_anon_cred.c1
-rw-r--r--lib/gnutls_auth.c1
-rw-r--r--lib/gnutls_buffers.c1
-rw-r--r--lib/gnutls_cert.c178
-rw-r--r--lib/gnutls_cert.h17
-rw-r--r--lib/gnutls_cipher.c55
-rw-r--r--lib/gnutls_cipher_int.c1
-rw-r--r--lib/gnutls_compress.c1
-rw-r--r--lib/gnutls_compress_int.c1
-rw-r--r--lib/gnutls_constate.c9
-rw-r--r--lib/gnutls_datum.c1
-rw-r--r--lib/gnutls_db.c1
-rw-r--r--lib/gnutls_dh.c1
-rw-r--r--lib/gnutls_dh.h2
-rw-r--r--lib/gnutls_dh_primes.c102
-rw-r--r--lib/gnutls_errors.c7
-rw-r--r--lib/gnutls_extensions.c1
-rw-r--r--lib/gnutls_global.c3
-rw-r--r--lib/gnutls_handshake.c146
-rw-r--r--lib/gnutls_int.h22
-rw-r--r--lib/gnutls_int_compat.c1288
-rw-r--r--lib/gnutls_kx.c5
-rw-r--r--lib/gnutls_mem.c1
-rw-r--r--lib/gnutls_mpi.c1
-rw-r--r--lib/gnutls_num.c1
-rw-r--r--lib/gnutls_pk.c14
-rw-r--r--lib/gnutls_priority.c1
-rw-r--r--lib/gnutls_random.c9
-rw-r--r--lib/gnutls_record.c93
-rw-r--r--lib/gnutls_rsa_export.c2
-rw-r--r--lib/gnutls_session.c3
-rw-r--r--lib/gnutls_session_pack.c1
-rw-r--r--lib/gnutls_sig.c49
-rw-r--r--lib/gnutls_state.c30
-rw-r--r--lib/gnutls_str.c1
-rw-r--r--lib/gnutls_ui.c15
-rw-r--r--lib/gnutls_ui.h107
-rw-r--r--lib/gnutls_v2_compat.c1
-rw-r--r--lib/gnutls_x509.c69
-rw-r--r--lib/gnutls_x509.h3
-rw-r--r--lib/rsa_compat.c284
-rw-r--r--lib/strnstr.c1
-rw-r--r--lib/x509/compat.c702
-rw-r--r--lib/x509/compat.h12
-rw-r--r--lib/x509/x509.h8
-rw-r--r--lib/x509_b64.c5
-rw-r--r--libextra/Makefile.am2
-rw-r--r--libextra/auth_srp.c129
-rw-r--r--libextra/auth_srp_passwd.c1
-rw-r--r--libextra/auth_srp_rsa.c39
-rw-r--r--libextra/auth_srp_sb64.c1
-rw-r--r--libextra/ext_srp.c1
-rw-r--r--libextra/gnutls_extra.c39
-rw-r--r--libextra/gnutls_extra.h10
-rw-r--r--libextra/gnutls_openpgp.c174
-rw-r--r--libextra/gnutls_openssl.c2
-rw-r--r--libextra/gnutls_srp.c8
-rw-r--r--libextra/openpgp/Makefile.am2
-rw-r--r--libextra/openpgp/compat.c13
-rw-r--r--libextra/openpgp/extras.c1
-rw-r--r--libextra/openpgp/gnutls_openpgp.h16
-rw-r--r--libextra/openpgp/openpgp.c85
-rw-r--r--libextra/openpgp/openpgp.h14
-rw-r--r--libextra/openpgp/privkey.c133
-rw-r--r--libextra/openpgp/verify.c3
-rw-r--r--libextra/openpgp/xml.c3
-rw-r--r--src/serv.c10
104 files changed, 3502 insertions, 2347 deletions
diff --git a/NEWS b/NEWS
index 7d98c20ddd..76b6b5fc51 100644
--- a/NEWS
+++ b/NEWS
@@ -1,20 +1,29 @@
-Version 1.0.6
+Version 1.0.6 (12/02/2004)
+* Backported things from the development branch:
- Improved gnutls-cli's SRP behaviour in SRP ciphersuites.
If they are of highest priority then the abbreviated handshake
is used.
+- The error codes GNUTLS_E_NO_TEMPORARY_DH_PARAMS and GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
+ are no longer returned by the handshake function. Ciphersuites that
+ require temporary parameters are removed when such parameters do not exist.
+- Added the callbacks gnutls_certificate_client_retrieve_function() and
+ gnutls_certificate_server_retrieve_function(), to allow a client or a server
+ to specify certificates for the handshake without storing them to the
+ credentials structure.
+- Added support for generating and exporting DSA private keys.
Version 1.0.5 (11/02/2004)
- Fixed a bug where 'server name' extension was always sent.
-- Backported several things from the development branch:
- - Added CRL verification functionality to certtool.
- - Corrected the CRL distribution point extension handling.
- - Added PKCS #7 support to certtool utility.
- - Added support for reading and generating CRL distribution
- points extensions in certificates.
- - Added support for generating CRLs in the library and the
- certtool utility.
- - Added support for the Subject Key ID PKIX extension.
- - Added the gnutls_sign_algorithm type.
+* Backported things from the development branch:
+- Added CRL verification functionality to certtool.
+- Corrected the CRL distribution point extension handling.
+- Added PKCS #7 support to certtool utility.
+- Added support for reading and generating CRL distribution
+ points extensions in certificates.
+- Added support for generating CRLs in the library and the
+ certtool utility.
+- Added support for the Subject Key ID PKIX extension.
+- Added the gnutls_sign_algorithm type.
Version 1.0.4 (04/01/2004)
- Changed handshake behaviour to send the lowest TLS version
diff --git a/configure.in b/configure.in
index 27fae7012f..cd84165075 100644
--- a/configure.in
+++ b/configure.in
@@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os", [OS name])
dnl Gnutls Version
GNUTLS_MAJOR_VERSION=1
GNUTLS_MINOR_VERSION=0
-GNUTLS_MICRO_VERSION=5
+GNUTLS_MICRO_VERSION=6
GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION", [version of gnutls])
@@ -28,7 +28,7 @@ AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
dnl This is the library version
-GNUTLS_MOST_RECENT_INTERFACE=12
+GNUTLS_MOST_RECENT_INTERFACE=13
GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$GNUTLS_MICRO_VERSION
GNUTLS_OLDEST_INTERFACE=10
diff --git a/doc/tex/Makefile.am b/doc/tex/Makefile.am
index ddac1639d7..7227d8a12c 100644
--- a/doc/tex/Makefile.am
+++ b/doc/tex/Makefile.am
@@ -15,7 +15,7 @@ TEX_OBJECTS = gnutls.tex ../../lib/gnutls-api.tex fdl.tex ../../lib/x509/x509-ap
macros.tex cover.tex ciphersuites.tex handshake.tex translayer.tex \
auth.tex ciphers.tex errors.tex layers.tex alert.tex record.tex \
funcs.tex examples.tex ../../libextra/gnutls-extra-api.tex \
- memory.tex openpgp.tex x509.tex howto.tex openssl.tex \
+ memory.tex cert_auth.tex howto.tex openssl.tex \
appendix.tex x509cert.xml.tex pgpcert.xml.tex \
programs.tex library.tex certificate.tex record_weaknesses.tex \
tlsintro.tex compression.tex $(EXAMPLE_OBJECTS) preface.tex \
diff --git a/doc/tex/auth.tex b/doc/tex/auth.tex
index 4fea3dd6af..7a6f08a3ee 100644
--- a/doc/tex/auth.tex
+++ b/doc/tex/auth.tex
@@ -10,46 +10,7 @@ The available authentication methods in \gnutls{} are:
\item SRP authentication
\end{enumerate}
-% x.509 section
-\input{x509}
-
-\begin{figure}[hbtp]
-\index{Key exchange algorithms}
-\begin{tabular}{|l|p{9cm}|}
-\hline
-RSA & The RSA algorithm is used to encrypt a key and send it to the peer.
-The certificate must allow the key to be used for encryption.
-\\
-\hline
-RSA\_EXPORT & The RSA algorithm is used to encrypt a key and send it to the peer.
-In the EXPORT algorithm, the server signs temporary RSA parameters of 512
-bits -- which are considered weak -- and sends them to the client.
-\\
-\hline
-DHE\_RSA & The RSA algorithm is used to sign Ephemeral Diffie Hellman
-parameters which are sent to the peer. The key in the certificate must allow
-the key to be used for signing. Note that key exchange algorithms which use
-Ephemeral Diffie Hellman parameters, offer perfect forward secrecy.
-\\
-\hline
-DHE\_DSS & The DSS algorithm is used to sign Ephemeral Diffie Hellman
-parameters which are sent to the peer. DSS stands for Digital Signature
-Standard.
-\\
-\hline
-\end{tabular}
-
-\caption{Key exchange algorithms for OpenPGP and X.509 certificates.}
-\label{fig:cert}
-
-\end{figure}
-
-
-% openpgp section
-
-\input{openpgp}
-
-
+\input{cert_auth}
\section{Anonymous authentication\index{Anonymous authentication}}
The anonymous key exchange perform encryption but there is no indication of
@@ -59,6 +20,10 @@ but this protocol can be used even if there is no prior communication and
trusted parties with the peer, or when full anonymity is required.
Unless really required, do not use anonymous authentication.
Available key exchange methods are shown in \hyperref{figure}{figure }{}{fig:anon}.
+\par
+Note that the key exchange methods for anonymous authentication
+require Diffie Hellman parameters to be generated and associated with an
+anonymous credentials structure.
\begin{figure}[hbtp]
\begin{tabular}{|l|p{9cm}|}
@@ -75,3 +40,49 @@ ANON\_DH & This algorithm exchanges Diffie Hellman parameters.
\end{figure}
\input{srp}
+
+\section{Authentication and credentials}
+In \gnutls{} every key exchange method is associated with a
+credentials type. So in order to enable to enable a specific
+method, the corresponding credentials type should be initialized
+and set using \printfunc{gnutls_credentials_set}{gnutls\_credentials\_set}.
+A mapping is shown in \hyperref{figure}{figure }{}{fig:kxcred}.
+
+\begin{figure}[hbtp]
+\begin{tabular}{|l|l|p{4.5cm}|}
+
+\hline
+\bf{Key exchange} & \bf{Client credentials} & \bf{Server credentials}
+\\
+\hline
+\hline
+KX\_RSA &&
+\\
+\cline{1-1}
+KX\_DHE\_RSA & CRD\_CERTIFICATE & CRD\_CERTIFICATE
+\\
+\cline{1-1}
+KX\_DHE\_DSS &&
+\\
+\cline{1-1}
+KX\_RSA\_EXPORT &&
+\\
+\hline
+KX\_SRP\_RSA & CRD\_SRP & CRD\_SRP
+\\
+\cline{1-1}
+KX\_SRP\_DSS && CRD\_CERTIFICATE
+\\
+\hline
+KX\_SRP & CRD\_SRP & CRD\_SRP
+\\
+\hline
+KX\_ANON\_DH & CRD\_ANON & CRD\_ANON
+\\
+\hline
+\end{tabular}
+
+\caption{Key exchange algorithms and the corresponding credential types}
+\label{fig:kxcred}
+
+\end{figure}
diff --git a/doc/tex/certificate.tex b/doc/tex/certificate.tex
index 2f5067bc3c..75740ae3fd 100644
--- a/doc/tex/certificate.tex
+++ b/doc/tex/certificate.tex
@@ -27,8 +27,9 @@ on page \pageref{sec:x509api}. Some examples are listed below.
\subsection{X.509 certificates}
An X.509 certificate usually contains information about the certificate
-holder, the signer, a unique serial number, expiration dates etc. Some
-functions of \gnutls{}' API for certificate parsing are:
+holder, the signer, a unique serial number, expiration dates and several other
+fields\cite{RFC3280}. Several functions exist to generate and handle X.509
+certificates, all listed in \emph{gnutls/x509.h}. Some of them are:
\begin{itemize}
\item \printfunc{gnutls_x509_crt_init}{gnutls\_x509\_crt\_init}
\item \printfunc{gnutls_x509_crt_import}{gnutls\_x509\_crt\_import}
@@ -38,9 +39,8 @@ functions of \gnutls{}' API for certificate parsing are:
\end{itemize}
\par
-An example program that reads the peer's certificate,
-and prints some information about the peer's certificate in a TLS session,
-is listed below.
+To demonstrate the X.509 parsing capabilities an example program is listed below.
+That program reads the peer's certificate, and prints information about it.
\input{ex-x509-info}
@@ -101,7 +101,13 @@ which should return a signed certificate.
A PKCS \#12 structure usually contains a user's private keys and
certificates. It is commonly used in browsers to export and import
the user's identities.
-
+\par
+In \gnutls{} the PKCS \#12 structures are handled using the
+\emph{gnutls\_pkcs12} type. This is an abstract type that
+may hold several \emph{gnutls\_pkcs12\_bag} types. The Bag types are the
+holders of the actual data, which may be certificates, private
+keys or encrypted data. An Bag of type encrypted should be decrypted
+in order for its data to be accessed.
\par
The following example is about generating a PKCS \#12 structure.
@@ -139,7 +145,7 @@ Kevin, for some reason. A reason could be that Bob is lazy enough, and
signs other people's keys without being sure that they belong to the
actual owner.
-\subsection{Verifying an OpenPGP key}
+\subsection*{Verifying an OpenPGP key}
The verification functions of OpenPGP keys, included in \gnutls{},
are simple ones, and do not use the features of the ``web of trust''.
For that reason, if the verification needs are complex,
diff --git a/doc/tex/ciphers.tex b/doc/tex/ciphers.tex
index 0cb46e9916..a1d9c30950 100644
--- a/doc/tex/ciphers.tex
+++ b/doc/tex/ciphers.tex
@@ -1,4 +1,4 @@
-\subsection{Encryption algorithms used in the record layer}
+\subsection*{Encryption algorithms used in the record layer}
\index{Symmetric encryption algorithms}
Confidentiality in the record layer is achieved by using symmetric block
encryption algorithms like {\bf 3DES}, {\bf AES\footnote{AES or Advanced
diff --git a/doc/tex/ciphersuites.tex b/doc/tex/ciphersuites.tex
index 4899f59b0c..87c3a99135 100644
--- a/doc/tex/ciphersuites.tex
+++ b/doc/tex/ciphersuites.tex
@@ -1,4 +1,4 @@
-\subsection{TLS cipher suites}
+\subsection*{TLS cipher suites}
\par
The Handshake Protocol of \tlsI{} negotiates cipher suites
of the form \\
@@ -23,12 +23,5 @@ and set priorities on the individual ciphers. It may imply that all combinations
are allowed, but this is not true. For several reasons, not discussed here, some combinations
were not defined in the \tls{} protocol. The supported ciphersuites are shown
in appendix \ref{ap:ciphersuites} on page \pageref{ap:ciphersuites}.
-\gnutls{} will disable ciphersuites that are not compatible with the key, or
-the enabled authentication methods.
-For example keys marked as sign-only, will not be able to
-access the plain RSA ciphersuites, but only the DHE\_RSA ones. It is
-recommended not to use RSA keys for both signing and encryption. If possible
-use the same key for the DHE\_RSA and RSA\_EXPORT ciphersuites, which use signing,
-and a different key for the plain RSA ciphersuites, which uses encryption.
\addvspace{1.5cm}
diff --git a/doc/tex/compression.tex b/doc/tex/compression.tex
index 3a8e92bc00..cd057e027d 100644
--- a/doc/tex/compression.tex
+++ b/doc/tex/compression.tex
@@ -1,8 +1,8 @@
-\subsection{Compression algorithms used in the record layer}
+\subsection*{Compression algorithms used in the record layer}
\index{Compression algorithms}
The TLS' record layer also supports compression. The algorithms
implemented in \gnutls{} can be found in figure \ref{fig:compression}.
-All the algorithms except for ZLIB which is referenced in \cite{TLSCOMP}, should be
+All the algorithms except for DEFLATE which is referenced in \cite{TLSCOMP}, should be
considered as \gnutls' extensions\footnote{You should use \printfunc{gnutls_handshake_set_private_extensions}{gnutls\_handshake\_set\_private\_extensions}
to enable private extensions.}, and
should be advertised only when the peer is known to have a compliant client,
@@ -23,7 +23,7 @@ the paper \cite{TLSCOMP}.
\begin{tabular}{|l|p{9cm}|}
\hline
-ZLIB & ZLIB compression, using the deflate algorithm.
+DEFLATE & Zlib compression, using the deflate algorithm.
\\
\hline
LZO & LZO is a very fast compression algorithm. This algorithm is only
diff --git a/doc/tex/ex-cert-select.tex b/doc/tex/ex-cert-select.tex
index 796f2e568f..35b829c524 100644
--- a/doc/tex/ex-cert-select.tex
+++ b/doc/tex/ex-cert-select.tex
@@ -2,21 +2,204 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
+/* A TLS client that loads the certificate and key.
+ */
+
+#define MAX_BUF 1024
+#define SA struct sockaddr
+#define MSG "GET / HTTP/1.0\r\n\r\n"
+
+#define CERT_FILE "cert.pem"
+#define KEY_FILE "key.pem"
+#define CAFILE "ca.pem"
+
+static int cert_callback(gnutls_session session,
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ const gnutls_pk_algorithm* sign_algos, int sign_algos_length,
+ gnutls_retr_st * st);
+
+gnutls_x509_crt crt;
+gnutls_x509_privkey key;
+
+/* Helper functions to load a certificate and key
+ * files into memory. They use mmap for simplicity.
+ */
+static gnutls_datum mmap_file( const char* file)
+{
+int fd;
+gnutls_datum mmaped_file = { NULL, 0 };
+struct stat stat_st;
+void* ptr;
+
+ fd = open( file, 0);
+ if (fd==-1) return mmaped_file;
+
+ fstat( fd, &stat_st);
+
+ if ((ptr=mmap( NULL, stat_st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
+ return mmaped_file;
+
+ mmaped_file.data = ptr;
+ mmaped_file.size = stat_st.st_size;
+
+ return mmaped_file;
+}
+
+static void munmap_file( gnutls_datum data)
+{
+ munmap( data.data, data.size);
+}
+
+/* Load the certificate and the private key.
+ */
+static void load_keys( void)
+{
+int ret;
+gnutls_datum data;
+
+ data = mmap_file( CERT_FILE);
+ if (data.data == NULL) {
+ fprintf(stderr, "*** Error loading cert file.\n");
+ exit(1);
+ }
+ gnutls_x509_crt_init( &crt);
+
+ ret = gnutls_x509_crt_import( crt, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "*** Error loading key file: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ munmap_file( data);
+
+ data = mmap_file( KEY_FILE);
+ if (data.data == NULL) {
+ fprintf(stderr, "*** Error loading key file.\n");
+ exit(1);
+ }
+
+ gnutls_x509_privkey_init( &key);
+
+ ret = gnutls_x509_privkey_import( key, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "*** Error loading key file: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ munmap_file( data);
+
+}
+
+int main()
+{
+ int ret, sd, ii;
+ gnutls_session session;
+ char buffer[MAX_BUF + 1];
+ gnutls_certificate_credentials xcred;
+ /* Allow connections to servers that have OpenPGP keys as well.
+ */
+
+ gnutls_global_init();
+
+ load_keys();
+
+ /* X509 stuff */
+ gnutls_certificate_allocate_credentials(&xcred);
+
+ /* sets the trusted cas file
+ */
+ gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM);
+
+ gnutls_certificate_client_set_retrieve_function( xcred, cert_callback);
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT);
+
+ /* Use default priorities */
+ gnutls_set_default_priority(session);
+
+ /* put the x509 credentials to the current session
+ */
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
+
+ /* connect to the peer
+ */
+ sd = tcp_connect();
+
+ gnutls_transport_set_ptr( session, (gnutls_transport_ptr)sd);
+
+ /* Perform the TLS handshake
+ */
+ ret = gnutls_handshake( session);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Handshake failed\n");
+ gnutls_perror(ret);
+ goto end;
+ } else {
+ printf("- Handshake was completed\n");
+ }
+
+ gnutls_record_send( session, MSG, strlen(MSG));
+
+ ret = gnutls_record_recv( session, buffer, MAX_BUF);
+ if (ret == 0) {
+ printf("- Peer has closed the TLS connection\n");
+ goto end;
+ } else if (ret < 0) {
+ fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
+ goto end;
+ }
+
+ printf("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++) {
+ fputc(buffer[ii], stdout);
+ }
+ fputs("\n", stdout);
+
+ gnutls_bye( session, GNUTLS_SHUT_RDWR);
+
+ end:
+
+ tcp_close( sd);
+
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(xcred);
+
+ gnutls_global_deinit();
+
+ return 0;
+}
+
+
+
/* This callback should be associated with a session by calling
- * gnutls_certificate_client_set_select_function( session, cert_callback),
+ * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
* before a handshake.
*/
static int cert_callback(gnutls_session session,
- const gnutls_datum * client_certs, int client_certs_num,
- const gnutls_datum * req_ca_rdn, int nreqs)
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ const gnutls_pk_algorithm* sign_algos, int sign_algos_length,
+ gnutls_retr_st * st)
{
char issuer_dn[256];
int i, ret;
size_t len;
+ gnutls_certificate_type type;
/* Print the server's trusted CAs
*/
@@ -35,11 +218,25 @@ static int cert_callback(gnutls_session session,
}
}
- /* Select a certificate from the client_certs and return its
- * index.
+ /* Select a certificate and return it.
+ * The certificate must be of any of the "sign algorithms"
+ * supported by the server.
*/
- return -1;
+ type = gnutls_certificate_type_get( session);
+ if (type == GNUTLS_CRT_X509) {
+ st->type = type;
+ st->ncerts = 1;
+
+ st->cert.x509 = &crt;
+ st->key.x509 = key;
+
+ st->deinit_all = 0;
+ } else {
+ return -1;
+ }
+
+ return 0;
}
diff --git a/doc/tex/examples.tex b/doc/tex/examples.tex
index 31a38c972d..544b502616 100644
--- a/doc/tex/examples.tex
+++ b/doc/tex/examples.tex
@@ -37,9 +37,8 @@ Real world programs should be able to handle certificate chains as well.
\subsection{Using a callback to select the certificate to use}
There are cases where a client holds several certificate and key pairs,
-and may want to choose the appropriate to send in the current session.
-The following example demonstrates the use of the certificate selection callback
-to assist in this purpose.
+and may not want to load all of them in the credentials structure.
+The following example demonstrates the use of the certificate selection callback.
\par
\input{ex-cert-select}
diff --git a/doc/tex/gnutls.bib b/doc/tex/gnutls.bib
index 5a5b30bcf3..db2bdf6d7c 100644
--- a/doc/tex/gnutls.bib
+++ b/doc/tex/gnutls.bib
@@ -16,8 +16,17 @@
url = "http://kaizi.viagenie.qc.ca/ietf/rfc/rfc2945.txt"
}
+@Misc{RFC3280,
+ author = "Russell Housley and Tim Polk and Warwick Ford and David Solo",
+ title = "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile",
+ month = "April",
+ year = {2002},
+ note = "Available from http://kaizi.viagenie.qc.ca/ietf/rfc/rfc3280.txt",
+ url = "http://kaizi.viagenie.qc.ca/ietf/rfc/rfc3280.txt"
+}
+
@Misc{SSL3,
- author = "Alan O. Freier and Philip Karlton and Paul C. Kocher",
+ author = "Alan Freier and Philip Karlton and Paul Kocher",
title = "The SSL Protocol Version 3.0",
month = "November",
year = {1996},
@@ -35,7 +44,7 @@
}
@Misc{TLSSRP,
- author = "David Taylor",
+ author = "David Taylor and Trevor Perrin and Tom Wu and Nikos Mavroyanopoulos",
title = "Using SRP for TLS Authentication",
month = "June",
year = {2003},
diff --git a/doc/tex/handshake.tex b/doc/tex/handshake.tex
index 283ac70e36..657fef695d 100644
--- a/doc/tex/handshake.tex
+++ b/doc/tex/handshake.tex
@@ -34,7 +34,7 @@ handshake.
\input{ciphersuites}
-\subsection{Client authentication}
+\subsection*{Client authentication}
In the case of ciphersuites that use certificate authentication, the
authentication\index{Certificate authentication!Client} of the client is
optional in \tls{}. A server may request a certificate from the client -- using the
@@ -46,7 +46,7 @@ by one of the server's acceptable signers. In \gnutls{} the server's acceptable
signers list is constructed using the trusted CA certificates in the
credentials structure.
-\subsection{Resuming Sessions\index{Resuming sessions}}
+\subsection*{Resuming Sessions\index{Resuming sessions}}
\label{resume}
\par
The
@@ -64,7 +64,7 @@ it may be normal for a server not to resume a session even if you requested that
Also note that you must enable, using the priority functions, at least the
algorithms used in the last session.
-\subsection{Resuming internals}
+\subsection*{Resuming internals}
The resuming capability, mostly in the server side, is one of the problems of a thread-safe TLS
implementations. The problem is that all threads must share information in
order to be able to resume sessions. The gnutls approach is, in case of a
diff --git a/doc/tex/library.tex b/doc/tex/library.tex
index 08af7c6190..9955ca37b9 100644
--- a/doc/tex/library.tex
+++ b/doc/tex/library.tex
@@ -18,7 +18,7 @@ in the distribution}.
Important features of the \gnutls{} library include:
\begin{itemize}
-\item Support for both \tlsI{} and \sslIII{} protocols.
+\item Support for \tlsI{}, \tlsII{} and \sslIII{} protocols.
\item Support for both {\bf X.509} and {\bf OpenPGP} certificates.
\item Support for handling and verification of certificates.
\item Support for {\bf SRP} for \tls{} authentication.
@@ -27,7 +27,7 @@ Important features of the \gnutls{} library include:
\item Thread safety
\end{itemize}
-Additionaly \gnutls{} provides a limited emulation API for the widely used
+Additionally \gnutls{} provides a limited emulation API for the widely used
OpenSSL\footnote{\htmladdnormallink{http://www.openssl.org/}{http://www.openssl.org/}}
library, to ease integration with existing applications.
diff --git a/doc/tex/macros.tex b/doc/tex/macros.tex
index 060f4dfe26..550dcc05c5 100644
--- a/doc/tex/macros.tex
+++ b/doc/tex/macros.tex
@@ -1,6 +1,7 @@
\newcommand{\gnutls}{{\emph{GnuTLS}}}
\newcommand{\gnutlse}{{\emph{GnuTLS-extra}}}
\newcommand{\tlsI}{{\emph{TLS 1.0}}}
+\newcommand{\tlsII}{{\emph{TLS 1.1}}}
\newcommand{\tls}{{\emph{TLS}}}
\newcommand{\sslIII}{{\emph{SSL 3.0}}}
\newcommand{\sslII}{{\emph{SSL 2.0}}}
diff --git a/doc/tex/preparation.tex b/doc/tex/preparation.tex
index 6d2a66fc31..7afeaf2c99 100644
--- a/doc/tex/preparation.tex
+++ b/doc/tex/preparation.tex
@@ -5,7 +5,7 @@ To use \gnutls{}, you have to perform some changes to your sources and
your build system. The necessary changes are explained in the following
subsections.
-\subsection{Headers}
+\subsection*{Headers}
All the data types and functions of the \gnutls{} library are defined in
the header file `gnutls/gnutls.h'. This must be included in all programs that
@@ -14,7 +14,7 @@ make use of the \gnutls{} library.
The extra functionality of the \gnutlse{} library is available by
including the header file `gnutls/extra.h' in your programs.
-\subsection{Version check}
+\subsection*{Version check}
It is often desirable to check that the version of `gnutls' used is indeed
one which fits all requirements. Even with binary compatibility new
features may have been introduced but due to problem with the dynamic
@@ -23,7 +23,7 @@ the version is okay right after program startup.
See the function \printfunc{gnutls_check_version}{gnutls\_check\_version}
-\subsection{Building the source}
+\subsection*{Building the source}
If you want to compile a source file including the `gnutls/gnutls.h' header
file, you must make sure that the compiler can find it in the
diff --git a/doc/tex/programs.tex b/doc/tex/programs.tex
index 8489f20bea..16e66fd4e1 100644
--- a/doc/tex/programs.tex
+++ b/doc/tex/programs.tex
@@ -7,7 +7,7 @@ The ``gnutls-srpcrypt'' is a very simple program that emulates the programs in t
\emph{Stanford SRP libraries}.
It is intended for use in places where you don't expect SRP
authentication to be the used for system users.
-Traditionaly \emph{libsrp} used two files. One called 'tpasswd' which holds usernames
+Traditionally \emph{libsrp} used two files. One called 'tpasswd' which holds usernames
and verifiers, and 'tpasswd.conf' which holds generators and primes.
\par
How to use srpcrypt:
diff --git a/doc/tex/record_weaknesses.tex b/doc/tex/record_weaknesses.tex
index 75c5696a11..21845dd1e1 100644
--- a/doc/tex/record_weaknesses.tex
+++ b/doc/tex/record_weaknesses.tex
@@ -1,4 +1,4 @@
-\subsection{Weaknesses and countermeasures}
+\subsection*{Weaknesses and countermeasures}
\index{TLS protocols!Record}
Some weaknesses that may affect the security of the Record layer have been
@@ -10,15 +10,7 @@ and exploit the facts that
\item the IV for CBC encrypted packets is the last block of the previous encrypted packet
\end{enumerate}
-\gnutls{} implements all the known counter-measures for these attacks. For the first
-two cases, \gnutls{} does only have one error code for both of the decryption failures,
-and processes the message normally even if a padding error occured. This avoids
-both of these attacks.
-For the latter, an empty record can be sent before every record packet, and this is
-believed to avoid the known attacks in CBC encrypted packets. See the function
-\printfunc{gnutls_record_set_cbc_protection}{gnutls\_record\_set\_cbc\_protection}
-for more information.
-
-For a detailed discussion see the archives of the TLS Working Group mailing list
+Those weaknesses were solved in \tlsII{} which is implemented in
+\gnutls{}. For a detailed discussion see the archives of the TLS Working Group mailing list
and the paper \cite{CBCATT}.
diff --git a/doc/tex/tls_extensions.tex b/doc/tex/tls_extensions.tex
index 0c54e2aa1b..23786c1f50 100644
--- a/doc/tex/tls_extensions.tex
+++ b/doc/tex/tls_extensions.tex
@@ -9,7 +9,7 @@ mainly in \cite{TLSEXT}. The extensions supported in \gnutls{} are
\end{itemize}
discussed in the subsections that follow.
-\subsection{Maximum fragment length negotiation}
+\subsection*{Maximum fragment length negotiation}
\index{TLS Extensions!Maximum fragment length}
This extension allows a \tlsI{} implementation to negotiate
@@ -21,7 +21,7 @@ and the
\printfunc{gnutls_record_get_max_size}{gnutls\_record\_get\_max\_size}
functions.
-\subsection{Server name indication}
+\subsection*{Server name indication}
\index{TLS Extensions!Server name indication}
A common problem in HTTPS servers is the fact that the \tls{}
diff --git a/includes/gnutls/openpgp.h b/includes/gnutls/openpgp.h
index 208050da54..85d741841f 100644
--- a/includes/gnutls/openpgp.h
+++ b/includes/gnutls/openpgp.h
@@ -32,8 +32,8 @@ extern "C" {
#include <gnutls/gnutls.h>
-struct gnutls_openpgp_key_int; /* object to hold (parsed) openpgp keys */
-typedef struct gnutls_openpgp_key_int* gnutls_openpgp_key;
+/* gnutls_openpgp_key should be defined in gnutls.h
+ */
typedef enum gnutls_openpgp_key_fmt { GNUTLS_OPENPGP_FMT_RAW,
GNUTLS_OPENPGP_FMT_BASE64 } gnutls_openpgp_key_fmt;
@@ -47,6 +47,10 @@ int gnutls_openpgp_key_export(gnutls_openpgp_key key,
gnutls_openpgp_key_fmt format, void* output_data,
size_t* output_data_size);
+/* The key_usage flags are defined in gnutls.h. They are
+ * the GNUTLS_KEY_* definitions.
+ */
+int gnutls_openpgp_key_get_key_usage( gnutls_openpgp_key cert, unsigned int* key_usage);
int gnutls_openpgp_key_get_fingerprint( gnutls_openpgp_key key,
void* result, size_t* result_size);
@@ -68,6 +72,15 @@ int gnutls_openpgp_key_check_hostname( gnutls_openpgp_key key, const char *hostn
int gnutls_openpgp_key_to_xml( gnutls_openpgp_key key, gnutls_datum *xmlkey,
int ext);
+/* privkey stuff.
+ */
+int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey * key);
+void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey key);
+int gnutls_openpgp_privkey_get_pk_algorithm( gnutls_openpgp_privkey key, unsigned int *bits);
+int gnutls_openpgp_privkey_import(gnutls_openpgp_privkey key,
+ const gnutls_datum * data, gnutls_openpgp_key_fmt format,
+ const char* pass, unsigned int flags);
+
/* Keyring stuff.
*/
struct gnutls_openpgp_keyring_int; /* object to hold (parsed) openpgp keyrings */
@@ -107,6 +120,11 @@ int gnutls_openpgp_key_verify_trustdb(
unsigned int * verify /* the output of the verification */);
+/* certificate authentication stuff.
+ */
+int gnutls_certificate_set_openpgp_key(gnutls_certificate_credentials res,
+ gnutls_openpgp_key key, gnutls_openpgp_privkey pkey);
+
#ifdef __cplusplus
}
#endif
diff --git a/includes/gnutls/openssl.h b/includes/gnutls/openssl.h
index eb4667af9c..3b214f2b6a 100644
--- a/includes/gnutls/openssl.h
+++ b/includes/gnutls/openssl.h
@@ -34,6 +34,7 @@ extern "C" {
#endif
#include <gnutls/gnutls.h>
+#include <gnutls/compat8.h>
#include <gcrypt.h>
#define OPENSSL_VERSION_NUMBER (0x0090604F)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 39aa7f0115..9a55b33fc7 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -45,8 +45,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \
gnutls_dh_primes.c ext_max_record.c gnutls_alert.c gnutls_int_compat.c \
gnutls_str.c gnutls_state.c gnutls_x509.c ext_cert_type.c \
gnutls_rsa_export.c auth_rsa_export.c \
- ext_server_name.c auth_dh_common.c \
- dh_compat.c rsa_compat.c strnstr.c
+ ext_server_name.c auth_dh_common.c strnstr.c
# Separate so we can create the documentation
diff --git a/lib/auth_anon.c b/lib/auth_anon.c
index 65707806db..a49df2092c 100644
--- a/lib/auth_anon.c
+++ b/lib/auth_anon.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -60,6 +61,7 @@ const MOD_AUTH_STRUCT anon_auth_struct = {
static int gen_anon_server_kx( gnutls_session session, opaque** data) {
GNUTLS_MPI g, p;
+ const GNUTLS_MPI *mpis;
int ret;
const gnutls_anon_server_credentials cred;
@@ -69,28 +71,27 @@ static int gen_anon_server_kx( gnutls_session session, opaque** data) {
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
- if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_ANON, sizeof( ANON_SERVER_AUTH_INFO_INT), 1)) < 0) {
+ p = mpis[0];
+ g = mpis[1];
+
+ if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_ANON, sizeof( ANON_SERVER_AUTH_INFO_INT), 1)) < 0)
+ {
gnutls_assert();
- cleanup_gp:
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
return ret;
}
if ((ret=_gnutls_dh_set_prime_bits( session, _gnutls_mpi_get_nbits(p))) < 0) {
gnutls_assert();
- goto cleanup_gp;
+ return ret;
}
ret = _gnutls_dh_common_print_server_kx( session, g, p, data);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
-
if (ret < 0) {
gnutls_assert();
}
@@ -105,6 +106,7 @@ const gnutls_anon_server_credentials cred;
int bits;
int ret;
GNUTLS_MPI p, g;
+const GNUTLS_MPI *mpis;
bits = _gnutls_dh_get_prime_bits( session);
@@ -114,16 +116,17 @@ GNUTLS_MPI p, g;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
ret = _gnutls_proc_dh_common_client_kx( session, data, _data_size, g, p);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
-
return ret;
}
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index f289026e7d..de770cc358 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -44,16 +45,18 @@
#include <gnutls_extra.h>
#include "debug.h"
-static int _gnutls_server_find_cert_list_index(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo);
+static gnutls_cert *alloc_and_load_x509_certs(gnutls_x509_crt * certs, uint);
+static gnutls_privkey *alloc_and_load_x509_key(gnutls_x509_privkey key);
+static gnutls_cert *alloc_and_load_pgp_certs(gnutls_openpgp_key cert);
+static gnutls_privkey *alloc_and_load_pgp_key(const gnutls_openpgp_privkey key);
+
/* Copies data from a internal certificate struct (gnutls_cert) to
* exported certificate struct (CERTIFICATE_AUTH_INFO)
*/
static
-int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
- gnutls_cert * cert, int ncerts)
+int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
+ gnutls_cert * cert, int ncerts)
{
/* Copy peer's information to AUTH_INFO
*/
@@ -64,7 +67,7 @@ int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
info->ncerts = 0;
return 0;
}
-
+
info->raw_certificate_list =
gnutls_calloc(1, sizeof(gnutls_datum) * ncerts);
if (info->raw_certificate_list == NULL) {
@@ -107,10 +110,8 @@ int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
* -1 otherwise.
*/
inline
- static int _gnutls_check_pk_algo_in_list(gnutls_pk_algorithm *
- pk_algos, int pk_algos_length,
- gnutls_pk_algorithm
- algo_to_check)
+static int _gnutls_check_pk_algo_in_list(const gnutls_pk_algorithm *pk_algos,
+ int pk_algos_length, gnutls_pk_algorithm algo_to_check)
{
int i;
for (i = 0; i < pk_algos_length; i++) {
@@ -128,7 +129,7 @@ inline
*/
static int _find_x509_cert(const gnutls_certificate_credentials cred,
opaque * _data, size_t _data_size,
- gnutls_pk_algorithm * pk_algos,
+ const gnutls_pk_algorithm * pk_algos,
int pk_algos_length, int *indx)
{
uint size;
@@ -150,7 +151,9 @@ static int _find_x509_cert(const gnutls_certificate_credentials cred,
for (i = 0; i < cred->ncerts; i++) {
for (j = 0; j < cred->cert_list_length[i]; j++) {
if ((result =
- _gnutls_cert_get_dn( &cred->cert_list[i][j], &odn)) < 0) {
+ _gnutls_cert_get_dn(&cred->
+ cert_list[i][j],
+ &odn)) < 0) {
gnutls_assert();
return result;
}
@@ -162,10 +165,14 @@ static int _find_x509_cert(const gnutls_certificate_credentials cred,
* the *_SIGN algorithm matches
* the cert is our cert!
*/
- cert_pk = cred->cert_list[i][0].subject_pk_algorithm;
+ cert_pk =
+ cred->cert_list[i][0].
+ subject_pk_algorithm;
if ((memcmp(odn.data, data, size) == 0) &&
- (_gnutls_check_pk_algo_in_list(pk_algos, pk_algos_length, cert_pk) == 0)) {
+ (_gnutls_check_pk_algo_in_list
+ (pk_algos, pk_algos_length,
+ cert_pk) == 0)) {
*indx = i;
break;
}
@@ -219,33 +226,194 @@ static int _find_openpgp_cert(const gnutls_certificate_credentials cred,
return 0;
}
-/* Some upper limit to protect alloca();
+/* Returns the number of issuers in the server's
+ * certificate request packet.
*/
-#define MAX_ISSUERS 512
+static int get_issuers_num( gnutls_session session, opaque * data, ssize_t data_size)
+{
+int issuers_dn_len = 0, result;
+uint size;
-/* Finds the appropriate certificate depending on the cA Distinguished name
- * advertized by the server. If none matches then returns 0 and -1 as index.
- * In case of an error a negative value, is returned.
- *
- * 20020128: added ability to select a certificate depending on the SIGN
- * algorithm (only in automatic mode).
+ /* Count the number of the given issuers;
+ * This is used to allocate the issuers_dn without
+ * using realloc().
+ */
+
+ if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
+ return 0;
+
+ do {
+ /* This works like DECR_LEN()
+ */
+ result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ DECR_LENGTH_COM(data_size, 2, goto error);
+ size = _gnutls_read_uint16(data);
+
+ result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ DECR_LENGTH_COM(data_size, size, goto error);
+
+ data += 2;
+
+ if (size > 0) {
+ issuers_dn_len++;
+ data += size;
+ }
+
+ if (data_size == 0)
+ break;
+
+ } while (1);
+
+ return issuers_dn_len;
+
+ error:
+ return result;
+}
+
+/* Returns the issuers in the server's certificate request
+ * packet.
*/
-static int _gnutls_find_acceptable_client_cert(gnutls_session session,
- opaque * _data,
- size_t _data_size, int *ind,
- gnutls_pk_algorithm *
- pk_algos,
- int pk_algos_length)
+static int get_issuers( gnutls_session session,
+ gnutls_datum* issuers_dn, int issuers_len,
+ opaque * data, size_t data_size)
+{
+int i;
+uint size;
+
+ if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
+ return 0;
+
+ /* put the requested DNs to req_dn, only in case
+ * of X509 certificates.
+ */
+ if (issuers_len > 0) {
+
+ for (i = 0; i < issuers_len; i++) {
+ /* The checks here for the buffer boundaries
+ * are not needed since the buffer has been
+ * parsed above.
+ */
+ data_size -= 2;
+
+ size = _gnutls_read_uint16(data);
+
+ data += 2;
+
+ issuers_dn[i].data = data;
+ issuers_dn[i].size = size;
+
+ data += size;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Calls the client_cert_callback() to select an index for the
+ * certificate to use.
+ */
+static int call_client_cert_callback(gnutls_session session,
+ const gnutls_certificate_credentials cred, gnutls_pk_algorithm * pk_algos,
+ int pk_algos_length, gnutls_datum * issuers_dn, uint issuers_dn_len)
{
- int result, size;
- int indx = -1;
uint i, j;
+ int indx, result;
int *ij_map = NULL;
- const gnutls_certificate_credentials cred;
- opaque *data = _data;
- ssize_t data_size = _data_size;
gnutls_datum *my_certs = NULL;
- gnutls_datum *issuers_dn = NULL;
+
+ if (cred->ncerts != 0) {
+ my_certs =
+ gnutls_alloca(cred->ncerts *
+ sizeof(gnutls_datum));
+ if (my_certs == NULL) {
+ result = GNUTLS_E_MEMORY_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+
+
+ /* maps j -> i
+ */
+ ij_map = gnutls_alloca(sizeof(int) * cred->ncerts);
+ if (ij_map == NULL) {
+ result = GNUTLS_E_MEMORY_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ }
+
+ /* put our certificate's issuer and dn into cdn, idn
+ * Note that the certificates we provide to the callback
+ * are not all the certificates we have. Only the certificates
+ * that are requested by the server (certificate type - and sign
+ * algorithm matches), are provided.
+ */
+ for (j = i = 0; i < cred->ncerts; i++) {
+ if ((cred->cert_list[i][0].cert_type ==
+ gnutls_certificate_type_get(session)) &&
+ (_gnutls_check_pk_algo_in_list(pk_algos,
+ pk_algos_length,
+ cred->
+ cert_list[i][0].
+ subject_pk_algorithm)
+ == 0)) {
+ /* Add a certificate ONLY if it is allowed
+ * by the peer.
+ */
+ ij_map[j] = i;
+ my_certs[j++] = cred->cert_list[i][0].raw;
+ }
+ }
+
+ indx =
+ session->internals.client_cert_callback(session,
+ my_certs,
+ j,
+ issuers_dn,
+ issuers_dn_len);
+
+ /* the indx returned by the user is relative
+ * to the certificates we provided him.
+ * This will make it relative to the certificates
+ * we've got.
+ */
+ if (indx != -1 && cred->ncerts != 0)
+ indx = ij_map[indx];
+ else
+ indx = -1;
+
+
+ result = indx;
+
+ error:
+ if (my_certs != NULL) {
+ gnutls_afree(my_certs);
+ }
+ if (ij_map != NULL) {
+ gnutls_afree(ij_map);
+ }
+ return result;
+
+}
+
+OPENPGP_KEY_DEINIT _E_gnutls_openpgp_key_deinit;
+OPENPGP_PRIVKEY_DEINIT _E_gnutls_openpgp_privkey_deinit;
+
+/* Calls the client get callback.
+ */
+static int call_get_cert_callback( gnutls_session session,
+ gnutls_datum* issuers_dn, int issuers_dn_length,
+ gnutls_pk_algorithm* pk_algos, int pk_algos_length)
+{
+uint i;
+gnutls_cert *local_certs = NULL;
+gnutls_privkey *local_key = NULL;
+gnutls_retr_st st;
+int ret;
+gnutls_certificate_type type =
+ gnutls_certificate_type_get(session);
+const gnutls_certificate_credentials cred;
cred =
_gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
@@ -254,185 +422,181 @@ static int _gnutls_find_acceptable_client_cert(gnutls_session session,
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- /* If we have no callback.
- */
- if (session->internals.client_cert_callback == NULL) {
- result = 0;
+ memset( &st, 0, sizeof(st));
- if (session->security_parameters.cert_type ==
- GNUTLS_CRT_X509)
- result =
- _find_x509_cert(cred, _data, _data_size,
- pk_algos, pk_algos_length,
- &indx);
+ if (session->security_parameters.entity == GNUTLS_SERVER) {
+ ret =
+ cred->server_get_cert_callback(session, &st);
+ } else { /* CLIENT */
+ ret =
+ cred->client_get_cert_callback(session,
+ issuers_dn, issuers_dn_length,
+ pk_algos, pk_algos_length,
+ &st);
+ }
- if (session->security_parameters.cert_type ==
- GNUTLS_CRT_OPENPGP)
- result =
- _find_openpgp_cert(cred, pk_algos,
- pk_algos_length, &indx);
+ if (ret < 0) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (type != st.type) {
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+ if (type == GNUTLS_CRT_X509) {
+ local_certs = alloc_and_load_x509_certs(st.cert.x509, st.ncerts);
+ if (local_certs != NULL)
+ local_key = alloc_and_load_x509_key(st.key.x509);
- if (result < 0) {
+ } else { /* PGP */
+ if (st.ncerts != 1) {
gnutls_assert();
- return result;
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
}
- } else /* If the callback is set, then use it. */
- if (session->internals.client_cert_callback != NULL) {
- /* use a callback to get certificate
- */
- uint issuers_dn_len = 0;
- opaque *dataptr = data;
- ssize_t dataptr_size = data_size;
- /* Count the number of the given issuers;
- * This is used to allocate the issuers_dn without
- * using realloc().
- */
+ local_certs = alloc_and_load_pgp_certs(st.cert.pgp);
+ if (local_certs != NULL)
+ local_key = alloc_and_load_pgp_key(st.key.pgp);
- if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
-
- /* Makes the issuers_dn stuff.
- */
- do {
- /* This works like DECR_LEN()
- */
- result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
- DECR_LENGTH_COM(dataptr_size, 2, goto error);
- size = _gnutls_read_uint16(dataptr);
-
- result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
- DECR_LENGTH_COM(dataptr_size, size, goto error);
+ }
- dataptr += 2;
-
- if (size > 0) {
- issuers_dn_len++;
- dataptr += size;
- }
+ _gnutls_selected_certs_set(session, local_certs, (local_certs!=NULL)?st.ncerts:0,
+ local_key, 1);
- if (dataptr_size == 0)
- break;
+ ret = 0;
- } while (issuers_dn_len < MAX_ISSUERS);
+cleanup:
- if (cred->ncerts != 0) {
- my_certs =
- gnutls_alloca(cred->ncerts * sizeof(gnutls_datum));
- if (my_certs == NULL) {
- result = GNUTLS_E_MEMORY_ERROR;
- gnutls_assert();
- goto error;
- }
+ if (st.type == GNUTLS_CRT_X509) {
+ if (st.deinit_all) {
+ for (i = 0; i < st.ncerts; i++) {
+ gnutls_x509_crt_deinit(st.cert.x509[i]);
+ }
+ gnutls_free( st.cert.x509);
+ gnutls_x509_privkey_deinit(st.key.x509);
+ }
+ } else {
+ if (st.deinit_all) {
+ if (_E_gnutls_openpgp_key_deinit == NULL ||
+ _E_gnutls_openpgp_privkey_deinit == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INIT_LIBEXTRA;
}
- /* put the requested DNs to req_dn, only in case
- * of X509 certificates.
- */
- if (issuers_dn_len > 0) {
- data = _data;
- data_size = _data_size;
-
- issuers_dn =
- gnutls_alloca(issuers_dn_len *
- sizeof(gnutls_datum));
- if (issuers_dn == NULL) {
- result = GNUTLS_E_MEMORY_ERROR;
- gnutls_assert();
- goto error;
- }
-
- for (i = 0; i < issuers_dn_len; i++) {
- /* The checks here for the buffer boundaries
- * are not needed since the buffer has been
- * parsed above.
- */
- data_size -= 2;
-
- size = _gnutls_read_uint16(data);
+ _E_gnutls_openpgp_key_deinit(st.cert.pgp);
+ _E_gnutls_openpgp_privkey_deinit(st.key.pgp);
+ }
+ }
- data += 2;
+ return ret;
+}
- issuers_dn[i].data = data;
- issuers_dn[i].size = size;
-
- data += size;
+/* Finds the appropriate certificate depending on the cA Distinguished name
+ * advertized by the server. If none matches then returns 0 and -1 as index.
+ * In case of an error a negative value, is returned.
+ *
+ * 20020128: added ability to select a certificate depending on the SIGN
+ * algorithm (only in automatic mode).
+ */
+static int _select_client_cert(gnutls_session session,
+ opaque * _data, size_t _data_size,
+ gnutls_pk_algorithm * pk_algos,
+ int pk_algos_length)
+{
+ int result;
+ int indx = -1;
+ const gnutls_certificate_credentials cred;
+ opaque *data = _data;
+ ssize_t data_size = _data_size;
+ int issuers_dn_length;
+ gnutls_datum * issuers_dn = NULL;
- }
- }
+ cred =
+ _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
- } else { /* Other certificate types */
- issuers_dn_len = 0;
- issuers_dn = NULL;
- }
+ if (cred->client_get_cert_callback != NULL ||
+ session->internals.client_cert_callback != NULL) {
- /* If not certificates are present.
- */
- /* maps j -> i
+ /* use a callback to get certificate
*/
+ issuers_dn_length = get_issuers_num( session, data, data_size);
+ if (issuers_dn_length < 0) {
+ gnutls_assert();
+ return issuers_dn_length;
+ }
- if (cred->ncerts != 0) {
- ij_map = gnutls_alloca(sizeof(int) * cred->ncerts);
- if (ij_map == NULL) {
- result = GNUTLS_E_MEMORY_ERROR;
+ if (issuers_dn_length > 0) {
+ issuers_dn = gnutls_malloc( sizeof(gnutls_datum)*issuers_dn_length);
+ if (issuers_dn == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ result = get_issuers( session, issuers_dn, issuers_dn_length, data, data_size);
+ if (result < 0) {
gnutls_assert();
- goto error;
+ goto cleanup;
}
}
- /* put our certificate's issuer and dn into cdn, idn
- * Note that the certificates we provide to the callback
- * are not all the certificates we have. Only the certificates
- * that are requested by the server (certificate type - and sign
- * algorithm matches), are provided.
- */
- for (j = i = 0; i < cred->ncerts; i++) {
- if ((cred->cert_list[i][0].cert_type ==
- gnutls_certificate_type_get(session)) &&
- (_gnutls_check_pk_algo_in_list(pk_algos,
- pk_algos_length,
- cred->
- cert_list[i][0].
- subject_pk_algorithm)
- == 0)) {
- /* Add a certificate ONLY if it is allowed
- * by the peer.
- */
- ij_map[j] = i;
- my_certs[j++] = cred->cert_list[i][0].raw;
- }
+ if (cred->client_get_cert_callback) {
+ result = call_get_cert_callback( session, issuers_dn, issuers_dn_length,
+ pk_algos, pk_algos_length);
+ goto cleanup;
}
- indx =
- session->internals.client_cert_callback(session,
- my_certs,
- j,
- issuers_dn,
- issuers_dn_len);
-
- /* the indx returned by the user is relative
- * to the certificates we provided him.
- * This will make it relative to the certificates
- * we've got.
+ /* in case of the callback that returns an index:
*/
- if (indx != -1 && cred->ncerts != 0)
- indx = ij_map[indx];
- else
- indx = -1;
+ indx = call_client_cert_callback(session, cred, pk_algos,
+ pk_algos_length, issuers_dn, issuers_dn_length);
+
+ } else {
+ /* If we have no callbacks, try to guess.
+ */
+ result = 0;
+
+ if (session->security_parameters.cert_type ==
+ GNUTLS_CRT_X509)
+ result =
+ _find_x509_cert(cred, _data, _data_size,
+ pk_algos, pk_algos_length,
+ &indx);
+
+ if (session->security_parameters.cert_type ==
+ GNUTLS_CRT_OPENPGP)
+ result =
+ _find_openpgp_cert(cred, pk_algos,
+ pk_algos_length, &indx);
+
- if (my_certs) gnutls_afree(my_certs);
- if (ij_map) gnutls_afree(ij_map);
- if (issuers_dn) gnutls_afree(issuers_dn);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
}
- *ind = indx;
- return 0;
+ if (indx >= 0) {
+ _gnutls_selected_certs_set(session,
+ &cred->cert_list[indx][0],
+ cred->cert_list_length[indx],
+ &cred->pkey[indx], 0);
+ } else {
+ _gnutls_selected_certs_set(session, NULL, 0, NULL, 0);
+ }
- error:
- if (my_certs != NULL) { gnutls_afree(my_certs); }
- if (ij_map != NULL) { gnutls_afree(ij_map); }
- if (issuers_dn != NULL) { gnutls_afree(issuers_dn); }
- return result;
+ result = 0;
+
+cleanup:
+ gnutls_free( issuers_dn);
+ return result;
}
@@ -450,9 +614,9 @@ int _gnutls_gen_x509_crt(gnutls_session session, opaque ** data)
/* find the appropriate certificate
*/
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
- &apr_cert_list_length,
- &apr_pkey)) < 0) {
+ _gnutls_get_selected_cert(session, &apr_cert_list,
+ &apr_cert_list_length,
+ &apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
@@ -497,14 +661,14 @@ int _gnutls_gen_openpgp_certificate(gnutls_session session, opaque ** data)
int ret;
opaque *pdata;
gnutls_cert *apr_cert_list;
- gnutls_privkey* apr_pkey;
+ gnutls_privkey *apr_pkey;
int apr_cert_list_length;
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
- &apr_cert_list_length,
- &apr_pkey)) < 0) {
+ _gnutls_get_selected_cert(session, &apr_cert_list,
+ &apr_cert_list_length,
+ &apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
@@ -539,7 +703,7 @@ int _gnutls_gen_openpgp_certificate(gnutls_session session, opaque ** data)
OPENPGP_FINGERPRINT _E_gnutls_openpgp_fingerprint = NULL;
OPENPGP_KEY_REQUEST _E_gnutls_openpgp_request_key = NULL;
-extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
+extern OPENPGP_RAW_KEY_TO_GCERT _E_gnutls_openpgp_raw_key_to_gcert;
int _gnutls_gen_openpgp_certificate_fpr(gnutls_session session,
opaque ** data)
@@ -548,14 +712,14 @@ int _gnutls_gen_openpgp_certificate_fpr(gnutls_session session,
size_t fpr_size;
opaque *pdata;
gnutls_cert *apr_cert_list;
- gnutls_privkey* apr_pkey;
+ gnutls_privkey *apr_pkey;
int apr_cert_list_length;
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
- &apr_cert_list_length,
- &apr_pkey)) < 0) {
+ _gnutls_get_selected_cert(session, &apr_cert_list,
+ &apr_cert_list_length,
+ &apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
@@ -644,7 +808,7 @@ int _gnutls_gen_cert_server_certificate(gnutls_session session,
/* Process server certificate
*/
-#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_free_cert(&peer_certificate_list[x])
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_gcert_deinit(&peer_certificate_list[x])
int _gnutls_proc_x509_server_certificate(gnutls_session session,
opaque * data, size_t data_size)
{
@@ -738,9 +902,10 @@ int _gnutls_proc_x509_server_certificate(gnutls_session session,
tmp.data = p;
if ((ret =
- _gnutls_x509_cert2gnutls_cert(&peer_certificate_list
+ _gnutls_x509_raw_cert_to_gcert(&peer_certificate_list
[j], &tmp,
- CERT_ONLY_EXTENSIONS)) < 0) {
+ CERT_ONLY_EXTENSIONS)) <
+ 0) {
gnutls_assert();
goto cleanup;
}
@@ -750,30 +915,31 @@ int _gnutls_proc_x509_server_certificate(gnutls_session session,
if ((ret =
- _gnutls_copy_certificate_auth_info(info,
+ _gnutls_copy_certificate_auth_info(info,
peer_certificate_list,
- peer_certificate_list_size)) < 0) {
+ peer_certificate_list_size))
+ < 0) {
gnutls_assert();
goto cleanup;
}
if ((ret =
_gnutls_check_key_usage(&peer_certificate_list[0],
- gnutls_kx_get(session))) < 0) {
+ gnutls_kx_get(session))) < 0) {
gnutls_assert();
goto cleanup;
}
ret = 0;
-cleanup:
+ cleanup:
CLEAR_CERTS;
gnutls_free(peer_certificate_list);
return ret;
}
-#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_free_cert(&peer_certificate_list[x])
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_gcert_deinit(&peer_certificate_list[x])
int _gnutls_proc_openpgp_server_certificate(gnutls_session session,
opaque * data,
size_t data_size)
@@ -898,14 +1064,14 @@ int _gnutls_proc_openpgp_server_certificate(gnutls_session session,
memset(peer_certificate_list, 0, sizeof(gnutls_cert) *
peer_certificate_list_size);
- if (_E_gnutls_openpgp_cert2gnutls_cert == NULL) {
+ if (_E_gnutls_openpgp_raw_key_to_gcert == NULL) {
gnutls_assert();
ret = GNUTLS_E_INIT_LIBEXTRA;
goto cleanup;
}
if ((ret =
- _E_gnutls_openpgp_cert2gnutls_cert(&peer_certificate_list[0],
+ _E_gnutls_openpgp_raw_key_to_gcert(&peer_certificate_list[0],
&tmp)) < 0) {
gnutls_assert();
goto cleanup;
@@ -913,28 +1079,29 @@ int _gnutls_proc_openpgp_server_certificate(gnutls_session session,
if ((ret =
_gnutls_copy_certificate_auth_info(info,
- peer_certificate_list,
- peer_certificate_list_size)) < 0) {
+ peer_certificate_list,
+ peer_certificate_list_size))
+ < 0) {
gnutls_assert();
goto cleanup;
}
if ((ret =
_gnutls_check_key_usage(&peer_certificate_list[0],
- gnutls_kx_get(session))) < 0) {
+ gnutls_kx_get(session))) < 0) {
gnutls_assert();
goto cleanup;
}
ret = 0;
-
-cleanup:
+
+ cleanup:
_gnutls_free_datum(&akey);
CLEAR_CERTS;
gnutls_afree(peer_certificate_list);
return ret;
-
+
}
int _gnutls_proc_cert_server_certificate(gnutls_session session,
@@ -983,7 +1150,7 @@ int _gnutls_proc_cert_cert_req(gnutls_session session, opaque * data,
const gnutls_certificate_credentials cred;
CERTIFICATE_AUTH_INFO info;
ssize_t dsize = data_size;
- int i, j, ind;
+ int i, j;
gnutls_pk_algorithm pk_algos[MAX_SIGN_ALGOS];
int pk_algos_length;
@@ -1040,15 +1207,11 @@ int _gnutls_proc_cert_cert_req(gnutls_session session, opaque * data,
* he wants to use.
*/
if ((ret =
- _gnutls_find_acceptable_client_cert(session, p, size,
- &ind, pk_algos,
- pk_algos_length)) < 0) {
+ _select_client_cert(session, p, size,
+ pk_algos, pk_algos_length)) < 0) {
gnutls_assert();
return ret;
}
- /* put the index of the client certificate to use
- */
- session->internals.selected_cert_index = ind;
/* We should reply with a certificate message,
* even if we have no certificate to send.
@@ -1063,7 +1226,7 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session,
{
int ret;
gnutls_cert *apr_cert_list;
- gnutls_privkey* apr_pkey;
+ gnutls_privkey *apr_pkey;
int apr_cert_list_length, size;
gnutls_datum signature;
@@ -1071,9 +1234,9 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session,
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
- &apr_cert_list_length,
- &apr_pkey)) < 0) {
+ _gnutls_get_selected_cert(session, &apr_cert_list,
+ &apr_cert_list_length,
+ &apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
@@ -1081,9 +1244,8 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session,
if (apr_pkey != NULL) {
if ((ret =
_gnutls_tls_sign_hdata(session,
- &apr_cert_list[0],
- apr_pkey,
- &signature)) < 0) {
+ &apr_cert_list[0],
+ apr_pkey, &signature)) < 0) {
gnutls_assert();
return ret;
}
@@ -1132,29 +1294,9 @@ int _gnutls_proc_cert_client_cert_vrfy(gnutls_session session,
sig.data = pdata;
sig.size = size;
- switch (session->security_parameters.cert_type) {
- case GNUTLS_CRT_X509:
- ret =
- _gnutls_x509_cert2gnutls_cert(&peer_cert,
- &info->
- raw_certificate_list[0],
- CERT_NO_COPY);
- break;
- case GNUTLS_CRT_OPENPGP:
- if (_E_gnutls_openpgp_cert2gnutls_cert == NULL) {
- gnutls_assert();
- return GNUTLS_E_INIT_LIBEXTRA;
- }
- ret =
- _E_gnutls_openpgp_cert2gnutls_cert(&peer_cert,
- &info->
- raw_certificate_list
- [0]);
- break;
- default:
- gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
- }
+ ret = _gnutls_raw_cert_to_gcert( &peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_NO_COPY);
if (ret < 0) {
gnutls_assert();
@@ -1164,10 +1306,10 @@ int _gnutls_proc_cert_client_cert_vrfy(gnutls_session session,
if ((ret =
_gnutls_verify_sig_hdata(session, &peer_cert, &sig)) < 0) {
gnutls_assert();
- _gnutls_free_cert(&peer_cert);
+ _gnutls_gcert_deinit(&peer_cert);
return ret;
}
- _gnutls_free_cert(&peer_cert);
+ _gnutls_gcert_deinit(&peer_cert);
return 0;
}
@@ -1196,7 +1338,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session,
*/
if (session->security_parameters.cert_type == GNUTLS_CRT_X509 &&
- session->internals.ignore_rdn_sequence == 0)
+ session->internals.ignore_rdn_sequence == 0)
size += cred->x509_rdn_sequence.size;
(*data) = gnutls_malloc(size);
@@ -1214,7 +1356,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session,
pdata += CERTTYPE_SIZE;
if (session->security_parameters.cert_type == GNUTLS_CRT_X509 &&
- session->internals.ignore_rdn_sequence == 0) {
+ session->internals.ignore_rdn_sequence == 0) {
_gnutls_write_datum16(pdata, cred->x509_rdn_sequence);
/* pdata += cred->x509_rdn_sequence.size + 2; */
}
@@ -1230,117 +1372,223 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session,
* It is normal to return 0 with no certificates in client side.
*
*/
-int _gnutls_find_apr_cert(gnutls_session session,
- gnutls_cert ** apr_cert_list,
- int *apr_cert_list_length,
- gnutls_privkey ** apr_pkey)
+int _gnutls_get_selected_cert(gnutls_session session,
+ gnutls_cert ** apr_cert_list,
+ int *apr_cert_list_length,
+ gnutls_privkey ** apr_pkey)
{
- const gnutls_certificate_credentials cred;
- int ind;
+ if (session->security_parameters.entity == GNUTLS_SERVER) {
- cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
+ /* select_client_cert() has been called before.
+ */
+
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_pkey = session->internals.selected_key;
+ *apr_cert_list_length =
+ session->internals.selected_cert_list_length;
+
+ if (apr_cert_list_length == 0 || apr_pkey == NULL ||
+ apr_cert_list == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ } else { /* CLIENT SIDE
+ */
+
+ /* we have already decided which certificate
+ * to send.
+ */
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_cert_list_length =
+ session->internals.selected_cert_list_length;
+ *apr_pkey = session->internals.selected_key;
- if (cred == NULL) {
- gnutls_assert();
- *apr_cert_list = NULL;
- *apr_pkey = NULL;
- *apr_cert_list_length = 0;
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if (session->security_parameters.entity == GNUTLS_SERVER) {
+ return 0;
+}
- if (cred->ncerts == 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- gnutls_assert(); /* this is not allowed */
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- } else {
- /* find_cert_list_index() has been called before.
- */
- ind = session->internals.selected_cert_index;
+/* converts the given x509 certificate to gnutls_cert* and allocates
+ * space for them.
+ */
+static gnutls_cert *alloc_and_load_x509_certs(gnutls_x509_crt * certs,
+ uint ncerts)
+{
+ gnutls_cert *local_certs;
+ int ret = 0;
+ uint i, j;
- if (ind < 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- gnutls_assert();
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- } else {
- *apr_cert_list = cred->cert_list[ind];
- *apr_cert_list_length =
- cred->cert_list_length[ind];
- *apr_pkey = &cred->pkey[ind];
- }
- }
- } else { /* CLIENT SIDE */
- if (cred->ncerts == 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- /* it is allowed not to have a certificate
- */
- } else {
- /* we had already decided which certificate
- * to send.
- */
- ind = session->internals.selected_cert_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];
- }
+ local_certs = gnutls_malloc(sizeof(gnutls_cert) * ncerts);
+ if (local_certs == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ for (i = 0; i < ncerts; i++) {
+ ret = _gnutls_x509_crt_to_gcert(&local_certs[i],
+ certs[i], 0);
+ if (ret < 0)
+ break;
+ }
+
+ if (ret < 0) {
+ gnutls_assert();
+ for (j = 0; j < i; j++) {
+ _gnutls_gcert_deinit(&local_certs[j]);
}
+ gnutls_free(local_certs);
+ return NULL;
+ }
+ return local_certs;
+}
+
+/* converts the given x509 key to gnutls_privkey* and allocates
+ * space for it.
+ */
+static gnutls_privkey *alloc_and_load_x509_key(gnutls_x509_privkey key)
+{
+ gnutls_privkey *local_key;
+ int ret = 0;
+
+ local_key = gnutls_malloc(sizeof(gnutls_privkey));
+ if (local_key == NULL) {
+ gnutls_assert();
+ return NULL;
}
- return 0;
+ ret =
+ _gnutls_x509_privkey_to_gkey(local_key, key);
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ return local_key;
}
-/* finds the most appropriate certificate in the cert list.
- * The 'appropriate' is defined by the user.
- * (frontend to _gnutls_server_find_cert_index())
+
+OPENPGP_KEY_TO_GCERT _E_gnutls_openpgp_key_to_gcert;
+OPENPGP_PRIVKEY_TO_GKEY _E_gnutls_openpgp_privkey_to_gkey;
+
+/* converts the given pgp certificate to gnutls_cert* and allocates
+ * space for them.
*/
-const gnutls_cert *_gnutls_server_find_cert(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo)
+static gnutls_cert *alloc_and_load_pgp_certs(gnutls_openpgp_key cert)
{
- int i;
- const gnutls_certificate_credentials x509_cred;
+ gnutls_cert *local_certs;
+ int ret = 0;
+ uint i, j;
- x509_cred =
- _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
+ local_certs = gnutls_malloc(sizeof(gnutls_cert));
+ if (local_certs == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
- if (x509_cred == NULL)
+ if (_E_gnutls_openpgp_key_to_gcert==NULL) {
+ gnutls_assert();
return NULL;
+ }
- i = _gnutls_server_find_cert_list_index(session, requested_algo);
+ ret = _E_gnutls_openpgp_key_to_gcert(&local_certs[i], cert);
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
- if (i < 0)
+ if (ret < 0) {
+ gnutls_assert();
+ for (j = 0; j < i; j++) {
+ _gnutls_gcert_deinit(&local_certs[j]);
+ }
+ gnutls_free(local_certs);
return NULL;
+ }
- return &x509_cred->cert_list[i][0];
+ return local_certs;
}
+/* converts the given raw key to gnutls_privkey* and allocates
+ * space for it.
+ */
+static gnutls_privkey *alloc_and_load_pgp_key(const gnutls_openpgp_privkey key)
+{
+ gnutls_privkey *local_key;
+ int ret = 0;
+
+ local_key = gnutls_malloc(sizeof(gnutls_privkey));
+ if (local_key == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ if (_E_gnutls_openpgp_privkey_to_gkey==NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ ret =
+ _E_gnutls_openpgp_privkey_to_gkey(local_key, key);
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ return local_key;
+}
+
+
+void _gnutls_selected_certs_deinit(gnutls_session session)
+{
+ if (session->internals.selected_need_free != 0) {
+ int i;
+
+ for (i = 0;
+ i < session->internals.selected_cert_list_length;
+ i++) {
+ _gnutls_gcert_deinit(&session->internals.
+ selected_cert_list[i]);
+ }
+ session->internals.selected_cert_list = NULL;
+ session->internals.selected_cert_list_length = 0;
+
+ _gnutls_gkey_deinit(session->internals.selected_key);
+ }
+
+ return;
+}
+
+void _gnutls_selected_certs_set(gnutls_session session,
+ gnutls_cert * certs, int ncerts,
+ gnutls_privkey * key, int need_free)
+{
+ _gnutls_selected_certs_deinit(session);
+
+ session->internals.selected_cert_list = certs;
+ session->internals.selected_cert_list_length = ncerts;
+ session->internals.selected_key = key;
+ session->internals.selected_need_free = need_free;
+
+}
+
+
/* finds the most appropriate certificate in the cert list.
* The 'appropriate' is defined by the user.
*
* requested_algo holds the parameters required by the peer (RSA, DSA
* or -1 for any).
+ *
+ * Returns 0 on success and a negative value on error. The
+ * selected certificate will be in session->internals.selected_*.
+ *
*/
-static int _gnutls_server_find_cert_list_index(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo)
+int _gnutls_server_select_cert(gnutls_session session,
+ gnutls_pk_algorithm requested_algo)
{
uint i, j;
- int index;
+ int index, ret;
const gnutls_certificate_credentials cred;
int my_certs_length;
@@ -1351,10 +1599,12 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
+ ret = 0;
index = -1; /* default is use no certificate */
for (i = 0; i < cred->ncerts; i++) {
- /* find one compatible certificate */
+ /* find one compatible certificate
+ */
if (requested_algo == (gnutls_pk_algorithm) - 1 ||
requested_algo ==
cred->cert_list[i][0].subject_pk_algorithm) {
@@ -1368,7 +1618,15 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
}
- if (session->internals.server_cert_callback != NULL && cred->ncerts > 0) {
+ /* If the callback which retrieves certificate has been
+ * set use it.
+ */
+ if (cred->server_get_cert_callback != NULL) {
+
+ return call_get_cert_callback( session, NULL, 0, NULL, 0);
+
+ } else if (session->internals.server_cert_callback != NULL
+ && cred->ncerts > 0) {
/* use the callback to get certificate
*/
gnutls_datum *my_certs;
@@ -1377,13 +1635,18 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
my_certs_length = cred->ncerts;
my_certs =
gnutls_malloc(my_certs_length * sizeof(gnutls_datum));
- if (my_certs == NULL)
+ if (my_certs == NULL) {
+ ret = GNUTLS_E_MEMORY_ERROR;
goto out;
+ }
/* put our certificate's issuer and dn into cdn, idn
*/
ij_map = gnutls_malloc(my_certs_length * sizeof(int));
- if (ij_map == NULL) goto cleanup_certs;
+ if (ij_map == NULL) {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup_certs;
+ }
j = 0;
for (i = 0; i < cred->ncerts; i++) {
@@ -1412,17 +1675,24 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
if (index != -1)
index = ij_map[index];
+ ret = 0;
gnutls_free(ij_map);
- cleanup_certs:
+ cleanup_certs:
gnutls_free(my_certs);
}
- out:
+ out:
/* store the index for future use, in the handshake.
* (This will allow not calling this callback again.)
*/
- session->internals.selected_cert_index = index;
- return index;
+ if (index >= 0 && ret == 0) {
+ _gnutls_selected_certs_set(session,
+ &cred->cert_list[index][0],
+ cred->cert_list_length[index],
+ &cred->pkey[index], 0);
+ }
+
+ return ret;
}
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index a9760ab0ec..d99991a9b7 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -3,6 +3,31 @@
# include "gnutls_cert.h"
# include "gnutls_auth.h"
# include "x509/x509.h"
+#include "../libextra/openpgp/openpgp.h"
+
+typedef struct retr_st {
+ gnutls_certificate_type type;
+ union cert {
+ gnutls_x509_crt* x509;
+ gnutls_openpgp_key pgp;
+ } cert;
+ uint ncerts;
+
+ union key {
+ gnutls_x509_privkey x509;
+ gnutls_openpgp_privkey pgp;
+ } key;
+
+ uint deinit_all;
+} gnutls_retr_st;
+
+typedef int gnutls_certificate_client_retrieve_function(gnutls_session,
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ const gnutls_pk_algorithm* pk_algos, int pk_algos_length,
+ gnutls_retr_st *);
+
+typedef int gnutls_certificate_server_retrieve_function(
+ struct gnutls_session_int*, gnutls_retr_st*);
/* This structure may be complex, but it's the only way to
* support a server that has multiple certificates
@@ -59,6 +84,9 @@ typedef struct {
* generating on every handshake.
*/
gnutls_datum x509_rdn_sequence;
+
+ gnutls_certificate_client_retrieve_function* client_get_cert_callback;
+ gnutls_certificate_server_retrieve_function* server_get_cert_callback;
} CERTIFICATE_CREDENTIALS_INT;
/* typedef CERTIFICATE_CREDENTIALS_INT * CERTIFICATE_CREDENTIALS; */
@@ -89,8 +117,13 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session, opaque **);
int _gnutls_proc_cert_cert_req(gnutls_session, opaque *, size_t);
int _gnutls_proc_cert_client_cert_vrfy(gnutls_session, opaque *, size_t);
int _gnutls_proc_cert_server_certificate(gnutls_session, opaque *, size_t);
-int _gnutls_find_apr_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey);
-const gnutls_cert * _gnutls_server_find_cert( struct gnutls_session_int*, gnutls_pk_algorithm);
+int _gnutls_get_selected_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey);
+
+int _gnutls_server_select_cert( struct gnutls_session_int*, gnutls_pk_algorithm);
+void _gnutls_selected_certs_deinit( gnutls_session session);
+void _gnutls_selected_certs_set( gnutls_session session,
+ gnutls_cert* certs, int ncerts, gnutls_privkey* key,
+ int need_free);
#define _gnutls_proc_cert_client_certificate _gnutls_proc_cert_server_certificate
diff --git a/lib/auth_dh_common.c b/lib/auth_dh_common.c
index 287c5c4191..7ae1ea1703 100644
--- a/lib/auth_dh_common.c
+++ b/lib/auth_dh_common.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c
index 8e255da02d..79f499156f 100644
--- a/lib/auth_dhe.c
+++ b/lib/auth_dhe.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -79,6 +80,7 @@ const MOD_AUTH_STRUCT dhe_dss_auth_struct = {
static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
{
GNUTLS_MPI g, p;
+ const GNUTLS_MPI *mpis;
int ret = 0, data_size;
int bits;
gnutls_cert *apr_cert_list;
@@ -98,18 +100,22 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_CERTIFICATE,
sizeof( CERTIFICATE_AUTH_INFO_INT), 0)) < 0)
{
@@ -125,8 +131,6 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
}
ret = _gnutls_dh_common_print_server_kx( session, g, p, data);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
if (ret < 0) {
gnutls_assert();
@@ -168,9 +172,6 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
return data_size;
}
-
-OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert = NULL;
-
static int proc_dhe_server_kx(gnutls_session session, opaque * data,
size_t _data_size)
{
@@ -205,32 +206,11 @@ static int proc_dhe_server_kx(gnutls_session session, opaque * data,
signature.data = &data[vparams.size + 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;
+ if ((ret =
+ _gnutls_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) {
+ gnutls_assert();
+ return ret;
}
ret =
@@ -238,7 +218,7 @@ static int proc_dhe_server_kx(gnutls_session session, opaque * data,
&peer_cert,
&vparams, &signature);
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -256,6 +236,7 @@ int bits;
const gnutls_certificate_credentials cred;
int ret;
GNUTLS_MPI p, g;
+const GNUTLS_MPI *mpis;
bits = _gnutls_dh_get_prime_bits( session);
@@ -265,14 +246,16 @@ GNUTLS_MPI p, g;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
ret = _gnutls_proc_dh_common_client_kx( session, data, _data_size, g, p);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
return ret;
diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c
index ef8d0d6d5e..5931460274 100644
--- a/lib/auth_rsa.c
+++ b/lib/auth_rsa.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -60,9 +61,6 @@ const MOD_AUTH_STRUCT rsa_auth_struct = {
_gnutls_proc_cert_cert_req /* proc server cert request */
};
-/* in auth_dhe.c */
-extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
-
/* This function reads the RSA parameters from peer's certificate;
*/
int _gnutls_get_public_rsa_params(gnutls_session session,
@@ -82,32 +80,13 @@ int i;
return GNUTLS_E_INTERNAL_ERROR;
}
- switch( session->security_parameters.cert_type) {
- case GNUTLS_CRT_X509:
- if ((ret =
- _gnutls_x509_cert2gnutls_cert( &peer_cert,
- &info->raw_certificate_list[0], CERT_ONLY_PUBKEY|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:
+ ret =
+ _gnutls_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_ONLY_PUBKEY|CERT_NO_COPY);
+
+ if (ret < 0) {
gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ return ret;
}
@@ -116,7 +95,7 @@ int i;
== GNUTLS_KX_RSA_EXPORT &&
_gnutls_mpi_get_nbits(peer_cert.params[0]) > 512) {
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
if (session->key->rsa[0] == NULL ||
session->key->rsa[1] == NULL) {
@@ -147,7 +126,7 @@ int i;
for (i=0;i<*params_len;i++) {
params[i] = _gnutls_mpi_copy(peer_cert.params[i]);
}
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
return 0;
}
@@ -156,7 +135,7 @@ int i;
*/
int _gnutls_get_private_rsa_params(gnutls_session session, GNUTLS_MPI **params, int* params_size)
{
-int index;
+int bits;
const gnutls_certificate_credentials cred;
cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
@@ -165,14 +144,16 @@ const gnutls_certificate_credentials cred;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (index=session->internals.selected_cert_index) < 0) {
+ if (session->internals.selected_cert_list == NULL) {
gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
+ bits = _gnutls_mpi_get_nbits(session->internals.selected_cert_list[0].params[0]);
+
if ( _gnutls_cipher_suite_get_kx_algo(session->security_parameters.current_cipher_suite)
== GNUTLS_KX_RSA_EXPORT &&
- _gnutls_mpi_get_nbits(cred->cert_list[index][0].params[0]) > 512) {
+ bits > 512) {
/* EXPORT case: */
if (cred->rsa_params == NULL) {
@@ -192,8 +173,8 @@ const gnutls_certificate_credentials cred;
/* non export cipher suites. */
- *params_size = cred->pkey[index].params_size;
- *params = cred->pkey[index].params;
+ *params_size = session->internals.selected_key->params_size;
+ *params = session->internals.selected_key->params;
return 0;
}
diff --git a/lib/auth_rsa_export.c b/lib/auth_rsa_export.c
index 3ae0096690..340c7e5aa3 100644
--- a/lib/auth_rsa_export.c
+++ b/lib/auth_rsa_export.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -64,9 +65,6 @@ const MOD_AUTH_STRUCT rsa_export_auth_struct = {
_gnutls_proc_cert_cert_req /* proc server cert request */
};
-extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
-
-
static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data)
{
const GNUTLS_MPI *rsa_params;
@@ -88,7 +86,7 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data)
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -191,47 +189,26 @@ CERTIFICATE_AUTH_INFO info = _gnutls_get_auth_info( session);
return 0;
}
- 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 0;
- }
- 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 0;
- }
- break;
-
- default:
- gnutls_assert();
- return 0;
+ if ((ret =
+ _gnutls_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) {
+ gnutls_assert();
+ return 0;
}
if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA) {
gnutls_assert();
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
return 0;
}
if ( _gnutls_mpi_get_nbits( peer_cert.params[0])
<= 512) {
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
return 1;
}
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
return 0;
}
@@ -308,32 +285,11 @@ static int proc_rsa_export_server_kx(gnutls_session session, opaque * data,
signature.data = &data[vparams.size + 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;
+ if ((ret =
+ _gnutls_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) {
+ gnutls_assert();
+ return ret;
}
ret =
@@ -341,7 +297,7 @@ static int proc_rsa_export_server_kx(gnutls_session session, opaque * data,
&peer_cert,
&vparams, &signature);
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
if (ret < 0) {
gnutls_assert();
}
diff --git a/lib/debug.c b/lib/debug.c
index cc3c9f72ab..d944fe6b3b 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2000,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2000,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/dh_compat.c b/lib/dh_compat.c
deleted file mode 100644
index f6f1f49a05..0000000000
--- a/lib/dh_compat.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2000,2001,2003 Nikos Mavroyanopoulos
- *
- * This file is part of GNUTLS.
- *
- * The GNUTLS library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; 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 <gnutls_datum.h>
-#include <x509_b64.h> /* for PKCS3 PEM decoding */
-#include <gnutls_global.h>
-#include <gnutls_dh.h>
-#include "debug.h"
-
-/* Replaces the prime in the static DH parameters, with a randomly
- * generated one.
- */
-/*-
- * gnutls_dh_params_set - This function will replace the old DH parameters
- * @dh_params: Is a structure will hold the prime numbers
- * @prime: holds the new prime
- * @generator: holds the new generator
- * @bits: is the prime's number of bits. This value is ignored.
- *
- * This function will replace the pair of prime and generator for use in
- * the Diffie-Hellman key exchange. The new parameters should be stored in the
- * appropriate gnutls_datum.
- *
- -*/
-int gnutls_dh_params_set(gnutls_dh_params dh_params, gnutls_datum prime,
- gnutls_datum generator, int bits)
-{
- GNUTLS_MPI tmp_prime, tmp_g;
- size_t siz = 0;
-
- /* sprime is not null, because of the check_bits()
- * above.
- */
-
- siz = prime.size;
- if (_gnutls_mpi_scan(&tmp_prime, prime.data, &siz)) {
- gnutls_assert();
- return GNUTLS_E_MPI_SCAN_FAILED;
- }
-
- siz = generator.size;
- if (_gnutls_mpi_scan(&tmp_g, generator.data, &siz)) {
- _gnutls_mpi_release(&tmp_prime);
- gnutls_assert();
- return GNUTLS_E_MPI_SCAN_FAILED;
- }
-
- /* copy the generated values to the structure
- */
- dh_params->_prime = tmp_prime;
- dh_params->_generator = tmp_g;
-
- return 0;
-
-}
-
-/*-
- * gnutls_dh_params_generate - This function will generate new DH parameters
- * @prime: will hold the new prime
- * @generator: will hold the new generator
- * @bits: is the prime's number of bits
- *
- * This function will generate a new pair of prime and generator for use in
- * the Diffie-Hellman key exchange. The new parameters will be allocated using
- * gnutls_malloc() and will be stored in the appropriate datum.
- * This function is normally very slow. Another function
- * (gnutls_dh_params_set()) should be called in order to replace the
- * included DH primes in the gnutls library.
- *
- * Note that the bits value should be one of 768, 1024, 2048, 3072 or 4096.
- * Also note that the generation of new DH parameters is only useful
- * to servers. Clients use the parameters sent by the server, thus it's
- * no use calling this in client side.
- *
- -*/
-int gnutls_dh_params_generate(gnutls_datum * prime,
- gnutls_datum * generator, int bits)
-{
-
- GNUTLS_MPI tmp_prime, tmp_g;
- size_t siz;
-
- if (_gnutls_dh_generate_prime(&tmp_g, &tmp_prime, bits) < 0) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, tmp_g);
-
- generator->data = gnutls_malloc(siz);
- if (generator->data == NULL) {
- _gnutls_mpi_release(&tmp_g);
- _gnutls_mpi_release(&tmp_prime);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- generator->size = siz;
- _gnutls_mpi_print(generator->data, &siz, tmp_g);
-
-
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, tmp_prime);
-
- prime->data = gnutls_malloc(siz);
- if (prime->data == NULL) {
- gnutls_free(generator->data);
- generator->data = NULL; generator->size = 0;
- _gnutls_mpi_release(&tmp_g);
- _gnutls_mpi_release(&tmp_prime);
- return GNUTLS_E_MEMORY_ERROR;
- }
- prime->size = siz;
- _gnutls_mpi_print(prime->data, &siz, tmp_prime);
-
-#ifdef DEBUG
- {
- opaque buffer[512];
-
- _gnutls_debug_log
- ("dh_params_generate: Generated %d bits prime %s, generator %s.\n",
- bits, _gnutls_bin2hex(prime->data, prime->size, buffer, sizeof(buffer)),
- _gnutls_bin2hex(generator->data, generator->size, buffer, sizeof(buffer)));
- }
-#endif
-
- return 0;
-
-}
diff --git a/lib/ext_cert_type.c b/lib/ext_cert_type.c
index 7375646124..ba2998ff00 100644
--- a/lib/ext_cert_type.c
+++ b/lib/ext_cert_type.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c
index 59e31590f8..c0ccff7f58 100644
--- a/lib/ext_max_record.c
+++ b/lib/ext_max_record.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/ext_server_name.c b/lib/ext_server_name.c
index e8778145f6..e0cd9d5ccb 100644
--- a/lib/ext_server_name.c
+++ b/lib/ext_server_name.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -128,7 +129,8 @@ int _gnutls_server_name_send_params(gnutls_session session, opaque * data,
if (session->security_parameters.extensions.server_names_size == 0)
return 0;
- /* uint16 */
+ /* uint16
+ */
total_size = 2;
for (i = 0;
i < session->security_parameters.extensions.server_names_size;
@@ -203,8 +205,7 @@ int _gnutls_server_name_send_params(gnutls_session session, opaque * data,
* gnutls_server_name_type.
*
* If @type is GNUTLS_NAME_DNS, then this function is to be used by servers
- * that support virtual hosting, and the data will be null terminated.
- * The client may give the server the dnsname they connected to.
+ * that support virtual hosting, and the data will be a null terminated UTF-8 string.
*
* If @data has not enough size to hold the server name GNUTLS_E_SHORT_MEMORY_BUFFER
* is returned, and @data_length will hold the required size.
@@ -265,12 +266,13 @@ int gnutls_server_name_get(gnutls_session session, void *data,
* @name_length: holds the length of name
*
* This function is to be used by clients that want to inform
- * ( via a TLS extension mechanism) the server of the name they
+ * (via a TLS extension mechanism) the server of the name they
* connected to. This should be used by clients that connect
* to servers that do virtual hosting.
*
* The value of @name depends on the @ind type. In case of GNUTLS_NAME_DNS,
- * a null terminated string is expected.
+ * an ASCII or UTF-8 null terminated string, without the trailing dot, is expected.
+ * IPv4 or IPv6 addresses are not permitted.
*
**/
int gnutls_server_name_set(gnutls_session session,
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in
index 6a1fc387d0..aa1f34e8b3 100644
--- a/lib/gnutls.h.in.in
+++ b/lib/gnutls.h.in.in
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -122,7 +123,6 @@ typedef enum gnutls_handshake_description { GNUTLS_HANDSHAKE_HELLO_REQUEST,
/* Note that the status bits have different meanings
* in openpgp keys and x.509 certificate verification.
*/
-#define GNUTLS_CERT_NOT_TRUSTED GNUTLS_CERT_INVALID
typedef enum gnutls_certificate_status {
GNUTLS_CERT_INVALID=2, /* will be set if the certificate
* was not verified.
@@ -147,7 +147,8 @@ typedef enum gnutls_openpgp_key_status { GNUTLS_OPENPGP_KEY,
typedef enum gnutls_close_request { GNUTLS_SHUT_RDWR=0, GNUTLS_SHUT_WR=1 } gnutls_close_request;
#define GNUTLS_TLS1 GNUTLS_TLS1_0
-typedef enum gnutls_protocol_version { GNUTLS_SSL3=1, GNUTLS_TLS1_0 } gnutls_protocol_version;
+typedef enum gnutls_protocol_version { GNUTLS_SSL3=1, GNUTLS_TLS1_0,
+ } gnutls_protocol_version;
typedef enum gnutls_certificate_type { GNUTLS_CRT_X509=1, GNUTLS_CRT_OPENPGP
} gnutls_certificate_type;
@@ -234,8 +235,6 @@ void gnutls_handshake_set_private_extensions(gnutls_session session, int allow);
gnutls_handshake_description gnutls_handshake_get_last_out( gnutls_session session);
gnutls_handshake_description gnutls_handshake_get_last_in( gnutls_session session);
-void gnutls_record_set_cbc_protection(gnutls_session session, int prot);
-
/* Record layer functions.
*/
ssize_t gnutls_record_send( gnutls_session session, const void *data, size_t sizeofdata);
@@ -354,6 +353,7 @@ int gnutls_certificate_allocate_credentials( gnutls_certificate_credentials *sc)
void gnutls_certificate_free_keys(gnutls_certificate_credentials sc);
void gnutls_certificate_free_cas(gnutls_certificate_credentials sc);
+void gnutls_certificate_free_ca_names(gnutls_certificate_credentials sc);
void gnutls_certificate_free_crls(gnutls_certificate_credentials sc);
void gnutls_certificate_set_dh_params(gnutls_certificate_credentials res, gnutls_dh_params);
diff --git a/lib/gnutls_alert.c b/lib/gnutls_alert.c
index d8dc35c9a4..462bb795b6 100644
--- a/lib/gnutls_alert.c
+++ b/lib/gnutls_alert.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index eb55209b68..30c330fddf 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -25,7 +26,10 @@
#include "gnutls_cert.h"
-/* Cred type mappings to KX algorithms */
+/* Cred type mappings to KX algorithms
+ * FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require
+ * more than one credentials type.
+ */
typedef struct {
gnutls_kx_algorithm algorithm;
gnutls_credentials_type client_type;
@@ -40,8 +44,8 @@ static const gnutls_cred_map cred_mappings[] = {
{ 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 },
- { GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE },
+ { GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE },
+ { GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE },
{ 0, 0, 0}
};
@@ -155,16 +159,15 @@ static const gnutls_cipher_entry algorithms[] = {
struct gnutls_hash_entry {
const char *name;
gnutls_mac_algorithm id;
- size_t digestsize;
};
typedef struct gnutls_hash_entry gnutls_hash_entry;
static const gnutls_hash_entry hash_algorithms[] = {
- {"SHA", GNUTLS_MAC_SHA, 20},
- {"MD5", GNUTLS_MAC_MD5, 16},
- {"RIPEMD160", GNUTLS_MAC_RMD160, 20},
- {"NULL", GNUTLS_MAC_NULL, 0},
- {0, 0, 0}
+ {"SHA", GNUTLS_MAC_SHA},
+ {"MD5", GNUTLS_MAC_MD5},
+ {"RIPEMD160", GNUTLS_MAC_RMD160},
+ {"NULL", GNUTLS_MAC_NULL},
+ {0, 0}
};
#define GNUTLS_HASH_LOOP(b) \
@@ -219,16 +222,16 @@ const int _gnutls_kx_algorithms_size = MAX_KX_ALGOS;
gnutls_kx_algo_entry _gnutls_kx_algorithms[MAX_KX_ALGOS] = {
#ifdef ENABLE_ANON
- { "Anon DH", GNUTLS_KX_ANON_DH, &anon_auth_struct },
+ { "Anon DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0 },
#endif
- { "RSA", GNUTLS_KX_RSA, &rsa_auth_struct },
- { "RSA EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct },
- { "DHE RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct },
- { "DHE DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct },
+ { "RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0 },
+ { "RSA EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0, 1 },
+ { "DHE RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 0 },
+ { "DHE DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0 },
/* other algorithms are appended here by gnutls-extra
* initialization function.
*/
- {0, 0, 0}
+ {0, 0, 0, 0, 0}
};
#define GNUTLS_KX_LOOP(b) \
@@ -477,15 +480,6 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
/* Generic Functions */
-/* HASHES */
-int _gnutls_mac_get_digest_size(gnutls_mac_algorithm algorithm)
-{
- size_t ret = 0;
- GNUTLS_HASH_ALG_LOOP(ret = p->digestsize);
- return ret;
-
-}
-
inline int _gnutls_mac_priority(gnutls_session session, gnutls_mac_algorithm algorithm)
{ /* actually returns the priority */
unsigned int i;
@@ -776,6 +770,21 @@ int _gnutls_kx_is_ok(gnutls_kx_algorithm algorithm)
return ret;
}
+int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP(ret = p->needs_rsa_params);
+ return ret;
+}
+
+int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP(ret = p->needs_dh_params);
+ return ret;
+}
+
+
/* Version */
int _gnutls_version_priority(gnutls_session session,
gnutls_protocol_version version)
@@ -1344,7 +1353,7 @@ gnutls_pk_algorithm _gnutls_map_pk_get_pk(gnutls_kx_algorithm kx_algorithm)
return ret;
}
-/* Returns the encipher type for the the given key exchange algorithm.
+/* Returns the encipher type for the given key exchange algorithm.
* That one of CIPHER_ENCRYPT, CIPHER_SIGN, CIPHER_IGN.
*
* ex. GNUTLS_KX_RSA requires a certificate able to encrypt... so returns CIPHER_ENCRYPT.
diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h
index cbfde6788f..7038e99ff2 100644
--- a/lib/gnutls_algorithms.h
+++ b/lib/gnutls_algorithms.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2000,2003 Nikos Mavroyanopoulos
*
* This file is part of GNUTLS.
*
@@ -31,7 +31,6 @@ int _gnutls_version_get_minor( gnutls_protocol_version ver);
gnutls_protocol_version _gnutls_version_get( int major, int minor);
/* functions for macs */
-int _gnutls_mac_get_digest_size(gnutls_mac_algorithm algorithm);
const char* gnutls_mac_get_name(gnutls_mac_algorithm algorithm);
int _gnutls_mac_is_ok(gnutls_mac_algorithm algorithm);
int _gnutls_mac_priority(gnutls_session session, gnutls_mac_algorithm algorithm);
@@ -60,6 +59,9 @@ const char *gnutls_cipher_get_name(gnutls_cipher_algorithm algorithm);
/* functions for key exchange */
int _gnutls_kx_priority(gnutls_session session, gnutls_kx_algorithm algorithm);
+int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm algorithm);
+int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm algorithm);
+
MOD_AUTH_STRUCT * _gnutls_kx_auth_struct(gnutls_kx_algorithm algorithm);
const char *gnutls_kx_get_name(gnutls_kx_algorithm algorithm);
@@ -91,6 +93,8 @@ struct gnutls_kx_algo_entry {
const char *name;
gnutls_kx_algorithm algorithm;
MOD_AUTH_STRUCT *auth_struct;
+ int needs_dh_params;
+ int needs_rsa_params;
};
typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
diff --git a/lib/gnutls_anon_cred.c b/lib/gnutls_anon_cred.c
index 578aef62af..42b61bdf74 100644
--- a/lib/gnutls_anon_cred.c
+++ b/lib/gnutls_anon_cred.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c
index 2c5bef6f9a..deaed91266 100644
--- a/lib/gnutls_auth.c
+++ b/lib/gnutls_auth.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 2b80b9ad5b..02d22370c0 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index b65789e524..a7a2297780 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -59,7 +60,7 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc)
for (i = 0; i < sc->ncerts; i++) {
for (j = 0; j < sc->cert_list_length[i]; j++) {
- _gnutls_free_cert( &sc->cert_list[i][j]);
+ _gnutls_gcert_deinit( &sc->cert_list[i][j]);
}
gnutls_free( sc->cert_list[i]);
}
@@ -71,7 +72,7 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc)
sc->cert_list = NULL;
for (i = 0; i < sc->ncerts; i++) {
- _gnutls_privkey_deinit( &sc->pkey[i]);
+ _gnutls_gkey_deinit( &sc->pkey[i]);
}
gnutls_free( sc->pkey);
@@ -86,7 +87,9 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc)
* @sc: is an &gnutls_certificate_credentials structure.
*
* This function will delete all the CAs associated
- * with the given credentials.
+ * with the given credentials. Servers that do not use
+ * gnutls_certificate_verify_peers() may call this to
+ * save some memory.
*
**/
void gnutls_certificate_free_cas(gnutls_certificate_credentials sc)
@@ -102,8 +105,23 @@ void gnutls_certificate_free_cas(gnutls_certificate_credentials sc)
gnutls_free( sc->x509_ca_list);
sc->x509_ca_list = NULL;
- _gnutls_free_datum( &sc->x509_rdn_sequence);
+}
+/**
+ * gnutls_certificate_free_ca_names - Used to free all the CA names from a gnutls_certificate_credentials structure
+ * @sc: is an &gnutls_certificate_credentials structure.
+ *
+ * This function will delete all the CA name in the
+ * given credentials. Clients may call this to save some memory
+ * since in client side the CA names are not used.
+ *
+ * CA names are used by servers to advertize the CAs they
+ * support to clients.
+ *
+ **/
+void gnutls_certificate_free_ca_names(gnutls_certificate_credentials sc)
+{
+ _gnutls_free_datum( &sc->x509_rdn_sequence);
}
/**
@@ -157,15 +175,25 @@ int gnutls_certificate_allocate_credentials(gnutls_certificate_credentials * res
* This function also uses the KeyUsage field of the certificate
* extensions in order to disable unneded algorithms.
*/
-int _gnutls_cert_supported_kx(const gnutls_cert* cert, gnutls_kx_algorithm ** alg,
+int _gnutls_selected_cert_supported_kx( gnutls_session session, gnutls_kx_algorithm ** alg,
int *alg_size)
{
gnutls_kx_algorithm kx;
- int i;
gnutls_pk_algorithm pk;
gnutls_kx_algorithm kxlist[MAX_ALGOS];
+ gnutls_cert * cert;
+ int i;
+
+ if (session->internals.selected_cert_list_length == 0) {
+ gnutls_assert();
+ *alg_size = 0;
+ *alg = NULL;
+ return 0;
+ }
+ cert = &session->internals.selected_cert_list[0];
i = 0;
+
for (kx = 0; kx < MAX_ALGOS; kx++) {
pk = _gnutls_map_pk_get_pk(kx);
if (pk == cert->subject_pk_algorithm) {
@@ -228,7 +256,7 @@ void gnutls_certificate_server_set_request(gnutls_session session,
* the raw certificates (DER for X.509 or binary for OpenPGP), of the
* client.
*
- * @req_ca_cert, is only used in X.509 certificates.
+ * @req_ca_dn, is only used in X.509 certificates.
* Contains a list with the CA names that the server considers trusted.
* Normally we should send a certificate that is signed
* by one of these CAs. These names are DER encoded. To get a more
@@ -236,7 +264,7 @@ void gnutls_certificate_server_set_request(gnutls_session session,
*
* This function specifies what we, in case of a client, are going
* to do when we have to send a certificate. If this callback
- * function is not provided then gnutls will automaticaly try to
+ * function is not provided then gnutls will automatically try to
* find an appropriate certificate to send. The appropriate certificate
* is chosen based on the CAs sent by the server, and the requested
* public key algorithms.
@@ -271,7 +299,7 @@ void gnutls_certificate_client_set_select_function(gnutls_session session,
*
* This function specifies what we, in case of a server, are going
* to do when we have to send a certificate. If this callback
- * function is not provided then gnutls will automaticaly try to
+ * function is not provided then gnutls will automatically try to
* find an appropriate certificate to send. (actually send the first in the list)
*
* In case the callback returned a negative number then gnutls will
@@ -290,11 +318,73 @@ void gnutls_certificate_server_set_select_function(gnutls_session session,
session->internals.server_cert_callback = func;
}
+/**
+ * gnutls_certificate_client_set_retrieve_function - Used to set a callback to retrieve the certificate
+ * @cred: is a &gnutls_certificate_credentials structure.
+ * @func: is the callback function
+ *
+ * This function sets a callback to be called in order to retrieve the certificate
+ * to be used in the handshake.
+ * The callback's function prototype is:
+ * int (*callback)(gnutls_session, const gnutls_datum* req_ca_dn, int nreqs,
+ * gnutls_pk_algorithm* pk_algos, int pk_algos_length, gnutls_retr_st st);
+ *
+ * @st should contain the certificates and private keys.
+ *
+ * @req_ca_cert, is only used in X.509 certificates.
+ * Contains a list with the CA names that the server considers trusted.
+ * Normally we should send a certificate that is signed
+ * by one of these CAs. These names are DER encoded. To get a more
+ * meaningful value use the function gnutls_x509_rdn_get().
+ *
+ * @pk_algos, contains a list with server's acceptable signature algorithms.
+ * The certificate returned should support the server's given algorithms.
+ *
+ * If the callback function is provided then gnutls will call it, in the
+ * handshake, after the certificate request message has been received.
+ *
+ * The callback function should set the certificate list to be sent, and
+ * return 0 on success. The value (-1) indicates error and the handshake
+ * will be terminated.
+ **/
+void gnutls_certificate_client_set_retrieve_function(gnutls_certificate_credentials cred,
+ gnutls_certificate_client_retrieve_function * func)
+{
+ cred->client_get_cert_callback = func;
+}
+
+/**
+ * gnutls_certificate_server_set_retrieve_function - Used to set a callback to retrieve the certificate
+ * @cred: is a &gnutls_certificate_credentials structure.
+ * @func: is the callback function
+ *
+ * This function sets a callback to be called in order to retrieve the certificate
+ * to be used in the handshake.
+ * The callback's function prototype is:
+ * int (*callback)(gnutls_session, const gnutls_datum* req_ca_dn, int nreqs,
+ * gnutls_pk_algorithm* pk_algos, int pk_algos_length, gnutls_retr_st st);
+ *
+ * @st should contain the certificates and private keys.
+ *
+ * If the callback function is provided then gnutls will call it, in the
+ * handshake, after the certificate request message has been received.
+ *
+ * The callback function should set the certificate list to be sent, and
+ * return 0 on success. The value (-1) indicates error and the handshake
+ * will be terminated.
+ **/
+void gnutls_certificate_server_set_retrieve_function(gnutls_certificate_credentials cred,
+ gnutls_certificate_server_retrieve_function * func)
+{
+ cred->server_get_cert_callback = func;
+}
+
+
/* These are set by the gnutls_extra library's initialization function.
*/
-OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_extract_key_creation_time = NULL;
-OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_extract_key_expiration_time = NULL;
+OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_get_raw_key_creation_time = NULL;
+OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_get_raw_key_expiration_time = NULL;
OPENPGP_VERIFY_KEY_FUNC _E_gnutls_openpgp_verify_key = NULL;
/*-
@@ -420,12 +510,12 @@ time_t gnutls_certificate_expiration_time_peers(gnutls_session session)
switch( gnutls_certificate_type_get( session)) {
case GNUTLS_CRT_X509:
- return gnutls_x509_extract_certificate_expiration_time(
+ return _gnutls_x509_get_raw_crt_expiration_time(
&info->raw_certificate_list[0]);
case GNUTLS_CRT_OPENPGP:
- if (_E_gnutls_openpgp_extract_key_expiration_time==NULL)
+ if (_E_gnutls_openpgp_get_raw_key_expiration_time==NULL)
return (time_t)-1;
- return _E_gnutls_openpgp_extract_key_expiration_time(
+ return _E_gnutls_openpgp_get_raw_key_expiration_time(
&info->raw_certificate_list[0]);
default:
return (time_t)-1;
@@ -460,18 +550,62 @@ time_t gnutls_certificate_activation_time_peers(gnutls_session session)
switch( gnutls_certificate_type_get( session)) {
case GNUTLS_CRT_X509:
- return gnutls_x509_extract_certificate_activation_time(
+ return _gnutls_x509_get_raw_crt_activation_time(
&info->raw_certificate_list[0]);
case GNUTLS_CRT_OPENPGP:
- if (_E_gnutls_openpgp_extract_key_creation_time==NULL)
+ if (_E_gnutls_openpgp_get_raw_key_creation_time==NULL)
return (time_t)-1;
- return _E_gnutls_openpgp_extract_key_creation_time(
+ return _E_gnutls_openpgp_get_raw_key_creation_time(
&info->raw_certificate_list[0]);
default:
return (time_t)-1;
}
}
+OPENPGP_RAW_KEY_TO_GCERT _E_gnutls_openpgp_raw_key_to_gcert;
+OPENPGP_RAW_PRIVKEY_TO_GKEY _E_gnutls_openpgp_raw_privkey_to_gkey;
+
+int _gnutls_raw_cert_to_gcert(gnutls_cert * gcert, gnutls_certificate_type type,
+ const gnutls_datum *raw_cert, int flags /* OR of ConvFlags */)
+{
+ switch( type) {
+ case GNUTLS_CRT_X509:
+ return _gnutls_x509_raw_cert_to_gcert( gcert,
+ raw_cert, flags);
+ case GNUTLS_CRT_OPENPGP:
+ if (_E_gnutls_openpgp_raw_key_to_gcert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INIT_LIBEXTRA;
+ }
+ return
+ _E_gnutls_openpgp_raw_key_to_gcert( gcert,
+ raw_cert);
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
+int _gnutls_raw_privkey_to_gkey(gnutls_privkey * key, gnutls_certificate_type type,
+ const gnutls_datum *raw_key, int key_enc /* DER or PEM */)
+{
+ switch( type) {
+ case GNUTLS_CRT_X509:
+ return _gnutls_x509_raw_privkey_to_gkey( key,
+ raw_key, key_enc);
+ case GNUTLS_CRT_OPENPGP:
+ if (_E_gnutls_openpgp_raw_privkey_to_gkey==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INIT_LIBEXTRA;
+ }
+ return
+ _E_gnutls_openpgp_raw_privkey_to_gkey( key, raw_key);
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
/* This function will convert a der certificate to a format
* (structure) that gnutls can understand and use. Actually the
@@ -482,7 +616,7 @@ time_t gnutls_certificate_activation_time_peers(gnutls_session session)
* extensions found in the certificate are unsupported and critical.
* The critical extensions will be catched by the verification functions.
*/
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCert,
+int _gnutls_x509_raw_cert_to_gcert(gnutls_cert * gcert, const gnutls_datum *derCert,
int flags /* OR of ConvFlags */)
{
int ret;
@@ -501,7 +635,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCe
return ret;
}
- ret = _gnutls_x509_crt2gnutls_cert( gcert, cert, flags);
+ ret = _gnutls_x509_crt_to_gcert( gcert, cert, flags);
gnutls_x509_crt_deinit( cert);
return ret;
@@ -509,7 +643,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCe
/* Like above but it accepts a parsed certificate instead.
*/
-int _gnutls_x509_crt2gnutls_cert(gnutls_cert * gcert, gnutls_x509_crt cert,
+int _gnutls_x509_crt_to_gcert(gnutls_cert * gcert, gnutls_x509_crt cert,
unsigned int flags)
{
int ret = 0;
@@ -566,10 +700,12 @@ int _gnutls_x509_crt2gnutls_cert(gnutls_cert * gcert, gnutls_x509_crt cert,
}
-void _gnutls_free_cert(gnutls_cert *cert)
+void _gnutls_gcert_deinit(gnutls_cert *cert)
{
int i;
+ if (cert == NULL) return;
+
for (i = 0; i < cert->params_size; i++) {
_gnutls_mpi_release( &cert->params[i]);
}
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index d322fc0ae4..96218ff479 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -81,15 +81,22 @@ typedef enum ConvFlags {
CERT_ONLY_EXTENSIONS=16
} ConvFlags;
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCert,
+int _gnutls_x509_raw_cert_to_gcert(gnutls_cert * gcert, const gnutls_datum *derCert,
int flags);
-int _gnutls_x509_crt2gnutls_cert(gnutls_cert * gcert, gnutls_x509_crt cert,
+int _gnutls_x509_crt_to_gcert(gnutls_cert * gcert, gnutls_x509_crt cert,
unsigned int flags);
-void _gnutls_free_cert(gnutls_cert* cert);
+
int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn);
-void _gnutls_privkey_deinit(gnutls_privkey *key);
+void _gnutls_gkey_deinit(gnutls_privkey *key);
+void _gnutls_gcert_deinit(gnutls_cert *cert);
-int _gnutls_cert_supported_kx( const gnutls_cert* cert, gnutls_kx_algorithm **alg, int *alg_size);
+int _gnutls_selected_cert_supported_kx(struct gnutls_session_int* session,
+ gnutls_kx_algorithm ** alg, int *alg_size);
+int _gnutls_raw_cert_to_gcert(gnutls_cert * gcert, gnutls_certificate_type type,
+ const gnutls_datum *raw_cert, int flags /* OR of ConvFlags */);
+int _gnutls_raw_privkey_to_gkey(gnutls_privkey * key, gnutls_certificate_type type,
+ const gnutls_datum *raw_key, int key_enc /* DER or PEM */);
+
#endif
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index cf32bcd435..3394dd7b4f 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -144,7 +145,10 @@ int _gnutls_decrypt(gnutls_session session, opaque *ciphertext,
if (gtxt.size > data_size) {
gnutls_assert();
_gnutls_free_datum( &gtxt);
- return GNUTLS_E_MEMORY_ERROR;
+ /* This shouldn't have happen and
+ * is a TLS fatal error.
+ */
+ return GNUTLS_E_INTERNAL_ERROR;
}
memcpy( data, gtxt.data, gtxt.size);
@@ -157,7 +161,8 @@ int _gnutls_decrypt(gnutls_session session, opaque *ciphertext,
}
inline
-static GNUTLS_MAC_HANDLE mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver)
+static GNUTLS_MAC_HANDLE
+mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver)
{
GNUTLS_MAC_HANDLE td;
@@ -165,7 +170,7 @@ GNUTLS_MAC_HANDLE td;
td =
_gnutls_mac_init_ssl3( mac, secret,
secret_size);
- } else { /* TLS 1 */
+ } else { /* TLS 1.x */
td =
_gnutls_hmac_init( mac, secret, secret_size);
}
@@ -223,7 +228,6 @@ int length;
*pad = (uint8) (blocksize - (length % blocksize)) + rand;
length += *pad;
-
break;
default:
gnutls_assert();
@@ -250,12 +254,13 @@ int _gnutls_compressed2ciphertext(gnutls_session session,
GNUTLS_MAC_HANDLE td;
uint8 type = _type;
uint8 major, minor;
- int hash_size = _gnutls_mac_get_digest_size(session->security_parameters.write_mac_algorithm);
+ int hash_size = _gnutls_hash_get_algo_len(session->security_parameters.write_mac_algorithm);
gnutls_protocol_version ver;
int blocksize =
_gnutls_cipher_get_block_size(session->security_parameters.
write_bulk_cipher_algorithm);
CipherType block_algo = _gnutls_cipher_is_block(session->security_parameters.write_bulk_cipher_algorithm);
+ opaque* data_ptr;
ver = gnutls_protocol_get_version( session);
@@ -280,7 +285,7 @@ int _gnutls_compressed2ciphertext(gnutls_session session,
_gnutls_hmac(td, UINT64DATA(session->connection_state.write_sequence_number), 8);
_gnutls_hmac(td, &type, 1);
- if ( ver != GNUTLS_SSL3) { /* TLS 1.0 only */
+ if ( ver >= GNUTLS_TLS1) { /* TLS 1.0 or higher */
_gnutls_hmac(td, &major, 1);
_gnutls_hmac(td, &minor, 1);
}
@@ -306,18 +311,27 @@ int _gnutls_compressed2ciphertext(gnutls_session session,
return GNUTLS_E_MEMORY_ERROR;
}
- memcpy(cipher_data, compressed.data, compressed.size);
- if (hash_size > 0)
- memcpy(&cipher_data[compressed.size], MAC, hash_size);
- if (block_algo==CIPHER_BLOCK && pad > 0)
- memset(&cipher_data[ length - pad], pad - 1, pad);
+ data_ptr = cipher_data;
+
+ memcpy(data_ptr, compressed.data, compressed.size);
+ data_ptr += compressed.size;
+
+ if (hash_size > 0) {
+ memcpy(data_ptr, MAC, hash_size);
+ data_ptr += hash_size;
+ }
+ if (block_algo==CIPHER_BLOCK && pad > 0) {
+ memset(data_ptr, pad - 1, pad);
+ }
/* Actual encryption (inplace).
*/
- if ( (ret = _gnutls_cipher_encrypt(session->connection_state.
+ ret = _gnutls_cipher_encrypt(session->connection_state.
write_cipher_state, cipher_data,
- length)) < 0) {
+ length);
+ if (ret < 0) {
+ gnutls_assert();
return ret;
}
@@ -340,7 +354,7 @@ int _gnutls_ciphertext2compressed(gnutls_session session,
int ret, i, pad_failed = 0;
uint8 major, minor;
gnutls_protocol_version ver;
- int hash_size = _gnutls_mac_get_digest_size(session->security_parameters.read_mac_algorithm);
+ int hash_size = _gnutls_hash_get_algo_len(session->security_parameters.read_mac_algorithm);
ver = gnutls_protocol_get_version( session);
minor = _gnutls_version_get_minor(ver);
@@ -395,9 +409,8 @@ int _gnutls_ciphertext2compressed(gnutls_session session,
length =
ciphertext.size - hash_size - pad;
-
- if (pad >
- ciphertext.size - hash_size) {
+
+ if (pad > ciphertext.size - hash_size) {
gnutls_assert();
/* We do not fail here. We check below for the
* the pad_failed. If zero means success.
@@ -405,14 +418,12 @@ int _gnutls_ciphertext2compressed(gnutls_session session,
pad_failed = GNUTLS_E_DECRYPTION_FAILED;
}
- /* Check the pading bytes (TLS 1.0 only)
+ /* Check the pading bytes (TLS 1.x)
*/
- if ( ver == GNUTLS_TLS1)
+ if ( ver >= GNUTLS_TLS1)
for (i=2;i<pad;i++) {
if (ciphertext.data[ciphertext.size-i] != ciphertext.data[ciphertext.size - 1])
- {
pad_failed = GNUTLS_E_DECRYPTION_FAILED;
- }
}
break;
@@ -431,7 +442,7 @@ int _gnutls_ciphertext2compressed(gnutls_session session,
_gnutls_hmac(td, UINT64DATA(session->connection_state.read_sequence_number), 8);
_gnutls_hmac(td, &type, 1);
- if ( ver != GNUTLS_SSL3) { /* TLS 1.0 only */
+ if ( ver >= GNUTLS_TLS1) { /* TLS 1.x */
_gnutls_hmac(td, &major, 1);
_gnutls_hmac(td, &minor, 1);
}
diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c
index 05267fff1b..c0b97f2408 100644
--- a/lib/gnutls_cipher_int.c
+++ b/lib/gnutls_cipher_int.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_compress.c b/lib/gnutls_compress.c
index 0cf65e041e..06d5ccdef9 100644
--- a/lib/gnutls_compress.c
+++ b/lib/gnutls_compress.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_compress_int.c b/lib/gnutls_compress_int.c
index b246a72a0a..3bd2b0d5d3 100644
--- a/lib/gnutls_compress_int.c
+++ b/lib/gnutls_compress_int.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index 53962844d8..bc7b9ae6da 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -361,7 +362,7 @@ int _gnutls_set_read_keys(gnutls_session session)
mac_algo = session->security_parameters.read_mac_algorithm;
algo = session->security_parameters.read_bulk_cipher_algorithm;
- hash_size = _gnutls_mac_get_digest_size(mac_algo);
+ hash_size = _gnutls_hash_get_algo_len(mac_algo);
IV_size = _gnutls_cipher_get_iv_size(algo);
key_size = gnutls_cipher_get_key_size(algo);
export_flag = _gnutls_cipher_get_export_flag(algo);
@@ -381,7 +382,7 @@ int _gnutls_set_write_keys(gnutls_session session)
mac_algo = session->security_parameters.write_mac_algorithm;
algo = session->security_parameters.write_bulk_cipher_algorithm;
- hash_size = _gnutls_mac_get_digest_size(mac_algo);
+ hash_size = _gnutls_hash_get_algo_len(mac_algo);
IV_size = _gnutls_cipher_get_iv_size(algo);
key_size = gnutls_cipher_get_key_size(algo);
export_flag = _gnutls_cipher_get_export_flag(algo);
@@ -534,7 +535,7 @@ int _gnutls_read_connection_state_init(gnutls_session session)
mac_size =
- _gnutls_mac_get_digest_size(session->security_parameters.
+ _gnutls_hash_get_algo_len(session->security_parameters.
read_mac_algorithm);
_gnutls_handshake_log
@@ -717,7 +718,7 @@ int _gnutls_write_connection_state_init(gnutls_session session)
write_compression_state, 0);
mac_size =
- _gnutls_mac_get_digest_size(session->security_parameters.
+ _gnutls_hash_get_algo_len(session->security_parameters.
write_mac_algorithm);
_gnutls_handshake_log
diff --git a/lib/gnutls_datum.c b/lib/gnutls_datum.c
index b871ad09f1..007404a8ae 100644
--- a/lib/gnutls_datum.c
+++ b/lib/gnutls_datum.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_db.c b/lib/gnutls_db.c
index 4cb0b20394..f54f1307d1 100644
--- a/lib/gnutls_db.c
+++ b/lib/gnutls_db.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_dh.c b/lib/gnutls_dh.c
index 65617a3e98..5d749066b2 100644
--- a/lib/gnutls_dh.c
+++ b/lib/gnutls_dh.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
* someday was part of gsti
diff --git a/lib/gnutls_dh.h b/lib/gnutls_dh.h
index 9385079470..f556dbee56 100644
--- a/lib/gnutls_dh.h
+++ b/lib/gnutls_dh.h
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-int _gnutls_get_dh_params(gnutls_dh_params, GNUTLS_MPI *ret_p, GNUTLS_MPI* ret_g);
+const GNUTLS_MPI* _gnutls_get_dh_params(gnutls_dh_params);
GNUTLS_MPI gnutls_calc_dh_secret( GNUTLS_MPI *ret_x, GNUTLS_MPI g, GNUTLS_MPI prime );
GNUTLS_MPI gnutls_calc_dh_key( GNUTLS_MPI f, GNUTLS_MPI x, GNUTLS_MPI prime );
int _gnutls_dh_generate_prime(GNUTLS_MPI *ret_g, GNUTLS_MPI* ret_n, uint bits);
diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c
index 4fdf442b8d..785b0b1fdc 100644
--- a/lib/gnutls_dh_primes.c
+++ b/lib/gnutls_dh_primes.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -31,34 +32,15 @@
/* returns the prime and the generator of DH params.
*/
-int _gnutls_get_dh_params(gnutls_dh_params dh_primes,
- GNUTLS_MPI * ret_p, GNUTLS_MPI * ret_g)
+const GNUTLS_MPI* _gnutls_get_dh_params(gnutls_dh_params dh_primes)
{
- if (dh_primes == NULL || dh_primes->_prime == NULL ||
- dh_primes->_generator == NULL)
+ if (dh_primes == NULL || dh_primes->params[1] == NULL ||
+ dh_primes->params[0] == NULL)
{
- gnutls_assert();
- return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
- }
-
- if (ret_p != NULL) { /* caller wants the prime */
- *ret_p = _gnutls_mpi_copy(dh_primes->_prime);
- if (*ret_p == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- }
-
- if (ret_g != NULL) { /* caller wants the generator */
- *ret_g = _gnutls_mpi_copy(dh_primes->_generator);
- if (*ret_g == NULL) {
- gnutls_assert();
- if (ret_p) _gnutls_mpi_release(ret_p);
- return GNUTLS_E_MEMORY_ERROR;
- }
+ return NULL;
}
- return 0;
+ return dh_primes->params;
}
int _gnutls_dh_generate_prime(GNUTLS_MPI * ret_g, GNUTLS_MPI * ret_n,
@@ -69,28 +51,6 @@ int _gnutls_dh_generate_prime(GNUTLS_MPI * ret_g, GNUTLS_MPI * ret_n,
int result, times = 0, qbits;
GNUTLS_MPI *factors = NULL;
- /* useless since gcry_prime_group_generator allocates its own MPI
- * fixed by BBP */
-#if 0
- g = mpi_new(16); /* this should be ok */
- if (g == NULL) {
- gnutls_assert();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-#endif
-
- /* useless + memleak since gcry_prime_generate allocates irs own prime
- * fixed by BBP */
-#if 0
- prime = mpi_new(32);
- if (prime == NULL) {
- gnutls_assert();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-#endif
-
/* Calculate the size of a prime factor of (prime-1)/2.
* This is a bad emulation of Michael Wiener's table
*/
@@ -105,11 +65,11 @@ int _gnutls_dh_generate_prime(GNUTLS_MPI * ret_g, GNUTLS_MPI * ret_n,
/* find a prime number of size bits.
*/
do {
- /* fixed by BBP */
- if (times) {
- _gnutls_mpi_release(&prime);
- gcry_prime_release_factors (factors);
- }
+
+ if (times) {
+ _gnutls_mpi_release(&prime);
+ gcry_prime_release_factors (factors);
+ }
err = gcry_prime_generate( &prime, bits, qbits,
&factors, NULL, NULL, GCRY_STRONG_RANDOM,
@@ -198,8 +158,8 @@ int gnutls_dh_params_import_raw(gnutls_dh_params dh_params, const gnutls_datum *
/* store the generated values
*/
- dh_params->_prime = tmp_prime;
- dh_params->_generator = tmp_g;
+ dh_params->params[0] = tmp_prime;
+ dh_params->params[1] = tmp_g;
return 0;
@@ -237,8 +197,8 @@ void gnutls_dh_params_deinit(gnutls_dh_params dh_params)
if (dh_params == NULL)
return;
- _gnutls_mpi_release(&dh_params->_prime);
- _gnutls_mpi_release(&dh_params->_generator);
+ _gnutls_mpi_release(&dh_params->params[0]);
+ _gnutls_mpi_release(&dh_params->params[1]);
gnutls_free(dh_params);
@@ -264,8 +224,8 @@ int gnutls_dh_params_generate2(gnutls_dh_params params, unsigned int bits)
{
int ret;
- ret = _gnutls_dh_generate_prime(&params->_generator,
- &params->_prime, bits);
+ ret = _gnutls_dh_generate_prime(&params->params[1],
+ &params->params[0], bits);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -348,7 +308,7 @@ int gnutls_dh_params_import_pkcs3(gnutls_dh_params params,
/* Read PRIME
*/
- result = _gnutls_x509_read_int( c2, "prime", &params->_prime);
+ result = _gnutls_x509_read_int( c2, "prime", &params->params[0]);
if ( result < 0) {
asn1_delete_structure(&c2);
gnutls_assert();
@@ -357,10 +317,10 @@ int gnutls_dh_params_import_pkcs3(gnutls_dh_params params,
/* read the generator
*/
- result = _gnutls_x509_read_int( c2, "base", &params->_generator);
+ result = _gnutls_x509_read_int( c2, "base", &params->params[1]);
if ( result < 0) {
asn1_delete_structure(&c2);
- _gnutls_mpi_release( &params->_prime);
+ _gnutls_mpi_release( &params->params[0]);
gnutls_assert();
return result;
}
@@ -399,8 +359,8 @@ int gnutls_dh_params_export_pkcs3( gnutls_dh_params params,
opaque * p_data, *g_data;
opaque * all_data;
- _gnutls_mpi_print( NULL, &g_size, params->_generator);
- _gnutls_mpi_print( NULL, &p_size, params->_prime);
+ _gnutls_mpi_print( NULL, &g_size, params->params[1]);
+ _gnutls_mpi_print( NULL, &p_size, params->params[0]);
all_data = gnutls_malloc( g_size + p_size);
if (all_data == NULL) {
@@ -411,8 +371,8 @@ int gnutls_dh_params_export_pkcs3( gnutls_dh_params params,
p_data = &all_data[0];
g_data = &all_data[p_size];
- _gnutls_mpi_print( p_data, &p_size, params->_prime);
- _gnutls_mpi_print( g_data, &g_size, params->_generator);
+ _gnutls_mpi_print( p_data, &p_size, params->params[0]);
+ _gnutls_mpi_print( g_data, &g_size, params->params[1]);
/* Ok. Now we have the data. Create the asn1 structures
*/
@@ -550,15 +510,15 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
size_t size;
- if (params->_generator == NULL ||
- params->_prime == NULL)
+ if (params->params[1] == NULL ||
+ params->params[0] == NULL)
{
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
size = 0;
- _gnutls_mpi_print(NULL, &size, params->_generator);
+ _gnutls_mpi_print(NULL, &size, params->params[1]);
generator->data = gnutls_malloc(size);
if (generator->data == NULL) {
@@ -566,11 +526,11 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
}
generator->size = size;
- _gnutls_mpi_print(generator->data, &size, params->_generator);
+ _gnutls_mpi_print(generator->data, &size, params->params[1]);
size = 0;
- _gnutls_mpi_print(NULL, &size, params->_prime);
+ _gnutls_mpi_print(NULL, &size, params->params[0]);
prime->data = gnutls_malloc(size);
if (prime->data == NULL) {
@@ -578,10 +538,10 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
return GNUTLS_E_MEMORY_ERROR;
}
prime->size = size;
- _gnutls_mpi_print(prime->data, &size, params->_prime);
+ _gnutls_mpi_print(prime->data, &size, params->params[0]);
if (bits)
- *bits = _gnutls_mpi_get_nbits( params->_prime);
+ *bits = _gnutls_mpi_get_nbits( params->params[0]);
return 0;
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 23670e13bf..390e713104 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -205,8 +206,8 @@ void gnutls_perror(int error)
* @error: is an error returned by a gnutls function. Error is always a negative value.
*
* This function is similar to strerror(). Differences: it accepts an error
- * number returned by a gnutls function; it might return NULL in the case of
- * an unknown error number.
+ * number returned by a gnutls function; In case of an unknown error
+ * a descriptive string is sent instead of NULL.
**/
const char* gnutls_strerror(int error)
{
@@ -215,7 +216,7 @@ const char* gnutls_strerror(int error)
/* avoid prefix */
GNUTLS_ERROR_ALG_LOOP(ret =
p->desc);
-
+ if (ret == NULL) return "(unknown error code)";
return ret;
}
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 179f09cdf7..d13e89cd86 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index df5327877a..0c6bf8525a 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -327,7 +328,7 @@ parse_version_string( const char *s, int *major, int *minor, int *micro )
* gnutls_check_version - This function checks the library's version
* @req_version: the version to check
*
- * Check that the the version of the library is at minimum the requested one
+ * Check that the version of the library is at minimum the requested one
* and return the version string; return NULL if the condition is not
* satisfied. If a NULL is passed to this function, no check is done,
* but the version string is simply returned.
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 27b201f803..9d9de3d230 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -46,6 +47,8 @@
#include <gnutls_alert.h>
#include <gnutls_state.h>
#include <ext_srp.h>
+#include <gnutls_rsa_export.h> /* for gnutls_get_rsa_params() */
+#include <auth_anon.h> /* for gnutls_anon_server_credentials */
#ifdef HANDSHAKE_DEBUG
#define ERR(x, y) _gnutls_handshake_log( "HSK[%x]: %s (%d)\n", session, x,y)
@@ -265,6 +268,12 @@ int _gnutls_read_client_hello(gnutls_session session, opaque * data,
* then we send him the highest we support.
*/
ver = _gnutls_version_max(session);
+ if (ver==GNUTLS_VERSION_UNKNOWN) {
+ /* this check is not really needed.
+ */
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
+ }
} else {
ver = version;
}
@@ -568,7 +577,7 @@ int _gnutls_server_select_suite(gnutls_session session, opaque *data, int datale
memset(session->security_parameters.current_cipher_suite.CipherSuite, '\0', 2);
retval = GNUTLS_E_UNKNOWN_CIPHER_SUITE;
-
+
for (j = 0; j < datalen; j += 2) {
for (i = 0; i < x; i++) {
if (memcmp(ciphers[i].CipherSuite, &data[j], 2) ==
@@ -1775,7 +1784,7 @@ int _gnutls_recv_hello(gnutls_session session, opaque *data, int datalen)
/**
* gnutls_rehandshake - This function will renegotiate security parameters
- * @session: is a a &gnutls_session structure.
+ * @session: is a &gnutls_session structure.
*
* This function will renegotiate security parameters with the
* client. This should only be called in case of a server.
@@ -2332,6 +2341,72 @@ int _gnutls_recv_hello_request(gnutls_session session, void *data,
}
}
+/* Returns 1 if the given KX has not the corresponding parameters
+ * (DH or RSA) set up. Otherwise returns 0.
+ */
+inline static int check_server_params( gnutls_session session, gnutls_kx_algorithm kx,
+ gnutls_kx_algorithm* alg, int alg_size)
+{
+ int cred_type;
+ const gnutls_certificate_credentials x509_cred;
+ const gnutls_anon_server_credentials anon_cred;
+ gnutls_dh_params dh_params = NULL;
+ gnutls_rsa_params rsa_params = NULL;
+ int j, keep;
+
+ cred_type = _gnutls_map_kx_get_cred( kx, 1);
+
+ if (cred_type == GNUTLS_CRD_CERTIFICATE) {
+ x509_cred =
+ _gnutls_get_cred(session->key, cred_type, NULL);
+
+ if (x509_cred != NULL) {
+ dh_params = x509_cred->dh_params;
+ rsa_params = x509_cred->rsa_params;
+ }
+
+ /* Check also if the certificate supports the
+ * KX method.
+ */
+ keep = 1;
+ for (j = 0; j < alg_size; j++) {
+ if (alg[j] == kx) {
+ keep = 0;
+ break;
+ }
+ }
+
+ if (keep == 1) return 1;
+
+
+ } else if ( cred_type == GNUTLS_CRD_ANON) {
+ anon_cred =
+ _gnutls_get_cred(session->key, cred_type, NULL);
+
+ if (anon_cred != NULL) {
+ dh_params = anon_cred->dh_params;
+ }
+ } else return 0; /* no need for params */
+
+
+ /* If the key exchange method needs RSA or DH params,
+ * but they are not set then remove it.
+ */
+ if (_gnutls_kx_needs_rsa_params( kx) != 0) {
+ /* needs rsa params. */
+ if (_gnutls_get_rsa_params( rsa_params)==NULL)
+ return 1;
+ }
+
+ if (_gnutls_kx_needs_dh_params( kx) != 0) {
+ /* needs DH params. */
+ if (_gnutls_get_dh_params( dh_params)==NULL)
+ return 1;
+ }
+
+ return 0;
+}
+
/* This function will remove algorithms that are not supported by
* the requested authentication method. We remove an algorithm if
* we have a certificate with keyUsage bits set.
@@ -2347,13 +2422,12 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
int ret = 0;
GNUTLS_CipherSuite *newSuite, cs;
- int newSuiteSize = 0, i, j, keep;
+ int newSuiteSize = 0, i, keep;
const gnutls_certificate_credentials x509_cred;
- const gnutls_cert* cert = NULL;
- gnutls_kx_algorithm *alg;
- int alg_size;
gnutls_kx_algorithm kx;
int server = session->security_parameters.entity==GNUTLS_SERVER?1:0;
+ gnutls_kx_algorithm *alg;
+ int alg_size;
/* if we should use a specific certificate,
* we should remove all algorithms that are not supported
@@ -2367,28 +2441,24 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
/* if x509_cred==NULL we should remove all X509 ciphersuites
*/
- cert = NULL;
- if (session->security_parameters.entity == GNUTLS_SERVER) {
- cert = _gnutls_server_find_cert(session, requested_pk_algo);
- }
-
- if (cert == NULL) {
- /* No certificate was found
- */
- alg_size = 0;
- alg = NULL;
- } else {
- /* get all the key exchange algorithms that are
- * supported by the X509 certificate parameters.
- */
- if ((ret =
- _gnutls_cert_supported_kx(cert, &alg,
- &alg_size)) < 0) {
+ if (session->security_parameters.entity == GNUTLS_SERVER && x509_cred != NULL) {
+ ret = _gnutls_server_select_cert(session, requested_pk_algo);
+ if (ret < 0) {
gnutls_assert();
return ret;
}
}
+ /* get all the key exchange algorithms that are
+ * supported by the X509 certificate parameters.
+ */
+ if ((ret =
+ _gnutls_selected_cert_supported_kx(session, &alg,
+ &alg_size)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
newSuite =
gnutls_malloc(numCipherSuites * sizeof(GNUTLS_CipherSuite));
if (newSuite == NULL) {
@@ -2410,28 +2480,14 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
*/
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, server) == GNUTLS_CRD_CERTIFICATE) {
- keep = 1; /* do not keep */
-
- if (x509_cred != NULL) {
- if (server) {
- /* here we check if the KX algorithm
- * is compatible with the certificate.
- */
- for (j = 0; j < alg_size; j++) {
- if (alg[j] == kx) {
- keep = 0;
- break;
- }
- }
- } else /* CLIENT */
- keep = 0;
- }
+ } else {
+ keep = 0;
+
+ if (server)
+ keep = check_server_params( session, kx, alg, alg_size);
}
+
+
memcpy( &cs.CipherSuite, &(*cipherSuites)[i].CipherSuite, 2);
@@ -2462,7 +2518,7 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
/**
* gnutls_handshake_set_max_packet_length - This function will set the maximum length of a handshake message
- * @session: is a a &gnutls_session structure.
+ * @session: is a &gnutls_session structure.
* @max: is the maximum number.
*
* This function will set the maximum size of a handshake message.
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 00868356f8..91c0e8585b 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -226,6 +226,7 @@ typedef void (*LOG_FUNC)( int, const char*);
typedef ssize_t (*gnutls_pull_func)(gnutls_transport_ptr, void*, size_t);
typedef ssize_t (*gnutls_push_func)(gnutls_transport_ptr, const void*, size_t);
+
/* Store & Retrieve functions defines:
*/
typedef int (*gnutls_db_store_func)(void*, gnutls_datum key, gnutls_datum data);
@@ -302,7 +303,9 @@ typedef struct {
/* Versions should be in order of the oldest
* (eg. SSL3 is before TLS1)
*/
-typedef enum gnutls_protocol_version { GNUTLS_SSL3=1, GNUTLS_TLS1, GNUTLS_VERSION_UNKNOWN=0xff }
+#define GNUTLS_TLS1 GNUTLS_TLS1_0
+typedef enum gnutls_protocol_version { GNUTLS_SSL3=1, GNUTLS_TLS1_0,
+ GNUTLS_TLS1_1, GNUTLS_VERSION_UNKNOWN=0xff }
gnutls_protocol_version;
/* This structure holds parameters got from TLS extension
@@ -578,11 +581,15 @@ typedef struct {
*/
uint16 proposed_record_size;
- /* holds the index of the selected certificate.
- * -1 if none.
+ /* holds the selected certificate and key.
+ * use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set()
+ * to change them.
*/
- int selected_cert_index;
-
+ gnutls_cert* selected_cert_list;
+ int selected_cert_list_length;
+ gnutls_privkey* selected_key;
+ int selected_need_free;
+
/* holds the extensions we sent to the peer
* (in case of a client)
*/
@@ -651,8 +658,9 @@ struct gnutls_session_int {
typedef struct gnutls_session_int *gnutls_session;
typedef struct {
- GNUTLS_MPI _prime;
- GNUTLS_MPI _generator;
+ /* [0] is the prime, [1] is the generator.
+ */
+ GNUTLS_MPI params[2];
} _gnutls_dh_params;
#define gnutls_dh_params _gnutls_dh_params*
diff --git a/lib/gnutls_int_compat.c b/lib/gnutls_int_compat.c
index ffb367a6b3..b5a48259cf 100644
--- a/lib/gnutls_int_compat.c
+++ b/lib/gnutls_int_compat.c
@@ -1,5 +1,3 @@
-#include <gnutls/gnutls.h>
-
/* This file contains functions needed only for binary compatibility
* with previous versions.
*/
@@ -7,6 +5,1290 @@
#ifdef GNUTLS_BACKWARDS_COMPATIBLE
-/* removed everything for 0.9.0 release */
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <x509_b64.h> /* for PKCS3 PEM decoding */
+#include <gnutls_global.h>
+#include <gnutls_dh.h>
+#include <gnutls_rsa_export.h>
+#include <gnutls_errors.h>
+#include <string.h> /* memset */
+#include <libtasn1.h>
+#include <gnutls/compat8.h>
+
+/* dh_compat.c */
+
+/* Replaces the prime in the static DH parameters, with a randomly
+ * generated one.
+ */
+/*-
+ * gnutls_dh_params_set - This function will replace the old DH parameters
+ * @dh_params: Is a structure will hold the prime numbers
+ * @prime: holds the new prime
+ * @generator: holds the new generator
+ * @bits: is the prime's number of bits. This value is ignored.
+ *
+ * This function will replace the pair of prime and generator for use in
+ * the Diffie-Hellman key exchange. The new parameters should be stored in the
+ * appropriate gnutls_datum.
+ *
+ -*/
+int gnutls_dh_params_set(gnutls_dh_params dh_params, gnutls_datum prime,
+ gnutls_datum generator, int bits)
+{
+ GNUTLS_MPI tmp_prime, tmp_g;
+ size_t siz = 0;
+
+ /* sprime is not null, because of the check_bits()
+ * above.
+ */
+
+ siz = prime.size;
+ if (_gnutls_mpi_scan(&tmp_prime, prime.data, &siz)) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = generator.size;
+ if (_gnutls_mpi_scan(&tmp_g, generator.data, &siz)) {
+ _gnutls_mpi_release(&tmp_prime);
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ /* copy the generated values to the structure
+ */
+ dh_params->params[0] = tmp_prime;
+ dh_params->params[1] = tmp_g;
+
+ return 0;
+
+}
+
+/*-
+ * gnutls_dh_params_generate - This function will generate new DH parameters
+ * @prime: will hold the new prime
+ * @generator: will hold the new generator
+ * @bits: is the prime's number of bits
+ *
+ * This function will generate a new pair of prime and generator for use in
+ * the Diffie-Hellman key exchange. The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ * This function is normally very slow. Another function
+ * (gnutls_dh_params_set()) should be called in order to replace the
+ * included DH primes in the gnutls library.
+ *
+ * Note that the bits value should be one of 768, 1024, 2048, 3072 or 4096.
+ * Also note that the generation of new DH parameters is only useful
+ * to servers. Clients use the parameters sent by the server, thus it's
+ * no use calling this in client side.
+ *
+ -*/
+int gnutls_dh_params_generate(gnutls_datum * prime,
+ gnutls_datum * generator, int bits)
+{
+
+ GNUTLS_MPI tmp_prime, tmp_g;
+ size_t siz;
+
+ if (_gnutls_dh_generate_prime(&tmp_g, &tmp_prime, bits) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, tmp_g);
+
+ generator->data = gnutls_malloc(siz);
+ if (generator->data == NULL) {
+ _gnutls_mpi_release(&tmp_g);
+ _gnutls_mpi_release(&tmp_prime);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ generator->size = siz;
+ _gnutls_mpi_print(generator->data, &siz, tmp_g);
+
+
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, tmp_prime);
+
+ prime->data = gnutls_malloc(siz);
+ if (prime->data == NULL) {
+ gnutls_free(generator->data);
+ generator->data = NULL; generator->size = 0;
+ _gnutls_mpi_release(&tmp_g);
+ _gnutls_mpi_release(&tmp_prime);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ prime->size = siz;
+ _gnutls_mpi_print(prime->data, &siz, tmp_prime);
+
+#ifdef DEBUG
+ {
+ opaque buffer[512];
+
+ _gnutls_debug_log
+ ("dh_params_generate: Generated %d bits prime %s, generator %s.\n",
+ bits, _gnutls_bin2hex(prime->data, prime->size, buffer, sizeof(buffer)),
+ _gnutls_bin2hex(generator->data, generator->size, buffer, sizeof(buffer)));
+ }
+#endif
+
+ return 0;
+}
+
+/* rsa_compat.c */
+
+/* This function takes a number of bits and returns a supported
+ * number of bits. Ie a number of bits that we have a prime in the
+ * dh_primes structure.
+ */
+
+#define MAX_SUPPORTED_BITS 512
+
+/* returns a negative value if the bits size is not supported
+ */
+static int check_bits(int bits)
+{
+ if (bits > MAX_SUPPORTED_BITS)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ return 0;
+}
+
+
+#define FREE_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
+ _gnutls_mpi_release(&rsa_params->params[i]);
+
+/*-
+ * gnutls_rsa_params_set - This function will replace the old RSA parameters
+ * @rsa_params: Is a structure which will hold the parameters
+ * @m: holds the modulus
+ * @e: holds the public exponent
+ * @d: holds the private exponent
+ * @p: holds the first prime (p)
+ * @q: holds the second prime (q)
+ * @u: holds the coefficient
+ * @bits: is the modulus's number of bits
+ *
+ * This function will replace the parameters used in the RSA-EXPORT key
+ * exchange. The new parameters should be stored in the
+ * appropriate gnutls_datum.
+ *
+ * Note that the bits value should only be less than 512. That is because
+ * the RSA-EXPORT ciphersuites are only allowed to sign a modulus of 512
+ * bits.
+ *
+ -*/
+int gnutls_rsa_params_set(gnutls_rsa_params rsa_params,
+ gnutls_datum m, gnutls_datum e,
+ gnutls_datum d, gnutls_datum p, gnutls_datum q, gnutls_datum u,
+ int bits)
+{
+ int i;
+ size_t siz;
+
+ if (check_bits(bits) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ FREE_PRIVATE_PARAMS
+
+ siz = m.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[0], m.data, &siz)) {
+ gnutls_assert();
+ failed:
+ FREE_PRIVATE_PARAMS
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = e.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[1], e.data, &siz)) {
+ gnutls_assert();
+ goto failed;
+ }
+
+ siz = d.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[2], d.data, &siz)) {
+ gnutls_assert();
+ goto failed;
+ }
+
+ siz = p.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[3], p.data, &siz)) {
+ gnutls_assert();
+ goto failed;
+ }
+
+ siz = q.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[4], q.data, &siz)) {
+ gnutls_assert();
+ goto failed;
+ }
+
+ siz = u.size;
+ if (_gnutls_mpi_scan(&rsa_params->params[5], u.data, &siz)) {
+ gnutls_assert();
+ goto failed;
+ }
+
+ return 0;
+
+}
+
+
+#define FREE_ALL_MPIS for (i=0;i<sizeof(rsa_params)/sizeof(GNUTLS_MPI);i++) \
+ _gnutls_mpi_release( &rsa_params[i]) \
+
+/*-
+ * gnutls_rsa_params_generate - This function will generate temporary RSA parameters
+ * @m: will hold the modulus
+ * @e: will hold the public exponent
+ * @d: will hold the private exponent
+ * @p: will hold the first prime (p)
+ * @q: will hold the second prime (q)
+ * @u: will hold the coefficient
+ * @bits: is the prime's number of bits
+ *
+ * This function will generate new temporary RSA parameters for use in
+ * RSA-EXPORT ciphersuites. The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ * This function is normally slow. An other function
+ * (gnutls_rsa_params_set()) should be called in order to use the
+ * generated RSA parameters.
+ *
+ * Note that the bits value should be 512.
+ * Also note that the generation of new RSA parameters is only useful
+ * to servers. Clients use the parameters sent by the server, thus it's
+ * no use calling this in client side.
+ *
+ -*/
+int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e,
+ gnutls_datum *d, gnutls_datum *p, gnutls_datum* q,
+ gnutls_datum* u, int bits)
+{
+
+ GNUTLS_MPI rsa_params[RSA_PRIVATE_PARAMS];
+ size_t siz;
+ uint i;
+ int ret, params_len;
+
+ if (check_bits(bits) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret = _gnutls_rsa_generate_params( rsa_params, &params_len, bits);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[0]);
+
+ m->data = gnutls_malloc(siz);
+ if (m->data == NULL) {
+ FREE_ALL_MPIS;
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ m->size = siz;
+ _gnutls_mpi_print( m->data, &siz, rsa_params[0]);
+
+ /* E */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[1]);
+
+ e->data = gnutls_malloc(siz);
+ if (e->data == NULL) {
+ FREE_ALL_MPIS;
+ _gnutls_free_datum( m);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ e->size = siz;
+ _gnutls_mpi_print( e->data, &siz, rsa_params[1]);
+
+ /* D */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[2]);
+
+ d->data = gnutls_malloc(siz);
+ if (d->data == NULL) {
+ FREE_ALL_MPIS;
+ _gnutls_free_datum( m);
+ _gnutls_free_datum( e);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ d->size = siz;
+ _gnutls_mpi_print( d->data, &siz, rsa_params[2]);
+
+ /* P */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[3]);
+
+ p->data = gnutls_malloc(siz);
+ if (p->data == NULL) {
+ FREE_ALL_MPIS;
+ _gnutls_free_datum( m);
+ _gnutls_free_datum( e);
+ _gnutls_free_datum( d);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ p->size = siz;
+ _gnutls_mpi_print(p->data, &siz, rsa_params[3]);
+
+ /* Q */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[4]);
+
+ q->data = gnutls_malloc(siz);
+ if (q->data == NULL) {
+ FREE_ALL_MPIS;
+ _gnutls_free_datum( m);
+ _gnutls_free_datum( e);
+ _gnutls_free_datum( d);
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ q->size = siz;
+ _gnutls_mpi_print(q->data, &siz, rsa_params[4]);
+
+ /* U */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, rsa_params[5]);
+
+ u->data = gnutls_malloc(siz);
+ if (u->data == NULL) {
+ FREE_ALL_MPIS;
+ _gnutls_free_datum( m);
+ _gnutls_free_datum( e);
+ _gnutls_free_datum( d);
+ _gnutls_free_datum( p);
+ _gnutls_free_datum( q);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ u->size = siz;
+ _gnutls_mpi_print(u->data, &siz, rsa_params[5]);
+
+ FREE_ALL_MPIS;
+
+#ifdef DEBUG
+ {
+ opaque buffer[512];
+
+ _gnutls_debug_log("rsa_params_generate: Generated %d bits modulus %s, exponent %s.\n",
+ bits, _gnutls_bin2hex(m->data, m->size, buffer, sizeof(buffer)),
+ _gnutls_bin2hex( e->data, e->size, buffer, sizeof(buffer)));
+ }
+#endif
+
+ return 0;
+
+}
+
+/* compat.c - X.509 */
+
+/* This file includes all functions that were in the 0.5.x and 0.8.x
+ * gnutls API. They are now implemented over the new certificate parsing
+ * API.
+ */
+
+#include <x509/dn.h>
+#include <x509/common.h>
+#include <x509/verify.h>
+#include <x509/pkcs7.h>
+#include <gnutls/compat8.h>
+
+/*-
+ * gnutls_x509_extract_dn - This function parses an RDN sequence
+ * @idn: should contain a DER encoded RDN sequence
+ * @rdn: a pointer to a structure to hold the name
+ *
+ * This function will return the name of the given RDN sequence.
+ * The name will be returned as a gnutls_x509_dn structure.
+ * Returns a negative error code in case of an error.
+ *
+ -*/
+int gnutls_x509_extract_dn(const gnutls_datum * idn, gnutls_x509_dn * rdn)
+{
+ ASN1_TYPE dn = ASN1_TYPE_EMPTY;
+ int result;
+ size_t len;
+
+ if ((result =
+ asn1_create_element(_gnutls_get_pkix(),
+ "PKIX1.Name", &dn
+ )) != ASN1_SUCCESS) {
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&dn, idn->data, idn->size, NULL);
+ if (result != ASN1_SUCCESS) {
+ /* couldn't decode DER */
+ asn1_delete_structure(&dn);
+ return _gnutls_asn2err(result);
+ }
+
+ memset( rdn, 0, sizeof(gnutls_x509_dn));
+
+ len = sizeof(rdn->country);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_COUNTRY_NAME, 0, 0, rdn->country, &len);
+
+ len = sizeof(rdn->organization);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_ORGANIZATION_NAME, 0, 0, rdn->organization, &len);
+
+ len = sizeof(rdn->organizational_unit_name);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, rdn->organizational_unit_name, &len);
+
+ len = sizeof(rdn->common_name);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_COMMON_NAME, 0, 0, rdn->common_name, &len);
+
+ len = sizeof(rdn->locality_name);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_LOCALITY_NAME, 0, 0, rdn->locality_name, &len);
+
+ len = sizeof(rdn->state_or_province_name);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, rdn->state_or_province_name, &len);
+
+ len = sizeof(rdn->email);
+ _gnutls_x509_parse_dn_oid( dn, "", OID_PKCS9_EMAIL, 0, 0, rdn->email, &len);
+
+ asn1_delete_structure(&dn);
+
+ return 0;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_dn - This function returns the certificate's distinguished name
+ * @cert: should contain an X.509 DER encoded certificate
+ * @ret: a pointer to a structure to hold the peer's name
+ *
+ * This function will return the name of the certificate holder. The name is gnutls_x509_dn structure and
+ * is a obtained by the peer's certificate. If the certificate send by the
+ * peer is invalid, or in any other failure this function returns error.
+ * Returns a negative error code in case of an error.
+ *
+ -*/
+int gnutls_x509_extract_certificate_dn(const gnutls_datum * cert,
+ gnutls_x509_dn * ret)
+{
+ gnutls_x509_crt xcert;
+ int result;
+ size_t len;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ len = sizeof( ret->country);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_COUNTRY_NAME, 0, 0,
+ ret->country, &len);
+
+ len = sizeof( ret->organization);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_ORGANIZATION_NAME, 0, 0,
+ ret->organization, &len);
+
+ len = sizeof( ret->organizational_unit_name);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
+ ret->organizational_unit_name, &len);
+
+ len = sizeof( ret->common_name);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_COMMON_NAME, 0, 0,
+ ret->common_name, &len);
+
+ len = sizeof( ret->locality_name);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_LOCALITY_NAME, 0, 0,
+ ret->locality_name, &len);
+
+ len = sizeof( ret->state_or_province_name);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
+ ret->state_or_province_name, &len);
+
+ len = sizeof( ret->email);
+ gnutls_x509_crt_get_dn_by_oid( xcert, OID_PKCS9_EMAIL, 0, 0,
+ ret->email, &len);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return 0;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_issuer_dn - This function returns the certificate's issuer distinguished name
+ * @cert: should contain an X.509 DER encoded certificate
+ * @ret: a pointer to a structure to hold the issuer's name
+ *
+ * This function will return the name of the issuer stated in the certificate. The name is a gnutls_x509_dn structure and
+ * is a obtained by the peer's certificate. If the certificate send by the
+ * peer is invalid, or in any other failure this function returns error.
+ * Returns a negative error code in case of an error.
+ *
+ -*/
+int gnutls_x509_extract_certificate_issuer_dn(const gnutls_datum * cert,
+ gnutls_x509_dn * ret)
+{
+ gnutls_x509_crt xcert;
+ int result;
+ size_t len;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ len = sizeof( ret->country);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_COUNTRY_NAME, 0, 0,
+ ret->country, &len);
+
+ len = sizeof( ret->organization);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_ORGANIZATION_NAME, 0, 0,
+ ret->organization, &len);
+
+ len = sizeof( ret->organizational_unit_name);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
+ ret->organizational_unit_name, &len);
+
+ len = sizeof( ret->common_name);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_COMMON_NAME, 0, 0,
+ ret->common_name, &len);
+
+ len = sizeof( ret->locality_name);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_LOCALITY_NAME, 0, 0,
+ ret->locality_name, &len);
+
+ len = sizeof( ret->state_or_province_name);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
+ ret->state_or_province_name, &len);
+
+ len = sizeof( ret->email);
+ gnutls_x509_crt_get_issuer_dn_by_oid( xcert, OID_PKCS9_EMAIL, 0, 0,
+ ret->email, &len);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return 0;
+}
+
+
+/*-
+ * gnutls_x509_extract_certificate_subject_alt_name - This function returns the certificate's alternative name, if any
+ * @cert: should contain an X.509 DER encoded certificate
+ * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
+ * @ret: is the place where the alternative name will be copied to
+ * @ret_size: holds the size of ret.
+ *
+ * This function will return the alternative names, contained in the
+ * given certificate.
+ *
+ * This is specified in X509v3 Certificate Extensions.
+ * GNUTLS will return the Alternative name, or a negative
+ * error code.
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the alternative
+ * name, or the type of alternative name if everything was ok. The type is
+ * one of the enumerated GNUTLS_X509_SUBJECT_ALT_NAME.
+ *
+ * If the certificate does not have an Alternative name with the specified
+ * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ *
+ -*/
+int gnutls_x509_extract_certificate_subject_alt_name(const gnutls_datum * cert, int seq, char *ret, int *ret_size)
+{
+ gnutls_x509_crt xcert;
+ int result;
+ size_t size = *ret_size;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_subject_alt_name( xcert, seq, ret, &size, NULL);
+ *ret_size = size;
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_ca_status - This function returns the certificate CA status
+ * @cert: should contain an X.509 DER encoded certificate
+ *
+ * This function will return certificates CA status, by reading the
+ * basicConstraints X.509 extension. If the certificate is a CA a positive
+ * value will be returned, or zero if the certificate does not have
+ * CA flag set.
+ *
+ * A negative value may be returned in case of parsing error.
+ * If the certificate does not contain the basicConstraints extension
+ * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
+ *
+ -*/
+int gnutls_x509_extract_certificate_ca_status(const gnutls_datum * cert)
+{
+ gnutls_x509_crt xcert;
+ int result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_ca_status( xcert, NULL);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_activation_time - This function returns the peer's certificate activation time
+ * @cert: should contain an X.509 DER encoded certificate
+ *
+ * This function will return the certificate's activation time in UNIX time
+ * (ie seconds since 00:00:00 UTC January 1, 1970).
+ * Returns a (time_t) -1 in case of an error.
+ *
+ -*/
+time_t gnutls_x509_extract_certificate_activation_time(const
+ gnutls_datum *
+ cert)
+{
+ gnutls_x509_crt xcert;
+ time_t result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_activation_time( xcert);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_expiration_time - This function returns the certificate's expiration time
+ * @cert: should contain an X.509 DER encoded certificate
+ *
+ * This function will return the certificate's expiration time in UNIX time
+ * (ie seconds since 00:00:00 UTC January 1, 1970).
+ * Returns a (time_t) -1 in case of an error.
+ *
+ -*/
+time_t gnutls_x509_extract_certificate_expiration_time(const
+ gnutls_datum *
+ cert)
+{
+ gnutls_x509_crt xcert;
+ time_t result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_expiration_time( xcert);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+/*-
+ * gnutls_x509_extract_certificate_version - This function returns the certificate's version
+ * @cert: is an X.509 DER encoded certificate
+ *
+ * This function will return the X.509 certificate's version (1, 2, 3). This is obtained by the X509 Certificate
+ * Version field. Returns a negative value in case of an error.
+ *
+ -*/
+int gnutls_x509_extract_certificate_version(const gnutls_datum * cert)
+{
+ gnutls_x509_crt xcert;
+ int result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_version( xcert);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+
+}
+
+/*-
+ * gnutls_x509_extract_certificate_serial - This function returns the certificate's serial number
+ * @cert: is an X.509 DER encoded certificate
+ * @result: The place where the serial number will be copied
+ * @result_size: Holds the size of the result field.
+ *
+ * This function will return the X.509 certificate's serial number.
+ * This is obtained by the X509 Certificate serialNumber
+ * field. Serial is not always a 32 or 64bit number. Some CAs use
+ * large serial numbers, thus it may be wise to handle it as something
+ * opaque.
+ * Returns a negative value in case of an error.
+ *
+ -*/
+int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* result, int* result_size)
+{
+ gnutls_x509_crt xcert;
+ size_t size = *result_size;
+ int ret;
+
+ ret = gnutls_x509_crt_init( &xcert);
+ if (ret < 0) return ret;
+
+ ret = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return ret;
+ }
+
+ ret = gnutls_x509_crt_get_serial( xcert, result, &size);
+ *result_size = size;
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return ret;
+}
+
+
+/*-
+ * gnutls_x509_extract_certificate_pk_algorithm - This function returns the certificate's PublicKey algorithm
+ * @cert: is a DER encoded X.509 certificate
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of an X.509
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public
+ * exponent.
+ *
+ * Returns a member of the gnutls_pk_algorithm enumeration on success,
+ * or a negative value on error.
+ *
+ -*/
+int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int* bits)
+{
+ gnutls_x509_crt xcert;
+ int result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ result = gnutls_x509_crt_get_pk_algorithm( xcert, bits);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+
+/*-
+ * gnutls_x509_extract_certificate_dn_string - This function returns the certificate's distinguished name
+ * @cert: should contain an X.509 DER encoded certificate
+ * @buf: a pointer to a structure to hold the peer's name
+ * @sizeof_buf: holds the size of 'buf'
+ * @issuer: if non zero, then extract the name of the issuer, instead of the holder
+ *
+ * This function will copy the name of the certificate holder in the provided buffer. The name
+ * will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253.
+ *
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough,
+ * and 0 on success.
+ *
+ -*/
+int gnutls_x509_extract_certificate_dn_string(char *buf, unsigned int sizeof_buf,
+ const gnutls_datum * cert, int issuer)
+{
+ gnutls_x509_crt xcert;
+ int result;
+
+ result = gnutls_x509_crt_init( &xcert);
+ if (result < 0) return result;
+
+ result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit( xcert);
+ return result;
+ }
+
+ if (!issuer)
+ result = gnutls_x509_crt_get_dn( xcert, buf, &sizeof_buf);
+ else
+ result = gnutls_x509_crt_get_issuer_dn( xcert, buf, &sizeof_buf);
+
+ gnutls_x509_crt_deinit( xcert);
+
+ return result;
+}
+
+/*-
+ * gnutls_x509_verify_certificate - This function verifies given certificate list
+ * @cert_list: is the certificate list to be verified
+ * @cert_list_length: holds the number of certificate in cert_list
+ * @CA_list: is the CA list which will be used in verification
+ * @CA_list_length: holds the number of CA certificate in CA_list
+ * @CRL_list: not used
+ * @CRL_list_length: not used
+ *
+ * This function will try to verify the given certificate list and return its status (TRUSTED, EXPIRED etc.).
+ * The return value (status) should be one or more of the gnutls_certificate_status
+ * enumerated elements bitwise or'd. Note that expiration and activation dates are not checked
+ * by this function, you should check them using the appropriate functions.
+ *
+ * This function understands the basicConstraints (2.5.29.19) PKIX extension.
+ * This means that only a certificate authority can sign a certificate.
+ *
+ * However you must also check the peer's name in order to check if the verified certificate belongs to the
+ * actual peer.
+ *
+ * The return value (status) should be one or more of the gnutls_certificate_status
+ * enumerated elements bitwise or'd.
+ *
+ * GNUTLS_CERT_INVALID\: the peer's certificate is not valid.
+ *
+ * GNUTLS_CERT_REVOKED\: the certificate has been revoked.
+ *
+ * A negative error code is returned in case of an error.
+ * GNUTLS_E_NO_CERTIFICATE_FOUND is returned to indicate that
+ * no certificate was sent by the peer.
+ *
+ *
+ -*/
+int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list_length,
+ const gnutls_datum * CA_list, int CA_list_length,
+ const gnutls_datum* CRL_list, int CRL_list_length)
+{
+ unsigned int verify;
+ gnutls_x509_crt *peer_certificate_list = NULL;
+ gnutls_x509_crt *ca_certificate_list = NULL;
+ gnutls_x509_crl *crl_list = NULL;
+ int peer_certificate_list_size=0, i, x, ret;
+ int ca_certificate_list_size=0, crl_list_size=0;
+
+ if (cert_list == NULL || cert_list_length == 0)
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+
+ /* generate a list of gnutls_certs based on the auth info
+ * raw certs.
+ */
+ peer_certificate_list_size = cert_list_length;
+ peer_certificate_list =
+ gnutls_calloc(1,
+ peer_certificate_list_size *
+ sizeof(gnutls_x509_crt));
+ if (peer_certificate_list == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ ca_certificate_list_size = CA_list_length;
+ ca_certificate_list =
+ gnutls_calloc(1,
+ ca_certificate_list_size *
+ sizeof(gnutls_x509_crt));
+ if (ca_certificate_list == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ /* allocate memory for CRL
+ */
+ crl_list_size = CRL_list_length;
+ crl_list =
+ gnutls_calloc(1,
+ crl_list_size *
+ sizeof(gnutls_x509_crl));
+ if (crl_list == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ /* convert certA_list to gnutls_cert* list
+ */
+ for (i = 0; i < peer_certificate_list_size; i++) {
+ ret = gnutls_x509_crt_init( &peer_certificate_list[i]);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ gnutls_x509_crt_import(peer_certificate_list[i],
+ &cert_list[i], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
+
+ /* convert CA_list to gnutls_x509_cert* list
+ */
+ for (i = 0; i < ca_certificate_list_size; i++) {
+ ret = gnutls_x509_crt_init(&ca_certificate_list[i]);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ gnutls_x509_crt_import(ca_certificate_list[i],
+ &CA_list[i], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
+
+#ifdef ENABLE_PKI
+ /* convert CRL_list to gnutls_x509_crl* list
+ */
+ for (i = 0; i < crl_list_size; i++) {
+ ret = gnutls_x509_crl_init( &crl_list[i]);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ gnutls_x509_crl_import(crl_list[i],
+ &CRL_list[i], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
+#endif
+
+ /* Verify certificate
+ */
+ ret =
+ gnutls_x509_crt_list_verify(peer_certificate_list,
+ peer_certificate_list_size,
+ ca_certificate_list, ca_certificate_list_size,
+ crl_list, crl_list_size, 0, &verify);
+
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = verify;
+
+ cleanup:
+
+ if (peer_certificate_list != NULL)
+ for(x=0;x<peer_certificate_list_size;x++) {
+ if (peer_certificate_list[x] != NULL)
+ gnutls_x509_crt_deinit(peer_certificate_list[x]);
+ }
+
+ if (ca_certificate_list != NULL)
+ for(x=0;x<ca_certificate_list_size;x++) {
+ if (ca_certificate_list[x] != NULL)
+ gnutls_x509_crt_deinit(ca_certificate_list[x]);
+ }
+
+#ifdef ENABLE_PKI
+ if (crl_list != NULL)
+ for(x=0;x<crl_list_size;x++) {
+ if (crl_list[x] != NULL)
+ gnutls_x509_crl_deinit(crl_list[x]);
+ }
+
+ gnutls_free( crl_list);
+#endif
+
+ gnutls_free( ca_certificate_list);
+ gnutls_free( peer_certificate_list);
+
+ return ret;
+}
+
+/*-
+ * gnutls_x509_extract_key_pk_algorithm - This function returns the keys's PublicKey algorithm
+ * @cert: is a DER encoded private key
+ *
+ * This function will return the public key algorithm of a DER encoded private
+ * key.
+ *
+ * Returns a member of the gnutls_pk_algorithm enumeration on success,
+ * or GNUTLS_E_UNKNOWN_PK_ALGORITHM on error.
+ *
+ -*/
+int gnutls_x509_extract_key_pk_algorithm( const gnutls_datum * key)
+{
+ gnutls_x509_privkey pkey;
+ int ret, pk;
+
+ ret = gnutls_x509_privkey_init( &pkey);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_privkey_import( pkey, key, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ pk = gnutls_x509_privkey_get_pk_algorithm( pkey);
+
+ gnutls_x509_privkey_deinit( pkey);
+ return pk;
+}
+
+#ifdef ENABLE_PKI
+
+/*-
+ * gnutls_x509_pkcs7_extract_certificate - This function returns a certificate in a PKCS7 certificate set
+ * @pkcs7_struct: should contain a PKCS7 DER formatted structure
+ * @indx: contains the index of the certificate to extract
+ * @certificate: the contents of the certificate will be copied there
+ * @certificate_size: should hold the size of the certificate
+ *
+ * This function will return a certificate of the PKCS7 or RFC2630 certificate set.
+ * Returns 0 on success. If the provided buffer is not long enough,
+ * then GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
+ *
+ * After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * will be returned.
+ *
+ -*/
+int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size)
+{
+ gnutls_pkcs7 pkcs7;
+ int result;
+ size_t size = *certificate_size;
+
+ result = gnutls_pkcs7_init( &pkcs7);
+ if (result < 0) return result;
+
+ result = gnutls_pkcs7_import( pkcs7, pkcs7_struct, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_pkcs7_deinit( pkcs7);
+ return result;
+ }
+
+ result = gnutls_pkcs7_get_crt_raw( pkcs7, indx, certificate, &size);
+ *certificate_size = size;
+
+ gnutls_pkcs7_deinit( pkcs7);
+
+ return result;
+}
+
+
+/*-
+ * gnutls_x509_pkcs7_extract_certificate_count - This function returns the number of certificates in a PKCS7 certificate set
+ * @pkcs7_struct: should contain a PKCS7 DER formatted structure
+ *
+ * This function will return the number of certifcates in the PKCS7 or
+ * RFC2630 certificate set.
+ *
+ * Returns a negative value on failure.
+ *
+ -*/
+int gnutls_x509_pkcs7_extract_certificate_count(const gnutls_datum * pkcs7_struct)
+{
+ gnutls_pkcs7 pkcs7;
+ int result;
+
+ result = gnutls_pkcs7_init( &pkcs7);
+ if (result < 0) return result;
+
+ result = gnutls_pkcs7_import( pkcs7, pkcs7_struct, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_pkcs7_deinit( pkcs7);
+ return result;
+ }
+
+ result = gnutls_pkcs7_get_crt_count( pkcs7);
+
+ gnutls_pkcs7_deinit( pkcs7);
+
+ return result;
+}
+
+#endif /* ENABLE_PKI */
+
+/* rfc2818_hostname.c */
+
+/* compare hostname against certificate, taking account of wildcards
+ * return 1 on success or 0 on error
+ */
+static int _gnutls_hostname_compare(const char *certname, const char *hostname)
+{
+ const char *cmpstr1, *cmpstr2;
+
+ if (strlen(certname) == 0 || strlen(hostname) == 0)
+ return 0;
+
+ if (strlen(certname) > 2 && strncmp(certname, "*.", 2) == 0) {
+ /* a wildcard certificate */
+
+ cmpstr1 = certname + 1;
+
+ /* find the first dot in hostname, compare from there on */
+ cmpstr2 = strchr(hostname, '.');
+
+ if (cmpstr2 == NULL) {
+ /* error, the hostname we're connecting to is only a local part */
+ return 0;
+ }
+
+ if (strcasecmp(cmpstr1, cmpstr2) == 0) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (strcasecmp(certname, hostname) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+#define MAX_CN 256
+
+/*-
+ * gnutls_x509_check_certificates_hostname - This function compares the given hostname with the hostname in the certificate
+ * @cert: should contain a DER encoded certificate
+ * @hostname: A null terminated string that contains a DNS name
+ *
+ * This function will check if the given certificate's subject matches
+ * the given hostname. This is a basic implementation of the matching
+ * described in RFC2818 (HTTPS), which takes into account wildcards.
+ *
+ * Returns non zero on success, and zero on failure.
+ *
+ -*/
+int gnutls_x509_check_certificates_hostname(const gnutls_datum * cert,
+ const char *hostname)
+{
+ char dnsname[MAX_CN];
+ int dnsnamesize;
+ int found_dnsname = 0;
+ int ret = 0;
+ gnutls_x509_dn dn;
+ int i = 0;
+
+ /* try matching against:
+ * 1) a DNS name as an alternative name (subjectAltName) extension
+ * in the certificate
+ * 2) the common name (CN) in the certificate
+ *
+ * either of these may be of the form: *.domain.tld
+ *
+ * only try (2) if there is no subjectAltName extension of
+ * type dNSName
+ */
+
+ /* Check through all included subjectAltName extensions, comparing
+ * against all those of type dNSName.
+ */
+ for (i = 0; !(ret < 0); i++) {
+
+ dnsnamesize = MAX_CN;
+ ret =
+ gnutls_x509_extract_certificate_subject_alt_name(cert, i,
+ dnsname,
+ &dnsnamesize);
+
+ if (ret == GNUTLS_SAN_DNSNAME) {
+ found_dnsname = 1;
+ if (_gnutls_hostname_compare(dnsname, hostname)) {
+ return 1;
+ }
+ }
+
+ }
+
+ if (!found_dnsname) {
+ /* not got the necessary extension, use CN instead
+ */
+ if (gnutls_x509_extract_certificate_dn(cert, &dn) != 0) {
+ /* got an error, can't find a name
+ */
+ return 0;
+ }
+
+ if (_gnutls_hostname_compare(dn.common_name, hostname)) {
+ return 1;
+ }
+ }
+
+ /* not found a matching name
+ */
+ return 0;
+}
+
+/* gnutls_state.c
+ */
+void gnutls_record_set_cbc_protection(gnutls_session session, int prot)
+{
+ /* obsoleted by TLS 1.1 */
+ return;
+}
#endif /* GNUTLS_BACKWARDS_COMPATIBLE */
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index 4d250084c3..dbb28b10d2 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -357,7 +358,7 @@ int _gnutls_send_client_certificate( gnutls_session session, int again)
if (again == 0) {
if (gnutls_protocol_get_version( session) != GNUTLS_SSL3 ||
- session->internals.selected_cert_index >= 0) {
+ session->internals.selected_cert_list_length > 0) {
/* TLS 1.0 or SSL 3.0 with a valid certificate
*/
data_size = session->internals.auth_struct->gnutls_generate_client_certificate( session, &data);
@@ -374,7 +375,7 @@ int _gnutls_send_client_certificate( gnutls_session session, int again)
* empty certificate.
*/
if (gnutls_protocol_get_version( session) == GNUTLS_SSL3 &&
- session->internals.selected_cert_index < 0)
+ session->internals.selected_cert_list_length == 0)
{
ret = gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_SSL3_NO_CERTIFICATE);
diff --git a/lib/gnutls_mem.c b/lib/gnutls_mem.c
index dc21b196e1..0762c6f1ae 100644
--- a/lib/gnutls_mem.c
+++ b/lib/gnutls_mem.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_mpi.c b/lib/gnutls_mpi.c
index 8dede95446..0f115578c6 100644
--- a/lib/gnutls_mpi.c
+++ b/lib/gnutls_mpi.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_num.c b/lib/gnutls_num.c
index b0856ca7ad..8d9ed1c8c4 100644
--- a/lib/gnutls_num.c
+++ b/lib/gnutls_num.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c
index 78a294a43d..5a2d1e888d 100644
--- a/lib/gnutls_pk.c
+++ b/lib/gnutls_pk.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -491,14 +492,15 @@ int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *sig_value
}
/* decrypt signature */
- if ( (ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params,
- params_len)) < 0) {
- _gnutls_mpi_release(&mdata);
- gnutls_assert();
- return ret;
- }
+ ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params,
+ params_len);
_gnutls_mpi_release(&mdata);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
return 0; /* ok */
}
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index ad898bc53d..3a6a6d9907 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_random.c b/lib/gnutls_random.c
index 849ac3cb91..01e61d4c54 100644
--- a/lib/gnutls_random.c
+++ b/lib/gnutls_random.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -25,14 +26,6 @@
#include <gnutls_int.h>
#include <gnutls_random.h>
#include <gnutls_errors.h>
-#ifndef USE_GCRYPT
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-#endif
/* fills the buffer 'res' with random bytes of 'bytes' long.
* level is WEAK, STRONG, or VERY_STRONG (libgcrypt)
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 1629b9edde..91d77d2207 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -50,11 +51,13 @@
* Returns the version of the currently used protocol.
*
**/
-gnutls_protocol_version gnutls_protocol_get_version(gnutls_session session) {
+gnutls_protocol_version gnutls_protocol_get_version(gnutls_session session)
+{
return session->security_parameters.version;
}
-void _gnutls_set_current_version(gnutls_session session, gnutls_protocol_version version) {
+void _gnutls_set_current_version(gnutls_session session, gnutls_protocol_version version)
+{
session->security_parameters.version = version;
}
@@ -252,48 +255,6 @@ gnutls_protocol_version lver;
}
}
-inline static
-ssize_t _gnutls_create_empty_record( gnutls_session session, ContentType type,
- opaque* erecord, unsigned int erecord_size)
-{
- int cipher_size;
- int retval;
- int data2send;
- uint8 headers[5];
-
- if (type!=GNUTLS_APPLICATION_DATA ||
- _gnutls_cipher_is_block( gnutls_cipher_get(session))!=CIPHER_BLOCK)
- /* alert messages and stream ciphers
- * do not need this protection
- */
- return 0;
-
- headers[0] = type;
-
- copy_record_version( session, (HandshakeType)(-1), &headers[1]);
-
- data2send = 0;
-
- cipher_size = _gnutls_encrypt( session, headers, RECORD_HEADER_SIZE, NULL, 0, erecord, erecord_size, type, 0);
- if (cipher_size <= 0) {
- gnutls_assert();
- if (cipher_size==0) cipher_size = GNUTLS_E_ENCRYPTION_FAILED;
- return cipher_size; /* error */
- }
-
- retval = cipher_size;
-
- /* increase sequence number
- */
- if (_gnutls_uint64pp( &session->connection_state.write_sequence_number) != 0) {
- _gnutls_session_invalidate( session);
- gnutls_assert();
- return GNUTLS_E_RECORD_LIMIT_REACHED;
- }
-
- return retval;
-}
-
/* This function behaves exactly like write(). The only difference is
* that it accepts, the gnutls_session and the ContentType of data to
* send (if called by the user the Content is specific)
@@ -308,7 +269,8 @@ ssize_t _gnutls_create_empty_record( gnutls_session session, ContentType type,
* and only if the previous send was interrupted for some reason.
*
*/
-ssize_t _gnutls_send_int( gnutls_session session, ContentType type, HandshakeType htype, const void *_data, size_t sizeofdata)
+ssize_t _gnutls_send_int( gnutls_session session, ContentType type,
+ HandshakeType htype, const void *_data, size_t sizeofdata)
{
uint8 *cipher;
int cipher_size;
@@ -366,27 +328,6 @@ ssize_t _gnutls_send_int( gnutls_session session, ContentType type, HandshakeTyp
retval = session->internals.record_send_buffer_user_size;
} else {
- /* Prepend our packet with an empty record. This is to
- * avoid the recent CBC attacks.
- */
- /* if this protection has been disabled
- */
- if (session->internals.cbc_protection_hack!=0) {
- erecord_size = MAX_RECORD_OVERHEAD;
- erecord = gnutls_alloca( erecord_size);
- if (erecord==NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- erecord_size =
- _gnutls_create_empty_record( session, type, erecord, erecord_size);
- if (erecord_size < 0) {
- gnutls_assert();
- return erecord_size;
- }
- }
-
/* now proceed to packet encryption
*/
cipher_size = data2send_size + MAX_RECORD_OVERHEAD;
@@ -437,7 +378,6 @@ ssize_t _gnutls_send_int( gnutls_session session, ContentType type, HandshakeTyp
gnutls_assert();
ret = GNUTLS_E_INTERNAL_ERROR;
}
-
_gnutls_session_unresumable( session);
_gnutls_session_invalidate( session);
gnutls_assert();
@@ -562,10 +502,10 @@ static int _gnutls_check_record_headers( gnutls_session session, uint8 headers[R
/* Here we check if the advertized version is the one we
* negotiated in the handshake.
*/
+#ifdef CHECK_RECORD_VERSION
inline
static int _gnutls_check_record_version( gnutls_session session, HandshakeType htype, opaque version[2])
{
-#ifdef CHECK_RECORD_VERSION
if ( (htype!=GNUTLS_CLIENT_HELLO && htype!=GNUTLS_SERVER_HELLO) &&
gnutls_protocol_get_version(session) != _gnutls_version_get( version[0], version[1])) {
@@ -575,10 +515,12 @@ static int _gnutls_check_record_version( gnutls_session session, HandshakeType h
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
}
-#endif
return 0;
}
+#else
+# define _gnutls_check_record_version(x,y,z) 0
+#endif
/* This function will check if the received record type is
* the one we actually expect.
@@ -618,7 +560,6 @@ static int _gnutls_record_check_type( gnutls_session session, ContentType recv_t
if (data[0] == GNUTLS_AL_FATAL) {
_gnutls_session_unresumable( session);
_gnutls_session_invalidate( session);
-
ret = GNUTLS_E_FATAL_ALERT_RECEIVED;
}
@@ -689,9 +630,11 @@ static int _gnutls_record_check_type( gnutls_session session, ContentType recv_t
* that it accepts the gnutls_session and the ContentType of data to
* receive (if called by the user the Content is Userdata only)
* It is intended to receive data, under the current session.
+ *
+ * The HandshakeType was introduced to support SSL V2.0 client hellos.
*/
-ssize_t _gnutls_recv_int( gnutls_session session, ContentType type, HandshakeType htype,
- opaque *data, size_t sizeofdata)
+ssize_t _gnutls_recv_int( gnutls_session session, ContentType type,
+ HandshakeType htype, opaque *data, size_t sizeofdata)
{
uint8 *tmpdata;
int tmplen;
@@ -934,10 +877,10 @@ ssize_t gnutls_record_send( gnutls_session session, const void *data, size_t siz
* @sizeofdata: is the length of the data
*
* This function has the similar semantics to send(). The only
- * difference is that is accepts a GNUTLS session.
+ * difference is that it accepts a GNUTLS session.
*
- * If the server requests a renegotiation the client may receive
- * and error code of GNUTLS_E_REHANDSHAKE. This message may be
+ * If the server requests a renegotiation, the client may receive
+ * an error code of GNUTLS_E_REHANDSHAKE. This message may be
* simply ignored, replied with an alert containing NO_RENEGOTIATION,
* or replied with a new handshake.
*
diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c
index b772a2312c..05e82535ef 100644
--- a/lib/gnutls_rsa_export.c
+++ b/lib/gnutls_rsa_export.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -43,7 +44,6 @@
const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params rsa_params)
{
if (rsa_params == NULL) {
- gnutls_assert();
return NULL;
}
diff --git a/lib/gnutls_session.c b/lib/gnutls_session.c
index 2c44748431..ca043c5b21 100644
--- a/lib/gnutls_session.c
+++ b/lib/gnutls_session.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2000,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 1a108d347d..f3b387d65f 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index 277db2aacc..bdcc35d135 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -147,30 +148,6 @@ opaque concat[36];
}
-/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
- * Cert is the certificate of the corresponding private key. It is only checked if
- * it supports signing.
- */
-static
-int _gnutls_tls_sign( gnutls_cert* cert, gnutls_privkey* pkey, const gnutls_datum* hash_concat, gnutls_datum *signature)
-{
-
- /* If our certificate supports signing
- */
-
- if ( cert != NULL)
- if ( cert->keyUsage != 0)
- if ( !(cert->keyUsage & KEY_DIGITAL_SIGNATURE)) {
- gnutls_assert();
- return GNUTLS_E_KEY_USAGE_VIOLATION;
- }
-
- return _gnutls_sign( pkey->pk_algorithm, pkey->params, pkey->params_size,
- hash_concat, signature);
-
-}
-
-
/* This will create a PKCS1 or DSA signature, using the given parameters, and the
* given data. The output will be allocated and be put in signature.
*/
@@ -206,6 +183,30 @@ int ret;
return 0;
}
+/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
+ * Cert is the certificate of the corresponding private key. It is only checked if
+ * it supports signing.
+ */
+static
+int _gnutls_tls_sign( gnutls_cert* cert, gnutls_privkey* pkey,
+ const gnutls_datum* hash_concat, gnutls_datum *signature)
+{
+
+ /* If our certificate supports signing
+ */
+
+ if ( cert != NULL)
+ if ( cert->keyUsage != 0)
+ if ( !(cert->keyUsage & KEY_DIGITAL_SIGNATURE)) {
+ gnutls_assert();
+ return GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+
+ return _gnutls_sign( pkey->pk_algorithm, pkey->params, pkey->params_size,
+ hash_concat, signature);
+
+}
+
static
int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *hash_concat,
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 310f159ccb..d63893d55b 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -20,7 +21,7 @@
*/
/* Functions to manipulate the session (gnutls_int.h), and some other stuff
- * are included here. The file's name is traditionaly gnutls_state even if the
+ * are included here. The file's name is traditionally gnutls_state even if the
* state has been renamed to session.
*/
@@ -273,6 +274,7 @@ void _gnutls_deinit(gnutls_session session)
_gnutls_buffer_clear( &session->internals.record_send_buffer);
gnutls_credentials_clear( session);
+ _gnutls_selected_certs_deinit( session);
if (session->connection_state.read_cipher_state != NULL)
_gnutls_cipher_deinit(session->connection_state.read_cipher_state);
@@ -505,30 +507,6 @@ void _gnutls_record_set_default_version(gnutls_session session,
}
/**
- * gnutls_record_set_cbc_protection - Used to disable the CBC protection
- * @session: is a &gnutls_session structure.
- * @prot: is an integer (0 or 1)
- *
- * A newly discovered attack against the record protocol requires some
- * counter-measures to be taken. GnuTLS will not enable them by default.
- * The protection is to send an empty record packet, before each actual record
- * packet, in order to assure that the IV is not known to potential attackers.
- *
- * This function will enable or disable the chosen plaintext protection
- * in the TLS record protocol (used with ciphers in CBC mode).
- * if prot == 0 then protection is disabled (default), otherwise it
- * is enabled.
- *
- * The protection used will slightly decrease performance, and add
- * 20 or more bytes per record packet.
- *
- **/
-void gnutls_record_set_cbc_protection(gnutls_session session, int prot)
-{
- session->internals.cbc_protection_hack = prot;
-}
-
-/**
* gnutls_handshake_set_private_extensions - Used to enable the private cipher suites
* @session: is a &gnutls_session structure.
* @allow: is an integer (0 or 1)
@@ -777,7 +755,7 @@ void gnutls_session_set_ptr(gnutls_session session, void* ptr)
/**
* gnutls_record_get_direction - This function will return the direction of the last interrupted function call
- * @session: is a a &gnutls_session structure.
+ * @session: is a &gnutls_session structure.
*
* This function provides information about the internals of the record
* protocol and is only useful if a prior gnutls function call (e.g.
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index 9a3918cb7a..50e7486e53 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c
index dc5207efe2..f29eab87d8 100644
--- a/lib/gnutls_ui.c
+++ b/lib/gnutls_ui.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -196,7 +197,6 @@ int gnutls_dh_get_peers_public_bits(gnutls_session session)
const gnutls_datum *gnutls_certificate_get_ours(gnutls_session session)
{
const gnutls_certificate_credentials cred;
- int index;
CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL);
@@ -206,15 +206,10 @@ const gnutls_datum *gnutls_certificate_get_ours(gnutls_session session)
return NULL;
}
- index = session->internals.selected_cert_index;
- if (index < 0) {
- gnutls_assert();
- return NULL; /* no certificate */
- }
-
- if (cred->ncerts > (unsigned int) index)
- return &cred->cert_list[index][0].raw;
- return NULL;
+ if (session->internals.selected_cert_list == NULL)
+ return NULL;
+
+ return &session->internals.selected_cert_list[0].raw;
}
/**
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index 007690182c..8b7e0bd052 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -2,32 +2,63 @@
# define GNUTLS_UI_H
typedef enum gnutls_x509_subject_alt_name {
- GNUTLS_SAN_DNSNAME=1, GNUTLS_SAN_RFC822NAME,
+ GNUTLS_SAN_DNSNAME = 1, GNUTLS_SAN_RFC822NAME,
GNUTLS_SAN_URI, GNUTLS_SAN_IPADDRESS
} gnutls_x509_subject_alt_name;
-# ifdef LIBGNUTLS_VERSION /* These are defined only in gnutls.h */
+# ifdef LIBGNUTLS_VERSION /* These are defined only in gnutls.h */
/* Callback prototypes for the certificate authentication
* callbacks.
*/
-typedef int gnutls_certificate_client_select_function(
- gnutls_session, const gnutls_datum *client_cert, int ncerts,
- const gnutls_datum* req_ca_cert, int nreqs);
-typedef int gnutls_certificate_server_select_function(
- gnutls_session, const gnutls_datum *server_certs, int ncerts);
+typedef int gnutls_certificate_client_select_function(gnutls_session,
+ const gnutls_datum * client_cert, int ncerts,
+ const gnutls_datum * req_ca_cert, int nreqs);
+typedef int gnutls_certificate_server_select_function(gnutls_session,
+ const gnutls_datum * server_certs, int ncerts);
+
+
+struct gnutls_openpgp_key_int;
+typedef struct gnutls_openpgp_key_int *gnutls_openpgp_key;
+
+struct gnutls_openpgp_privkey_int;
+typedef struct gnutls_openpgp_privkey_int *gnutls_openpgp_privkey;
+
+typedef struct gnutls_retr_st {
+ gnutls_certificate_type type;
+ union cert {
+ gnutls_x509_crt *x509;
+ gnutls_openpgp_key pgp;
+ } cert;
+ unsigned int ncerts; /* one for pgp keys */
+
+ union key {
+ gnutls_x509_privkey x509;
+ gnutls_openpgp_privkey pgp;
+ } key;
+
+ unsigned int deinit_all; /* if non zero all keys will be deinited */
+} gnutls_retr_st;
+
+typedef int gnutls_certificate_client_retrieve_function(gnutls_session,
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ const gnutls_pk_algorithm* pk_algos, int pk_algos_length,
+ gnutls_retr_st *);
+typedef int gnutls_certificate_server_retrieve_function(gnutls_session,
+ gnutls_retr_st *);
+
/* Functions that allow AUTH_INFO structures handling
*/
-gnutls_credentials_type gnutls_auth_get_type( gnutls_session session);
+gnutls_credentials_type gnutls_auth_get_type(gnutls_session session);
/* DH */
-void gnutls_dh_set_prime_bits( gnutls_session session, int bits);
-int gnutls_dh_get_prime_bits( gnutls_session);
-int gnutls_dh_get_secret_bits( gnutls_session);
-int gnutls_dh_get_peers_public_bits( gnutls_session);
+void gnutls_dh_set_prime_bits(gnutls_session session, int bits);
+int gnutls_dh_get_prime_bits(gnutls_session);
+int gnutls_dh_get_secret_bits(gnutls_session);
+int gnutls_dh_get_peers_public_bits(gnutls_session);
/* RSA */
int gnutls_rsa_export_get_modulus_bits(gnutls_session session);
@@ -36,41 +67,53 @@ int gnutls_rsa_export_get_modulus_bits(gnutls_session session);
#include <gnutls/compat8.h>
-void gnutls_certificate_client_set_select_function( gnutls_session, gnutls_certificate_client_select_function *);
-void gnutls_certificate_server_set_select_function( gnutls_session, gnutls_certificate_server_select_function *);
+void gnutls_certificate_client_set_select_function(gnutls_session,
+ gnutls_certificate_client_select_function *);
+void gnutls_certificate_server_set_select_function(gnutls_session,
+ gnutls_certificate_server_select_function *);
+
+/* These are set on the credentials structure.
+ */
+void gnutls_certificate_client_set_retrieve_function(gnutls_certificate_client_credentials,
+ gnutls_certificate_client_retrieve_function *);
+void gnutls_certificate_server_set_retrieve_function(gnutls_certificate_server_credentials,
+ gnutls_certificate_server_retrieve_function *);
-void gnutls_certificate_server_set_request( gnutls_session, gnutls_certificate_request);
+void gnutls_certificate_server_set_request(gnutls_session,
+ gnutls_certificate_request);
/* X.509 certificate handling functions
*/
int gnutls_pkcs3_extract_dh_params(const gnutls_datum * params,
gnutls_x509_crt_fmt format, gnutls_datum * prime,
- gnutls_datum * generator, int* prime_bits);
-int gnutls_pkcs3_export_dh_params( const gnutls_datum * prime,
+ gnutls_datum * generator, int *prime_bits);
+int gnutls_pkcs3_export_dh_params(const gnutls_datum * prime,
const gnutls_datum * generator, gnutls_x509_crt_fmt format,
- unsigned char* params_data, int* params_data_size);
+ unsigned char *params_data, int *params_data_size);
/* get data from the session
*/
-const gnutls_datum* gnutls_certificate_get_peers( gnutls_session, unsigned int* list_size);
-const gnutls_datum *gnutls_certificate_get_ours( gnutls_session session);
+const gnutls_datum *gnutls_certificate_get_peers(gnutls_session,
+ unsigned int *list_size);
+const gnutls_datum *gnutls_certificate_get_ours(gnutls_session session);
time_t gnutls_certificate_activation_time_peers(gnutls_session session);
time_t gnutls_certificate_expiration_time_peers(gnutls_session session);
-int gnutls_certificate_client_get_request_status( gnutls_session);
-int gnutls_certificate_verify_peers( gnutls_session);
+int gnutls_certificate_client_get_request_status(gnutls_session);
+int gnutls_certificate_verify_peers(gnutls_session);
-int gnutls_pem_base64_encode( const char* header, const gnutls_datum *data,
- char* result, size_t* result_size);
-int gnutls_pem_base64_decode( const char* header, const gnutls_datum *b64_data,
- unsigned char* result, size_t* result_size);
+int gnutls_pem_base64_encode(const char *header, const gnutls_datum * data,
+ char *result, size_t * result_size);
+int gnutls_pem_base64_decode(const char *header,
+ const gnutls_datum * b64_data,
+ unsigned char *result, size_t * result_size);
-int gnutls_pem_base64_encode_alloc( const char* header, const gnutls_datum *data,
- gnutls_datum * result);
-int gnutls_pem_base64_decode_alloc( const char* header, const gnutls_datum *b64_data,
- gnutls_datum* result);
+int gnutls_pem_base64_encode_alloc(const char *header,
+ const gnutls_datum * data, gnutls_datum * result);
+int gnutls_pem_base64_decode_alloc(const char *header,
+ const gnutls_datum * b64_data, gnutls_datum * result);
/* key_usage will be an OR of the following values:
*/
@@ -89,6 +132,6 @@ int gnutls_pem_base64_decode_alloc( const char* header, const gnutls_datum *b64_
#define GNUTLS_KEY_DECIPHER_ONLY 32768
-# endif /* LIBGNUTLS_VERSION */
+# endif /* LIBGNUTLS_VERSION */
-#endif /* GNUTLS_UI_H */
+#endif /* GNUTLS_UI_H */
diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c
index 0676b2dc1b..9db6516b2c 100644
--- a/lib/gnutls_v2_compat.c
+++ b/lib/gnutls_v2_compat.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 6ee494064b..ff2603333d 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -220,7 +221,7 @@ static int parse_crt_mem( gnutls_cert** cert_list, uint* ncerts,
return GNUTLS_E_MEMORY_ERROR;
}
- ret = _gnutls_x509_crt2gnutls_cert(
+ ret = _gnutls_x509_crt_to_gcert(
&cert_list[0][i-1], cert, 0);
if ( ret < 0) {
gnutls_assert();
@@ -357,7 +358,7 @@ static int parse_pkcs7_cert_mem( gnutls_cert** cert_list, uint* ncerts, const
tmp2.data = pcert;
tmp2.size = pcert_size;
- ret = _gnutls_x509_cert2gnutls_cert(
+ ret = _gnutls_x509_raw_cert_to_gcert(
&cert_list[0][i - 1], &tmp2, 0);
if ( ret < 0) {
@@ -385,10 +386,10 @@ static int parse_pkcs7_cert_mem( gnutls_cert** cert_list, uint* ncerts, const
* a gnutls_cert structure. Returns the number of certificate parsed.
*/
static int parse_pem_cert_mem( gnutls_cert** cert_list, uint* ncerts,
- const opaque *input_cert, int input_cert_size)
+ const char *input_cert, int input_cert_size)
{
int size, siz2, i;
- const opaque *ptr;
+ const char *ptr;
opaque *ptr2;
gnutls_datum tmp;
int ret, count;
@@ -441,7 +442,7 @@ static int parse_pem_cert_mem( gnutls_cert** cert_list, uint* ncerts,
tmp.data = ptr2;
tmp.size = siz2;
- ret = _gnutls_x509_cert2gnutls_cert(
+ ret = _gnutls_x509_raw_cert_to_gcert(
&cert_list[0][i - 1], &tmp, 0);
if ( ret < 0) {
gnutls_assert();
@@ -519,7 +520,7 @@ int read_cert_mem(gnutls_certificate_credentials res, const void *cert, int cert
}
-static int privkey_cpy( gnutls_privkey* dest, gnutls_x509_privkey src)
+int _gnutls_x509_privkey_to_gkey( gnutls_privkey* dest, gnutls_x509_privkey src)
{
int i, ret;
@@ -547,15 +548,46 @@ int i, ret;
return ret;
}
-void _gnutls_privkey_deinit(gnutls_privkey *key)
+void _gnutls_gkey_deinit(gnutls_privkey *key)
{
int i;
+ if (key == NULL) return;
for (i = 0; i < key->params_size; i++) {
_gnutls_mpi_release( &key->params[i]);
}
}
+int _gnutls_x509_raw_privkey_to_gkey( gnutls_privkey* privkey, const gnutls_datum* raw_key,
+ gnutls_x509_crt_fmt type)
+{
+gnutls_x509_privkey tmpkey;
+int ret;
+
+ ret = gnutls_x509_privkey_init( &tmpkey);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_privkey_import( tmpkey, raw_key, type);
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_x509_privkey_deinit( tmpkey);
+ return ret;
+ }
+
+ ret = _gnutls_x509_privkey_to_gkey( privkey, tmpkey);
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_x509_privkey_deinit( tmpkey);
+ return ret;
+ }
+
+ gnutls_x509_privkey_deinit( tmpkey);
+
+ return 0;
+}
/* Reads a PEM encoded PKCS-1 RSA private key from memory
* 2002-01-26: Added ability to read DSA keys.
@@ -566,7 +598,6 @@ static int read_key_mem(gnutls_certificate_credentials res, const void *key, int
{
int ret;
gnutls_datum tmp;
- gnutls_x509_privkey tmpkey;
/* allocate space for the pkey list
*/
@@ -576,33 +607,15 @@ static int read_key_mem(gnutls_certificate_credentials res, const void *key, int
return GNUTLS_E_MEMORY_ERROR;
}
- ret = gnutls_x509_privkey_init( &tmpkey); //res->pkey[res->ncerts]);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
tmp.data = (opaque*)key;
tmp.size = key_size;
- ret = gnutls_x509_privkey_import( tmpkey, &tmp, type);
+ ret = _gnutls_x509_raw_privkey_to_gkey( &res->pkey[res->ncerts], &tmp, type);
if (ret < 0) {
gnutls_assert();
- gnutls_x509_privkey_deinit( tmpkey);
-
- return ret;
- }
-
- ret = privkey_cpy( &res->pkey[res->ncerts], tmpkey);
- if (ret < 0) {
- gnutls_assert();
- gnutls_x509_privkey_deinit( tmpkey);
-
return ret;
}
- gnutls_x509_privkey_deinit( tmpkey);
-
return 0;
}
@@ -827,7 +840,7 @@ int gnutls_certificate_set_x509_key(gnutls_certificate_credentials res,
return GNUTLS_E_MEMORY_ERROR;
}
- ret = privkey_cpy( &res->pkey[res->ncerts], key);
+ ret = _gnutls_x509_privkey_to_gkey( &res->pkey[res->ncerts], key);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h
index b48c2e1038..5a832b275f 100644
--- a/lib/gnutls_x509.h
+++ b/lib/gnutls_x509.h
@@ -16,3 +16,6 @@ int _gnutls_check_key_usage( const gnutls_cert* cert, gnutls_kx_algorithm alg);
int _gnutls_x509_read_rsa_params(opaque * der, int dersize, GNUTLS_MPI * params);
int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params);
+int _gnutls_x509_raw_privkey_to_gkey( gnutls_privkey* privkey, const gnutls_datum* raw_key,
+ gnutls_x509_crt_fmt type);
+int _gnutls_x509_privkey_to_gkey( gnutls_privkey* privkey, gnutls_x509_privkey);
diff --git a/lib/rsa_compat.c b/lib/rsa_compat.c
deleted file mode 100644
index 18a33a2a3f..0000000000
--- a/lib/rsa_compat.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2002,2003 Nikos Mavroyanopoulos
- *
- * This file is part of GNUTLS.
- *
- * The GNUTLS library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* This file contains code for RSA temporary keys. These keys are
- * only used in export cipher suites.
- */
-
-#include <gnutls_int.h>
-#include <gnutls_errors.h>
-#include <gnutls_datum.h>
-#include <gnutls_rsa_export.h>
-#include "debug.h"
-
-/* This function takes a number of bits and returns a supported
- * number of bits. Ie a number of bits that we have a prime in the
- * dh_primes structure.
- */
-
-#define MAX_SUPPORTED_BITS 512
-
-/* returns a negative value if the bits size is not supported
- */
-static int check_bits(int bits)
-{
- if (bits > MAX_SUPPORTED_BITS)
- return GNUTLS_E_INVALID_REQUEST;
-
- return 0;
-}
-
-
-#define FREE_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
- _gnutls_mpi_release(&rsa_params->params[i]);
-
-/*-
- * gnutls_rsa_params_set - This function will replace the old RSA parameters
- * @rsa_params: Is a structure which will hold the parameters
- * @m: holds the modulus
- * @e: holds the public exponent
- * @d: holds the private exponent
- * @p: holds the first prime (p)
- * @q: holds the second prime (q)
- * @u: holds the coefficient
- * @bits: is the modulus's number of bits
- *
- * This function will replace the parameters used in the RSA-EXPORT key
- * exchange. The new parameters should be stored in the
- * appropriate gnutls_datum.
- *
- * Note that the bits value should only be less than 512. That is because
- * the RSA-EXPORT ciphersuites are only allowed to sign a modulus of 512
- * bits.
- *
- -*/
-int gnutls_rsa_params_set(gnutls_rsa_params rsa_params,
- gnutls_datum m, gnutls_datum e,
- gnutls_datum d, gnutls_datum p, gnutls_datum q, gnutls_datum u,
- int bits)
-{
- int i;
- size_t siz;
-
- if (check_bits(bits) < 0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- FREE_PRIVATE_PARAMS
-
- siz = m.size;
- if (_gnutls_mpi_scan(&rsa_params->params[0], m.data, &siz)) {
- gnutls_assert();
- failed:
- FREE_PRIVATE_PARAMS
- return GNUTLS_E_MPI_SCAN_FAILED;
- }
-
- siz = e.size;
- if (_gnutls_mpi_scan(&rsa_params->params[1], e.data, &siz)) {
- gnutls_assert();
- goto failed;
- }
-
- siz = d.size;
- if (_gnutls_mpi_scan(&rsa_params->params[2], d.data, &siz)) {
- gnutls_assert();
- goto failed;
- }
-
- siz = p.size;
- if (_gnutls_mpi_scan(&rsa_params->params[3], p.data, &siz)) {
- gnutls_assert();
- goto failed;
- }
-
- siz = q.size;
- if (_gnutls_mpi_scan(&rsa_params->params[4], q.data, &siz)) {
- gnutls_assert();
- goto failed;
- }
-
- siz = u.size;
- if (_gnutls_mpi_scan(&rsa_params->params[5], u.data, &siz)) {
- gnutls_assert();
- goto failed;
- }
-
- return 0;
-
-}
-
-
-#define FREE_ALL_MPIS for (i=0;i<sizeof(rsa_params)/sizeof(GNUTLS_MPI);i++) \
- _gnutls_mpi_release( &rsa_params[i]) \
-
-/*-
- * gnutls_rsa_params_generate - This function will generate temporary RSA parameters
- * @m: will hold the modulus
- * @e: will hold the public exponent
- * @d: will hold the private exponent
- * @p: will hold the first prime (p)
- * @q: will hold the second prime (q)
- * @u: will hold the coefficient
- * @bits: is the prime's number of bits
- *
- * This function will generate new temporary RSA parameters for use in
- * RSA-EXPORT ciphersuites. The new parameters will be allocated using
- * gnutls_malloc() and will be stored in the appropriate datum.
- * This function is normally slow. An other function
- * (gnutls_rsa_params_set()) should be called in order to use the
- * generated RSA parameters.
- *
- * Note that the bits value should be 512.
- * Also note that the generation of new RSA parameters is only useful
- * to servers. Clients use the parameters sent by the server, thus it's
- * no use calling this in client side.
- *
- -*/
-int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e,
- gnutls_datum *d, gnutls_datum *p, gnutls_datum* q,
- gnutls_datum* u, int bits)
-{
-
- GNUTLS_MPI rsa_params[RSA_PRIVATE_PARAMS];
- size_t siz;
- uint i;
- int ret, params_len;
-
- if (check_bits(bits) < 0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- ret = _gnutls_rsa_generate_params( rsa_params, &params_len, bits);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[0]);
-
- m->data = gnutls_malloc(siz);
- if (m->data == NULL) {
- FREE_ALL_MPIS;
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- m->size = siz;
- _gnutls_mpi_print( m->data, &siz, rsa_params[0]);
-
- /* E */
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[1]);
-
- e->data = gnutls_malloc(siz);
- if (e->data == NULL) {
- FREE_ALL_MPIS;
- _gnutls_free_datum( m);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- e->size = siz;
- _gnutls_mpi_print( e->data, &siz, rsa_params[1]);
-
- /* D */
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[2]);
-
- d->data = gnutls_malloc(siz);
- if (d->data == NULL) {
- FREE_ALL_MPIS;
- _gnutls_free_datum( m);
- _gnutls_free_datum( e);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- d->size = siz;
- _gnutls_mpi_print( d->data, &siz, rsa_params[2]);
-
- /* P */
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[3]);
-
- p->data = gnutls_malloc(siz);
- if (p->data == NULL) {
- FREE_ALL_MPIS;
- _gnutls_free_datum( m);
- _gnutls_free_datum( e);
- _gnutls_free_datum( d);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- p->size = siz;
- _gnutls_mpi_print(p->data, &siz, rsa_params[3]);
-
- /* Q */
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[4]);
-
- q->data = gnutls_malloc(siz);
- if (q->data == NULL) {
- FREE_ALL_MPIS;
- _gnutls_free_datum( m);
- _gnutls_free_datum( e);
- _gnutls_free_datum( d);
- _gnutls_free_datum( p);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- q->size = siz;
- _gnutls_mpi_print(q->data, &siz, rsa_params[4]);
-
- /* U */
- siz = 0;
- _gnutls_mpi_print(NULL, &siz, rsa_params[5]);
-
- u->data = gnutls_malloc(siz);
- if (u->data == NULL) {
- FREE_ALL_MPIS;
- _gnutls_free_datum( m);
- _gnutls_free_datum( e);
- _gnutls_free_datum( d);
- _gnutls_free_datum( p);
- _gnutls_free_datum( q);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- u->size = siz;
- _gnutls_mpi_print(u->data, &siz, rsa_params[5]);
-
- FREE_ALL_MPIS;
-
-#ifdef DEBUG
- {
- opaque buffer[512];
-
- _gnutls_debug_log("rsa_params_generate: Generated %d bits modulus %s, exponent %s.\n",
- bits, _gnutls_bin2hex(m->data, m->size, buffer, sizeof(buffer)),
- _gnutls_bin2hex( e->data, e->size, buffer, sizeof(buffer)));
- }
-#endif
-
- return 0;
-
-}
diff --git a/lib/strnstr.c b/lib/strnstr.c
index 57aed55fb0..7eaa9d0dac 100644
--- a/lib/strnstr.c
+++ b/lib/strnstr.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/x509/compat.c b/lib/x509/compat.c
index 95b0ae6877..00fcd4629a 100644
--- a/lib/x509/compat.c
+++ b/lib/x509/compat.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -32,264 +33,6 @@
#include <gnutls/x509.h>
/**
- * gnutls_x509_extract_dn - This function parses an RDN sequence
- * @idn: should contain a DER encoded RDN sequence
- * @rdn: a pointer to a structure to hold the name
- *
- * This function will return the name of the given RDN sequence.
- * The name will be returned as a gnutls_x509_dn structure.
- * Returns a negative error code in case of an error.
- *
- **/
-int gnutls_x509_extract_dn(const gnutls_datum * idn, gnutls_x509_dn * rdn)
-{
- ASN1_TYPE dn = ASN1_TYPE_EMPTY;
- int result;
- size_t len;
-
- if ((result =
- asn1_create_element(_gnutls_get_pkix(),
- "PKIX1.Name", &dn
- )) != ASN1_SUCCESS) {
- return _gnutls_asn2err(result);
- }
-
- result = asn1_der_decoding(&dn, idn->data, idn->size, NULL);
- if (result != ASN1_SUCCESS) {
- /* couldn't decode DER */
- asn1_delete_structure(&dn);
- return _gnutls_asn2err(result);
- }
-
- memset( rdn, 0, sizeof(gnutls_x509_dn));
-
- len = sizeof(rdn->country);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, rdn->country, &len);
-
- len = sizeof(rdn->organization);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, rdn->organization, &len);
-
- len = sizeof(rdn->organizational_unit_name);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, rdn->organizational_unit_name, &len);
-
- len = sizeof(rdn->common_name);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_COMMON_NAME, 0, 0, rdn->common_name, &len);
-
- len = sizeof(rdn->locality_name);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, rdn->locality_name, &len);
-
- len = sizeof(rdn->state_or_province_name);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, rdn->state_or_province_name, &len);
-
- len = sizeof(rdn->email);
- _gnutls_x509_parse_dn_oid( dn, "", GNUTLS_OID_PKCS9_EMAIL, 0, 0, rdn->email, &len);
-
- asn1_delete_structure(&dn);
-
- return 0;
-}
-
-/**
- * gnutls_x509_extract_certificate_dn - This function returns the certificate's distinguished name
- * @cert: should contain an X.509 DER encoded certificate
- * @ret: a pointer to a structure to hold the peer's name
- *
- * This function will return the name of the certificate holder. The name is gnutls_x509_dn structure and
- * is a obtained by the peer's certificate. If the certificate send by the
- * peer is invalid, or in any other failure this function returns error.
- * Returns a negative error code in case of an error.
- *
- **/
-int gnutls_x509_extract_certificate_dn(const gnutls_datum * cert,
- gnutls_x509_dn * ret)
-{
- gnutls_x509_crt xcert;
- int result;
- size_t len;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- len = sizeof( ret->country);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
- ret->country, &len);
-
- len = sizeof( ret->organization);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
- ret->organization, &len);
-
- len = sizeof( ret->organizational_unit_name);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
- ret->organizational_unit_name, &len);
-
- len = sizeof( ret->common_name);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
- ret->common_name, &len);
-
- len = sizeof( ret->locality_name);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
- ret->locality_name, &len);
-
- len = sizeof( ret->state_or_province_name);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
- ret->state_or_province_name, &len);
-
- len = sizeof( ret->email);
- gnutls_x509_crt_get_dn_by_oid( xcert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
- ret->email, &len);
-
- gnutls_x509_crt_deinit( xcert);
-
- return 0;
-}
-
-/**
- * gnutls_x509_extract_certificate_issuer_dn - This function returns the certificate's issuer distinguished name
- * @cert: should contain an X.509 DER encoded certificate
- * @ret: a pointer to a structure to hold the issuer's name
- *
- * This function will return the name of the issuer stated in the certificate. The name is a gnutls_x509_dn structure and
- * is a obtained by the peer's certificate. If the certificate send by the
- * peer is invalid, or in any other failure this function returns error.
- * Returns a negative error code in case of an error.
- *
- **/
-int gnutls_x509_extract_certificate_issuer_dn(const gnutls_datum * cert,
- gnutls_x509_dn * ret)
-{
- gnutls_x509_crt xcert;
- int result;
- size_t len;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- len = sizeof( ret->country);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
- ret->country, &len);
-
- len = sizeof( ret->organization);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
- ret->organization, &len);
-
- len = sizeof( ret->organizational_unit_name);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
- ret->organizational_unit_name, &len);
-
- len = sizeof( ret->common_name);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
- ret->common_name, &len);
-
- len = sizeof( ret->locality_name);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
- ret->locality_name, &len);
-
- len = sizeof( ret->state_or_province_name);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
- ret->state_or_province_name, &len);
-
- len = sizeof( ret->email);
- gnutls_x509_crt_get_issuer_dn_by_oid( xcert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
- ret->email, &len);
-
- gnutls_x509_crt_deinit( xcert);
-
- return 0;
-}
-
-
-/**
- * gnutls_x509_extract_certificate_subject_alt_name - This function returns the certificate's alternative name, if any
- * @cert: should contain an X.509 DER encoded certificate
- * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
- * @ret: is the place where the alternative name will be copied to
- * @ret_size: holds the size of ret.
- *
- * This function will return the alternative names, contained in the
- * given certificate.
- *
- * This is specified in X509v3 Certificate Extensions.
- * GNUTLS will return the Alternative name, or a negative
- * error code.
- * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the alternative
- * name, or the type of alternative name if everything was ok. The type is
- * one of the enumerated GNUTLS_X509_SUBJECT_ALT_NAME.
- *
- * If the certificate does not have an Alternative name with the specified
- * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- *
- **/
-int gnutls_x509_extract_certificate_subject_alt_name(const gnutls_datum * cert, int seq, char *ret, int *ret_size)
-{
- gnutls_x509_crt xcert;
- int result;
- size_t size = *ret_size;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- result = gnutls_x509_crt_get_subject_alt_name( xcert, seq, ret, &size, NULL);
- *ret_size = size;
-
- gnutls_x509_crt_deinit( xcert);
-
- return result;
-}
-
-/**
- * gnutls_x509_extract_certificate_ca_status - This function returns the certificate CA status
- * @cert: should contain an X.509 DER encoded certificate
- *
- * This function will return certificates CA status, by reading the
- * basicConstraints X.509 extension. If the certificate is a CA a positive
- * value will be returned, or zero if the certificate does not have
- * CA flag set.
- *
- * A negative value may be returned in case of parsing error.
- * If the certificate does not contain the basicConstraints extension
- * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
- *
- **/
-int gnutls_x509_extract_certificate_ca_status(const gnutls_datum * cert)
-{
- gnutls_x509_crt xcert;
- int result;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- result = gnutls_x509_crt_get_ca_status( xcert, NULL);
-
- gnutls_x509_crt_deinit( xcert);
-
- return result;
-}
-
-/**
* gnutls_x509_extract_certificate_activation_time - This function returns the peer's certificate activation time
* @cert: should contain an X.509 DER encoded certificate
*
@@ -298,7 +41,7 @@ int gnutls_x509_extract_certificate_ca_status(const gnutls_datum * cert)
* Returns a (time_t) -1 in case of an error.
*
**/
-time_t gnutls_x509_extract_certificate_activation_time(const
+time_t _gnutls_x509_get_raw_crt_activation_time(const
gnutls_datum *
cert)
{
@@ -330,7 +73,7 @@ time_t gnutls_x509_extract_certificate_activation_time(const
* Returns a (time_t) -1 in case of an error.
*
**/
-time_t gnutls_x509_extract_certificate_expiration_time(const
+time_t _gnutls_x509_get_raw_crt_expiration_time(const
gnutls_datum *
cert)
{
@@ -353,442 +96,3 @@ time_t gnutls_x509_extract_certificate_expiration_time(const
return result;
}
-/**
- * gnutls_x509_extract_certificate_version - This function returns the certificate's version
- * @cert: is an X.509 DER encoded certificate
- *
- * This function will return the X.509 certificate's version (1, 2, 3). This is obtained by the X509 Certificate
- * Version field. Returns a negative value in case of an error.
- *
- **/
-int gnutls_x509_extract_certificate_version(const gnutls_datum * cert)
-{
- gnutls_x509_crt xcert;
- int result;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- result = gnutls_x509_crt_get_version( xcert);
-
- gnutls_x509_crt_deinit( xcert);
-
- return result;
-
-}
-
-/**
- * gnutls_x509_extract_certificate_serial - This function returns the certificate's serial number
- * @cert: is an X.509 DER encoded certificate
- * @result: The place where the serial number will be copied
- * @result_size: Holds the size of the result field.
- *
- * This function will return the X.509 certificate's serial number.
- * This is obtained by the X509 Certificate serialNumber
- * field. Serial is not always a 32 or 64bit number. Some CAs use
- * large serial numbers, thus it may be wise to handle it as something
- * opaque.
- * Returns a negative value in case of an error.
- *
- **/
-int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* result, int* result_size)
-{
- gnutls_x509_crt xcert;
- size_t size = *result_size;
- int ret;
-
- ret = gnutls_x509_crt_init( &xcert);
- if (ret < 0) return ret;
-
- ret = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_x509_crt_deinit( xcert);
- return ret;
- }
-
- ret = gnutls_x509_crt_get_serial( xcert, result, &size);
- *result_size = size;
-
- gnutls_x509_crt_deinit( xcert);
-
- return ret;
-}
-
-
-/**
- * gnutls_x509_extract_certificate_pk_algorithm - This function returns the certificate's PublicKey algorithm
- * @cert: is a DER encoded X.509 certificate
- * @bits: if bits is non null it will hold the size of the parameters' in bits
- *
- * This function will return the public key algorithm of an X.509
- * certificate.
- *
- * If bits is non null, it should have enough size to hold the parameters
- * size in bits. For RSA the bits returned is the modulus.
- * For DSA the bits returned are of the public
- * exponent.
- *
- * Returns a member of the gnutls_pk_algorithm enumeration on success,
- * or a negative value on error.
- *
- **/
-int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int* bits)
-{
- gnutls_x509_crt xcert;
- int result;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- result = gnutls_x509_crt_get_pk_algorithm( xcert, bits);
-
- gnutls_x509_crt_deinit( xcert);
-
- return result;
-}
-
-
-/**
- * gnutls_x509_extract_certificate_dn_string - This function returns the certificate's distinguished name
- * @cert: should contain an X.509 DER encoded certificate
- * @buf: a pointer to a structure to hold the peer's name
- * @sizeof_buf: holds the size of 'buf'
- * @issuer: if non zero, then extract the name of the issuer, instead of the holder
- *
- * This function will copy the name of the certificate holder in the provided buffer. The name
- * will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253.
- *
- * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough,
- * and 0 on success.
- *
- **/
-int gnutls_x509_extract_certificate_dn_string(char *buf, unsigned int sizeof_buf,
- const gnutls_datum * cert, int issuer)
-{
- gnutls_x509_crt xcert;
- int result;
-
- result = gnutls_x509_crt_init( &xcert);
- if (result < 0) return result;
-
- result = gnutls_x509_crt_import( xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit( xcert);
- return result;
- }
-
- if (!issuer)
- result = gnutls_x509_crt_get_dn( xcert, buf, &sizeof_buf);
- else
- result = gnutls_x509_crt_get_issuer_dn( xcert, buf, &sizeof_buf);
-
- gnutls_x509_crt_deinit( xcert);
-
- return result;
-}
-
-/**
- * gnutls_x509_verify_certificate - This function verifies given certificate list
- * @cert_list: is the certificate list to be verified
- * @cert_list_length: holds the number of certificate in cert_list
- * @CA_list: is the CA list which will be used in verification
- * @CA_list_length: holds the number of CA certificate in CA_list
- * @CRL_list: not used
- * @CRL_list_length: not used
- *
- * This function will try to verify the given certificate list and return its status (TRUSTED, EXPIRED etc.).
- * The return value (status) should be one or more of the gnutls_certificate_status
- * enumerated elements bitwise or'd. Note that expiration and activation dates are not checked
- * by this function, you should check them using the appropriate functions.
- *
- * This function understands the basicConstraints (2.5.29.19) PKIX extension.
- * This means that only a certificate authority can sign a certificate.
- *
- * However you must also check the peer's name in order to check if the verified certificate belongs to the
- * actual peer.
- *
- * The return value (status) should be one or more of the gnutls_certificate_status
- * enumerated elements bitwise or'd.
- *
- * GNUTLS_CERT_INVALID\: the peer's certificate is not valid.
- *
- * GNUTLS_CERT_REVOKED\: the certificate has been revoked.
- *
- * A negative error code is returned in case of an error.
- * GNUTLS_E_NO_CERTIFICATE_FOUND is returned to indicate that
- * no certificate was sent by the peer.
- *
- *
- **/
-int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list_length,
- const gnutls_datum * CA_list, int CA_list_length,
- const gnutls_datum* CRL_list, int CRL_list_length)
-{
- unsigned int verify;
- gnutls_x509_crt *peer_certificate_list = NULL;
- gnutls_x509_crt *ca_certificate_list = NULL;
- gnutls_x509_crl *crl_list = NULL;
- int peer_certificate_list_size=0, i, x, ret;
- int ca_certificate_list_size=0, crl_list_size=0;
-
- if (cert_list == NULL || cert_list_length == 0)
- return GNUTLS_E_NO_CERTIFICATE_FOUND;
-
- /* generate a list of gnutls_certs based on the auth info
- * raw certs.
- */
- peer_certificate_list_size = cert_list_length;
- peer_certificate_list =
- gnutls_calloc(1,
- peer_certificate_list_size *
- sizeof(gnutls_x509_crt));
- if (peer_certificate_list == NULL) {
- gnutls_assert();
- ret = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- ca_certificate_list_size = CA_list_length;
- ca_certificate_list =
- gnutls_calloc(1,
- ca_certificate_list_size *
- sizeof(gnutls_x509_crt));
- if (ca_certificate_list == NULL) {
- gnutls_assert();
- ret = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- /* allocate memory for CRL
- */
- crl_list_size = CRL_list_length;
- crl_list =
- gnutls_calloc(1,
- crl_list_size *
- sizeof(gnutls_x509_crl));
- if (crl_list == NULL) {
- gnutls_assert();
- ret = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- /* convert certA_list to gnutls_cert* list
- */
- for (i = 0; i < peer_certificate_list_size; i++) {
- ret = gnutls_x509_crt_init( &peer_certificate_list[i]);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- gnutls_x509_crt_import(peer_certificate_list[i],
- &cert_list[i], GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
- }
-
- /* convert CA_list to gnutls_x509_cert* list
- */
- for (i = 0; i < ca_certificate_list_size; i++) {
- ret = gnutls_x509_crt_init(&ca_certificate_list[i]);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- gnutls_x509_crt_import(ca_certificate_list[i],
- &CA_list[i], GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
- }
-
-#ifdef ENABLE_PKI
- /* convert CRL_list to gnutls_x509_crl* list
- */
- for (i = 0; i < crl_list_size; i++) {
- ret = gnutls_x509_crl_init( &crl_list[i]);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- gnutls_x509_crl_import(crl_list[i],
- &CRL_list[i], GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
- }
-#endif
-
- /* Verify certificate
- */
- ret =
- gnutls_x509_crt_list_verify(peer_certificate_list,
- peer_certificate_list_size,
- ca_certificate_list, ca_certificate_list_size,
- crl_list, crl_list_size, 0, &verify);
-
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret = verify;
-
- cleanup:
-
- if (peer_certificate_list != NULL)
- for(x=0;x<peer_certificate_list_size;x++) {
- if (peer_certificate_list[x] != NULL)
- gnutls_x509_crt_deinit(peer_certificate_list[x]);
- }
-
- if (ca_certificate_list != NULL)
- for(x=0;x<ca_certificate_list_size;x++) {
- if (ca_certificate_list[x] != NULL)
- gnutls_x509_crt_deinit(ca_certificate_list[x]);
- }
-
-#ifdef ENABLE_PKI
- if (crl_list != NULL)
- for(x=0;x<crl_list_size;x++) {
- if (crl_list[x] != NULL)
- gnutls_x509_crl_deinit(crl_list[x]);
- }
-
- gnutls_free( crl_list);
-#endif
-
- gnutls_free( ca_certificate_list);
- gnutls_free( peer_certificate_list);
-
- return ret;
-}
-
-/**
- * gnutls_x509_extract_key_pk_algorithm - This function returns the keys's PublicKey algorithm
- * @cert: is a DER encoded private key
- *
- * This function will return the public key algorithm of a DER encoded private
- * key.
- *
- * Returns a member of the gnutls_pk_algorithm enumeration on success,
- * or GNUTLS_E_UNKNOWN_PK_ALGORITHM on error.
- *
- **/
-int gnutls_x509_extract_key_pk_algorithm( const gnutls_datum * key)
-{
- gnutls_x509_privkey pkey;
- int ret, pk;
-
- ret = gnutls_x509_privkey_init( &pkey);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- ret = gnutls_x509_privkey_import( pkey, key, GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- pk = gnutls_x509_privkey_get_pk_algorithm( pkey);
-
- gnutls_x509_privkey_deinit( pkey);
- return pk;
-}
-
-#ifdef ENABLE_PKI
-
-/**
- * gnutls_x509_pkcs7_extract_certificate - This function returns a certificate in a PKCS7 certificate set
- * @pkcs7_struct: should contain a PKCS7 DER formatted structure
- * @indx: contains the index of the certificate to extract
- * @certificate: the contents of the certificate will be copied there
- * @certificate_size: should hold the size of the certificate
- *
- * This function will return a certificate of the PKCS7 or RFC2630 certificate set.
- * Returns 0 on success. If the provided buffer is not long enough,
- * then GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
- *
- * After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
- * will be returned.
- *
- **/
-int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size)
-{
- gnutls_pkcs7 pkcs7;
- int result;
- size_t size = *certificate_size;
-
- result = gnutls_pkcs7_init( &pkcs7);
- if (result < 0) return result;
-
- result = gnutls_pkcs7_import( pkcs7, pkcs7_struct, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_pkcs7_deinit( pkcs7);
- return result;
- }
-
- result = gnutls_pkcs7_get_crt_raw( pkcs7, indx, certificate, &size);
- *certificate_size = size;
-
- gnutls_pkcs7_deinit( pkcs7);
-
- return result;
-}
-
-
-/**
- * gnutls_x509_pkcs7_extract_certificate_count - This function returns the number of certificates in a PKCS7 certificate set
- * @pkcs7_struct: should contain a PKCS7 DER formatted structure
- *
- * This function will return the number of certifcates in the PKCS7 or
- * RFC2630 certificate set.
- *
- * Returns a negative value on failure.
- *
- **/
-int gnutls_x509_pkcs7_extract_certificate_count(const gnutls_datum * pkcs7_struct)
-{
- gnutls_pkcs7 pkcs7;
- int result;
-
- result = gnutls_pkcs7_init( &pkcs7);
- if (result < 0) return result;
-
- result = gnutls_pkcs7_import( pkcs7, pkcs7_struct, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_pkcs7_deinit( pkcs7);
- return result;
- }
-
- result = gnutls_pkcs7_get_crt_count( pkcs7);
-
- gnutls_pkcs7_deinit( pkcs7);
-
- return result;
-}
-
-#endif
diff --git a/lib/x509/compat.h b/lib/x509/compat.h
index 7e60f131db..4e9a0f5e13 100644
--- a/lib/x509/compat.h
+++ b/lib/x509/compat.h
@@ -1,10 +1,2 @@
-#include <gnutls/compat8.h>
-
-time_t gnutls_x509_extract_certificate_activation_time( const gnutls_datum*);
-time_t gnutls_x509_extract_certificate_expiration_time( const gnutls_datum*);
-
-int gnutls_x509_extract_certificate_subject_alt_name( const gnutls_datum*, int seq, char*, int*);
-int gnutls_x509_extract_certificate_dn( const gnutls_datum*, gnutls_x509_dn*);
-
-int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size);
-int gnutls_x509_pkcs7_extract_certificate_count(const gnutls_datum * pkcs7_struct);
+time_t _gnutls_x509_get_raw_crt_activation_time( const gnutls_datum*);
+time_t _gnutls_x509_get_raw_crt_expiration_time( const gnutls_datum*);
diff --git a/lib/x509/x509.h b/lib/x509/x509.h
index ee5c949e1a..341baf0ecb 100644
--- a/lib/x509/x509.h
+++ b/lib/x509/x509.h
@@ -64,6 +64,11 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
unsigned int seq, void *ret, size_t *ret_size, unsigned int* critical);
int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf);
+int gnutls_x509_crt_get_dn(gnutls_x509_crt cert, char *buf,
+ size_t *sizeof_buf);
+int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt cert, char *buf,
+ size_t *sizeof_buf);
+
int gnutls_x509_crt_get_ca_status(gnutls_x509_crt cert, unsigned int* critical);
int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits);
@@ -137,4 +142,7 @@ int gnutls_x509_privkey_export( gnutls_x509_privkey key,
#define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1
#define GNUTLS_CRL_REASON_AA_COMPROMISE 32768
+time_t gnutls_x509_crt_get_activation_time(gnutls_x509_crt cert);
+time_t gnutls_x509_crt_get_expiration_time(gnutls_x509_crt cert);
+
#endif
diff --git a/lib/x509_b64.c b/lib/x509_b64.c
index 7156bd2fb9..234ca13c1a 100644
--- a/lib/x509_b64.c
+++ b/lib/x509_b64.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000,2001,2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -163,12 +164,14 @@ int _gnutls_base64_encode(const uint8 * data, size_t data_size, uint8 ** result)
}
#define INCR(what, size) \
+ do { \
what+=size; \
if (what > ret) { \
gnutls_assert(); \
gnutls_free( (*result)); *result = NULL; \
return GNUTLS_E_INTERNAL_ERROR; \
- }
+ } \
+ } while(0)
/* encodes data and puts the result into result (locally allocated)
* The result_size (including the null terminator) is the return value.
diff --git a/libextra/Makefile.am b/libextra/Makefile.am
index 0a28bb78b2..0db520f996 100644
--- a/libextra/Makefile.am
+++ b/libextra/Makefile.am
@@ -43,7 +43,7 @@ libgnutls_extra_la_DEPENDENCIES = $(LZO_OBJECTS)
libgnutls_extra_la_SOURCES = $(COBJECTS_EXTRA)
libgnutls_extra_la_LIBADD = $(LZO_OBJECTS) \
- openpgp/openpgp.lo openpgp/xml.lo \
+ openpgp/openpgp.lo openpgp/xml.lo openpgp/privkey.lo \
openpgp/extras.lo openpgp/verify.lo openpgp/compat.lo \
../lib/libgnutls.la
diff --git a/libextra/auth_srp.c b/libextra/auth_srp.c
index 424dcc85eb..fb2d20043f 100644
--- a/libextra/auth_srp.c
+++ b/libextra/auth_srp.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -67,8 +68,67 @@ const MOD_AUTH_STRUCT srp_auth_struct = {
#define V session->key->x
#define S session->key->KEY
+/* Checks if b%n==0 which is a fatal srp error.
+ * Returns a proper error code in that case, and 0 when
+ * all are ok.
+ */
+inline
+static int check_b_mod_n( GNUTLS_MPI b, GNUTLS_MPI n)
+{
+int ret;
+GNUTLS_MPI r = _gnutls_mpi_alloc_like(b);
+
+ if (r == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_mpi_mod( r, b, n);
+ ret = _gnutls_mpi_cmp_ui(r, 0);
+
+ _gnutls_mpi_release( &r);
+
+ if (ret == 0) {
+ gnutls_assert();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ return 0;
+}
+
+/* Checks if a%n==0,+1,-1%n which is a fatal srp error.
+ * Returns a proper error code in that case, and 0 when
+ * all are ok.
+ */
inline
-static int check_a_mod_n( GNUTLS_MPI a, GNUTLS_MPI n);
+static int check_a_mod_n( GNUTLS_MPI a, GNUTLS_MPI n)
+{
+int ret;
+GNUTLS_MPI r = _gnutls_mpi_alloc_like(a);
+
+ if (r == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_mpi_mod( r, a, n);
+ ret = _gnutls_mpi_cmp_ui(r, 0);
+ if (ret != 0) ret = _gnutls_mpi_cmp_ui(r, 1);
+ if (ret != 0) {
+ _gnutls_mpi_sub_ui( r, n, 1);
+ ret = _gnutls_mpi_cmp(a, r);
+ }
+
+ _gnutls_mpi_release( &r);
+
+ if (ret == 0) {
+ gnutls_assert();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ return 0;
+}
+
/* 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.
@@ -297,7 +357,10 @@ int _gnutls_proc_srp_client_kx(gnutls_session session, opaque * data, size_t _da
gnutls_assert();
return GNUTLS_E_MPI_SCAN_FAILED;
}
-
+
+ _gnutls_dump_mpi( "SRP A: ", A);
+ _gnutls_dump_mpi( "SRP B: ", B);
+
/* Checks if A % n == 0 or
* A % n == +-1.
*/
@@ -306,9 +369,6 @@ int _gnutls_proc_srp_client_kx(gnutls_session session, opaque * data, size_t _da
return ret;
}
- _gnutls_dump_mpi( "SRP A: ", A);
- _gnutls_dump_mpi( "SRP B: ", B);
-
/* Start the SRP calculations.
* - Calculate u
*/
@@ -348,65 +408,6 @@ int _gnutls_proc_srp_client_kx(gnutls_session session, opaque * data, size_t _da
}
-/* Checks if b%n==0 which is a fatal srp error.
- * Returns a proper error code in that case, and 0 when
- * all are ok.
- */
-static int check_b_mod_n( GNUTLS_MPI b, GNUTLS_MPI n)
-{
-int ret;
-GNUTLS_MPI r = _gnutls_mpi_alloc_like(b);
-
- if (r == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- _gnutls_mpi_mod( r, b, n);
- ret = _gnutls_mpi_cmp_ui(r, 0);
-
- _gnutls_mpi_release( &r);
-
- if (ret == 0) {
- gnutls_assert();
- return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
- }
-
- return 0;
-}
-
-/* Checks if a%n==0,+1,-1%n which is a fatal srp error.
- * Returns a proper error code in that case, and 0 when
- * all are ok.
- */
-inline
-static int check_a_mod_n( GNUTLS_MPI a, GNUTLS_MPI n)
-{
-int ret;
-GNUTLS_MPI r = _gnutls_mpi_alloc_like(a);
-
- if (r == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- _gnutls_mpi_mod( r, a, n);
- ret = _gnutls_mpi_cmp_ui(r, 0);
- if (ret != 0) ret = _gnutls_mpi_cmp_ui(r, 1);
- if (ret != 0) {
- _gnutls_mpi_sub_ui( r, n, 1);
- ret = _gnutls_mpi_cmp(a, r);
- }
-
- _gnutls_mpi_release( &r);
-
- if (ret == 0) {
- gnutls_assert();
- return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
- }
-
- return 0;
-}
/* Static parameters according to draft-ietf-tls-srp-05
*/
diff --git a/libextra/auth_srp_passwd.c b/libextra/auth_srp_passwd.c
index 67cdaf1732..580cc7f438 100644
--- a/libextra/auth_srp_passwd.c
+++ b/libextra/auth_srp_passwd.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/libextra/auth_srp_rsa.c b/libextra/auth_srp_rsa.c
index 4d05a06525..561465d71f 100644
--- a/libextra/auth_srp_rsa.c
+++ b/libextra/auth_srp_rsa.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -100,7 +101,7 @@ int apr_cert_list_length;
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -132,8 +133,6 @@ int apr_cert_list_length;
}
-extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
-
static int proc_srp_cert_server_kx(gnutls_session session, opaque * data, size_t _data_size)
{
ssize_t ret;
@@ -170,32 +169,12 @@ opaque* p;
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_raw_cert_to_gcert( &peer_cert, session->security_parameters.cert_type,
+ &info->raw_certificate_list[0], CERT_NO_COPY);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
}
ret =
@@ -203,7 +182,7 @@ opaque* p;
&peer_cert,
&vparams, &signature);
- _gnutls_free_cert( &peer_cert);
+ _gnutls_gcert_deinit( &peer_cert);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/libextra/auth_srp_sb64.c b/libextra/auth_srp_sb64.c
index 9011ec1843..db8edb65b7 100644
--- a/libextra/auth_srp_sb64.c
+++ b/libextra/auth_srp_sb64.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/libextra/ext_srp.c b/libextra/ext_srp.c
index a9460a1e7d..2624b965b1 100644
--- a/libextra/ext_srp.c
+++ b/libextra/ext_srp.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2002 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c
index 2e2c27c3a8..1bda1681aa 100644
--- a/libextra/gnutls_extra.c
+++ b/libextra/gnutls_extra.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -75,6 +76,8 @@ int i;
_gnutls_kx_algorithms[i].name = "SRP";
_gnutls_kx_algorithms[i].algorithm = GNUTLS_KX_SRP;
_gnutls_kx_algorithms[i].auth_struct = &srp_auth_struct;
+ _gnutls_kx_algorithms[i].needs_dh_params = 0;
+ _gnutls_kx_algorithms[i].needs_rsa_params = 0;
_gnutls_kx_algorithms[i+1].name = 0;
}
i++;
@@ -83,6 +86,8 @@ int i;
_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].needs_dh_params = 0;
+ _gnutls_kx_algorithms[i].needs_rsa_params = 0;
_gnutls_kx_algorithms[i+1].name = 0;
}
i++;
@@ -91,6 +96,8 @@ int i;
_gnutls_kx_algorithms[i].name = "SRP DSS";
_gnutls_kx_algorithms[i].algorithm = GNUTLS_KX_SRP_DSS;
_gnutls_kx_algorithms[i].auth_struct = &srp_dss_auth_struct;
+ _gnutls_kx_algorithms[i].needs_dh_params = 0;
+ _gnutls_kx_algorithms[i].needs_rsa_params = 0;
_gnutls_kx_algorithms[i+1].name = 0;
return 0; /* ok */
@@ -143,21 +150,35 @@ int i;
}
-extern OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_extract_key_creation_time;
-extern OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_extract_key_expiration_time;
+extern OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_get_raw_key_creation_time;
+extern OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_get_raw_key_expiration_time;
extern OPENPGP_VERIFY_KEY_FUNC _E_gnutls_openpgp_verify_key;
-extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert;
extern OPENPGP_FINGERPRINT _E_gnutls_openpgp_fingerprint;
extern OPENPGP_KEY_REQUEST _E_gnutls_openpgp_request_key;
+extern OPENPGP_RAW_KEY_TO_GCERT _E_gnutls_openpgp_raw_key_to_gcert;
+extern OPENPGP_RAW_PRIVKEY_TO_GKEY _E_gnutls_openpgp_raw_privkey_to_gkey;
+
+extern OPENPGP_KEY_TO_GCERT _E_gnutls_openpgp_key_to_gcert;
+extern OPENPGP_PRIVKEY_TO_GKEY _E_gnutls_openpgp_privkey_to_gkey;
+extern OPENPGP_KEY_DEINIT _E_gnutls_openpgp_key_deinit;
+extern OPENPGP_PRIVKEY_DEINIT _E_gnutls_openpgp_privkey_deinit;
+
static void _gnutls_add_openpgp_functions(void) {
#ifdef HAVE_LIBOPENCDK
- _E_gnutls_openpgp_verify_key = gnutls_openpgp_verify_key;
- _E_gnutls_openpgp_extract_key_expiration_time = gnutls_openpgp_extract_key_expiration_time;
- _E_gnutls_openpgp_extract_key_creation_time = gnutls_openpgp_extract_key_creation_time;
- _E_gnutls_openpgp_fingerprint = gnutls_openpgp_fingerprint;
+ _E_gnutls_openpgp_verify_key = _gnutls_openpgp_verify_key;
+ _E_gnutls_openpgp_get_raw_key_expiration_time = _gnutls_openpgp_get_raw_key_expiration_time;
+ _E_gnutls_openpgp_get_raw_key_creation_time = _gnutls_openpgp_get_raw_key_creation_time;
+ _E_gnutls_openpgp_fingerprint = _gnutls_openpgp_fingerprint;
_E_gnutls_openpgp_request_key = _gnutls_openpgp_request_key;
- _E_gnutls_openpgp_cert2gnutls_cert = _gnutls_openpgp_cert2gnutls_cert;
+
+ _E_gnutls_openpgp_raw_key_to_gcert = _gnutls_openpgp_raw_key_to_gcert;
+ _E_gnutls_openpgp_raw_privkey_to_gkey = _gnutls_openpgp_raw_privkey_to_gkey;
+
+ _E_gnutls_openpgp_key_to_gcert = _gnutls_openpgp_key_to_gcert;
+ _E_gnutls_openpgp_privkey_to_gkey = _gnutls_openpgp_privkey_to_gkey;
+ _E_gnutls_openpgp_key_deinit = gnutls_openpgp_key_deinit;
+ _E_gnutls_openpgp_privkey_deinit = gnutls_openpgp_privkey_deinit;
#endif
}
@@ -272,7 +293,7 @@ parse_version_string( const char *s, int *major, int *minor, int *micro )
}
/****************
- * Check that the the version of the library is at minimum the requested one
+ * Check that the version of the library is at minimum the requested one
* and return the version string; return NULL if the condition is not
* satisfied. If a NULL is passed to this function, no check is done,
* but the version string is simply returned.
diff --git a/libextra/gnutls_extra.h b/libextra/gnutls_extra.h
index a458512b9d..40aef209d2 100644
--- a/libextra/gnutls_extra.h
+++ b/libextra/gnutls_extra.h
@@ -7,4 +7,12 @@ typedef time_t (*OPENPGP_KEY_EXPIRATION_TIME_FUNC)( const gnutls_datum*);
typedef int (*OPENPGP_KEY_REQUEST)(gnutls_session, gnutls_datum*,
const gnutls_certificate_credentials, opaque*,int);
typedef int (*OPENPGP_FINGERPRINT)(const gnutls_datum*, unsigned char*, size_t*);
-typedef int (*OPENPGP_CERT2GNUTLS_CERT)(gnutls_cert*, const gnutls_datum*);
+
+typedef int (*OPENPGP_RAW_KEY_TO_GCERT)(gnutls_cert*, const gnutls_datum*);
+typedef int (*OPENPGP_RAW_PRIVKEY_TO_GKEY)(gnutls_privkey*, const gnutls_datum*);
+
+typedef int (*OPENPGP_KEY_TO_GCERT)(gnutls_cert*, gnutls_openpgp_key);
+typedef int (*OPENPGP_PRIVKEY_TO_GKEY)(gnutls_privkey*, gnutls_openpgp_privkey);
+
+typedef void (*OPENPGP_KEY_DEINIT)(gnutls_openpgp_key);
+typedef void (*OPENPGP_PRIVKEY_DEINIT)(gnutls_openpgp_privkey);
diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c
index b307e42783..e510fbda72 100644
--- a/libextra/gnutls_openpgp.c
+++ b/libextra/gnutls_openpgp.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Timo Schulz <twoaday@freakmail.de>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -24,11 +25,9 @@
#include "gnutls_cert.h"
#include "gnutls_datum.h"
#include "gnutls_global.h"
-#include "auth_cert.h"
#include <openpgp/gnutls_openpgp.h>
#ifdef HAVE_LIBOPENCDK
-#include <gnutls/compat8.h>
#include <strfile.h>
#include <gnutls_str.h>
#include <stdio.h>
@@ -218,11 +217,10 @@ kbx_data_to_keyring( int type, int enc, const char *data,
}
-CDK_PACKET*
-search_packet( const gnutls_datum *buf, int pkttype )
+cdk_packet_t search_packet( const gnutls_datum *buf, int pkttype )
{
static cdk_kbnode_t knode = NULL;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
if( !buf && !pkttype ) {
cdk_kbnode_release( knode );
@@ -283,19 +281,21 @@ openpgp_pk_to_gnutls_cert( gnutls_cert *cert, cdk_pkt_pubkey_t pk )
}
/*-
- * _gnutls_openpgp_key2gnutls_key - Converts an OpenPGP secret key to GnuTLS
+ * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS
* @pkey: the GnuTLS private key context to store the key.
* @raw_key: the raw data which contains the whole key packets.
*
* The RFC2440 (OpenPGP Message Format) data is converted into the
* GnuTLS specific data which is need to perform secret key operations.
+ *
+ * This function can read both BASE64 and RAW keys.
-*/
int
-_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- gnutls_datum *raw_key )
+_gnutls_openpgp_raw_privkey_to_gkey( gnutls_privkey *pkey,
+ const gnutls_datum *raw_key)
{
cdk_kbnode_t snode;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
cdk_stream_t out;
cdk_pkt_seckey_t sk = NULL;
int pke_algo, i, j;
@@ -311,6 +311,7 @@ _gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
out = cdk_stream_tmp( );
if( !out )
return GNUTLS_E_CERTIFICATE_ERROR;
+
cdk_stream_write( out, raw_key->data, raw_key->size );
cdk_stream_seek( out, 0 );
@@ -365,7 +366,7 @@ leave:
/*-
- * _gnutls_openpgp_cert2gnutls_cert - Converts raw OpenPGP data to GnuTLS certs
+ * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs
* @cert: the certificate to store the data.
* @raw: the buffer which contains the whole OpenPGP key packets.
*
@@ -373,10 +374,10 @@ leave:
* specific certificate.
-*/
int
-_gnutls_openpgp_cert2gnutls_cert( gnutls_cert *cert, const gnutls_datum *raw )
+_gnutls_openpgp_raw_key_to_gcert( gnutls_cert *cert, const gnutls_datum *raw )
{
cdk_kbnode_t knode = NULL;
- CDK_PACKET *pkt = NULL;
+ cdk_packet_t pkt = NULL;
int rc;
if( !cert ) {
@@ -519,12 +520,11 @@ stream_to_datum( cdk_stream_t inp, gnutls_datum *raw )
**/
int
gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
- const gnutls_datum *cert,
- const gnutls_datum *key )
+ const gnutls_datum *cert, const gnutls_datum *key )
{
gnutls_datum raw;
cdk_kbnode_t knode = NULL, ctx = NULL, p;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
int i = 0;
int rc = 0;
cdk_stream_t inp = NULL;
@@ -540,8 +540,9 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
return GNUTLS_E_INTERNAL_ERROR;
}
- if( cdk_armor_filter_use( inp ) )
+ if( cdk_armor_filter_use( inp ) ) {
cdk_stream_set_armor_flag( inp, 0 );
+ }
res->cert_list = gnutls_realloc_fast(res->cert_list,
(1+res->ncerts)*sizeof(gnutls_cert*));
@@ -626,7 +627,7 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
}
cdk_stream_close( inp );
- rc = _gnutls_openpgp_key2gnutls_key( &res->pkey[res->ncerts-1], &raw );
+ rc = _gnutls_openpgp_raw_privkey_to_gkey( &res->pkey[res->ncerts-1], &raw);
if (rc) {
gnutls_assert();
}
@@ -708,7 +709,7 @@ int
gnutls_openpgp_count_key_names( const gnutls_datum *cert )
{
cdk_kbnode_t knode, p, ctx = NULL;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
int nuids = 0;
if( cert == NULL ) {
@@ -1006,5 +1007,142 @@ void gnutls_openpgp_set_recv_key_function( gnutls_session session,
session->internals.openpgp_recv_key_func = func;
}
+/* Copies a gnutls_openpgp_privkey to a gnutls_privkey structure.
+ */
+int _gnutls_openpgp_privkey_to_gkey( gnutls_privkey* dest, gnutls_openpgp_privkey src)
+{
+int i, ret;
+
+ memset( dest, 0, sizeof(gnutls_privkey));
+
+ for(i=0;i<src->pkey.params_size;i++) {
+ dest->params[i] = _gnutls_mpi_copy( src->pkey.params[i]);
+ if (dest->params[i] == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+ }
+
+ dest->pk_algorithm = src->pkey.pk_algorithm;
+ dest->params_size = src->pkey.params_size;
+
+ return 0;
+
+cleanup:
+ for (i=0;i<src->pkey.params_size;i++) {
+ _gnutls_mpi_release( &dest->params[i]);
+ }
+ return ret;
+}
+
+/* Converts a parsed gnutls_openpgp_key to a gnutls_cert structure.
+ */
+int _gnutls_openpgp_key_to_gcert(gnutls_cert * gcert, gnutls_openpgp_key cert)
+{
+ int ret = 0;
+ opaque* der;
+ size_t der_size = 0;
+ gnutls_datum raw;
+
+ memset(gcert, 0, sizeof(gnutls_cert));
+ gcert->cert_type = GNUTLS_CRT_OPENPGP;
+
+
+ ret = gnutls_openpgp_key_export( cert, GNUTLS_OPENPGP_FMT_RAW, NULL, &der_size);
+ if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ gnutls_assert();
+ return ret;
+ }
+
+ der = gnutls_malloc( der_size);
+ if (der == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret = gnutls_openpgp_key_export( cert, GNUTLS_OPENPGP_FMT_RAW, der, &der_size);
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_free(der);
+ return ret;
+ }
+
+ raw.data = der;
+ raw.size = der_size;
+
+ ret = _gnutls_openpgp_raw_key_to_gcert( gcert, &raw);
+
+ gnutls_free(der);
+
+ return 0;
+
+}
+
+/**
+ * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials structure
+ * @res: is an &gnutls_certificate_credentials structure.
+ * @key: contains an openpgp public key
+ * @pkey: is an openpgp private key
+ *
+ * This function sets a certificate/private key pair in the
+ * gnutls_certificate_credentials structure. This function may be called
+ * more than once (in case multiple keys/certificates exist for the
+ * server).
+ *
+ **/
+int gnutls_certificate_set_openpgp_key(gnutls_certificate_credentials res,
+ gnutls_openpgp_key key,
+ gnutls_openpgp_privkey pkey)
+{
+ int ret;
+
+ /* this should be first
+ */
+
+ res->pkey = gnutls_realloc_fast( res->pkey, (res->ncerts+1)*sizeof(gnutls_privkey));
+ if (res->pkey==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret = _gnutls_openpgp_privkey_to_gkey( &res->pkey[res->ncerts], pkey);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ res->cert_list = gnutls_realloc_fast( res->cert_list,
+ (1+ res->ncerts)*sizeof(gnutls_cert*));
+ if ( res->cert_list==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list_length = gnutls_realloc_fast( res->cert_list_length,
+ (1+ res->ncerts)*sizeof(int));
+ if (res->cert_list_length==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list[res->ncerts] = NULL; /* for realloc */
+ res->cert_list_length[res->ncerts] = 1;
+
+ ret = _gnutls_openpgp_key_to_gcert( res->cert_list[res->ncerts], key);
+ if ( ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ res->ncerts++;
+
+ /* FIXME: Check if they match.
+ */
+
+ return 0;
+}
+
+
#endif /* HAVE_LIBOPENCDK */
diff --git a/libextra/gnutls_openssl.c b/libextra/gnutls_openssl.c
index 558502bae6..683ec02b01 100644
--- a/libextra/gnutls_openssl.c
+++ b/libextra/gnutls_openssl.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2002 Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (C) 2004 Free Software Foundation
*
* 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
@@ -19,6 +20,7 @@
#include <config.h>
#include <gnutls/gnutls.h>
+#include <gnutls/compat8.h>
#include <gcrypt.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/libextra/gnutls_srp.c b/libextra/gnutls_srp.c
index 6807407950..4b5d34b09d 100644
--- a/libextra/gnutls_srp.c
+++ b/libextra/gnutls_srp.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2001,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -371,7 +372,8 @@ int gnutls_srp_allocate_client_credentials( gnutls_srp_client_credentials *sc) {
* @password: is the user's password
*
* This function sets the username and password, in a gnutls_srp_client_credentials structure.
- * Those will be used in SRP authentication.
+ * Those will be used in SRP authentication. @username and @password should be ASCII
+ * strings or UTF-8 strings prepared using the "SASLprep" profile of "stringprep".
*
* Returns 0 on success.
**/
@@ -528,7 +530,7 @@ int i;
*
* This function specifies what we, in case of a server, are going
* to do when we have to use a password file. If this callback
- * function is not provided then gnutls will automaticaly select the
+ * function is not provided then gnutls will automatically select the
* first password file
*
* In case the callback returned a negative number then gnutls will
@@ -594,6 +596,8 @@ void gnutls_srp_set_server_credentials_function(
*
* The @username and @password must be allocated using gnutls_malloc().
* @times will be 0 the first time called, and 1 the second.
+ * @username and @password should be ASCII strings or UTF-8 strings
+ * prepared using the "SASLprep" profile of "stringprep".
*
* The callback function will be called once or twice per handshake.
* The first time called, is before the ciphersuite is negotiated.
diff --git a/libextra/openpgp/Makefile.am b/libextra/openpgp/Makefile.am
index 174cd01262..aa7f7440c0 100644
--- a/libextra/openpgp/Makefile.am
+++ b/libextra/openpgp/Makefile.am
@@ -3,7 +3,7 @@ EXTRA_DIST = openpgp.h gnutls_openpgp.h
noinst_LTLIBRARIES = libpgp.la
-COBJECTS = openpgp.c xml.c verify.c extras.c compat.c
+COBJECTS = openpgp.c xml.c verify.c extras.c compat.c privkey.c
libpgp_la_SOURCES = $(COBJECTS)
diff --git a/libextra/openpgp/compat.c b/libextra/openpgp/compat.c
index 4faef21985..96386d9e0f 100644
--- a/libextra/openpgp/compat.c
+++ b/libextra/openpgp/compat.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 Timo Schulz
* Portions Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright 2004 Free Software Foundation
*
* This file is part of GNUTLS-EXTRA.
*
@@ -48,7 +49,7 @@
* NOTE: this function does not verify using any "web of trust". You
* may use GnuPG for that purpose, or any other external PGP application.
-*/
-int gnutls_openpgp_verify_key(const char *trustdb,
+int _gnutls_openpgp_verify_key(const char *trustdb,
const gnutls_datum * keyring,
const gnutls_datum * cert_list,
int cert_list_length)
@@ -148,7 +149,7 @@ leave:
* Returns the fingerprint of the OpenPGP key. Depence on the algorithm,
* the fingerprint can be 16 or 20 bytes.
-*/
-int gnutls_openpgp_fingerprint(const gnutls_datum * cert,
+int _gnutls_openpgp_fingerprint(const gnutls_datum * cert,
unsigned char *fpr, size_t * fprlen)
{
gnutls_openpgp_key key;
@@ -178,12 +179,12 @@ int gnutls_openpgp_fingerprint(const gnutls_datum * cert,
}
/*-
- * gnutls_openpgp_extract_key_creation_time - Extract the timestamp
+ * gnutls_openpgp_get_raw_key_creation_time - Extract the timestamp
* @cert: the raw data that contains the OpenPGP public key.
*
* Returns the timestamp when the OpenPGP key was created.
-*/
-time_t gnutls_openpgp_extract_key_creation_time(const gnutls_datum * cert)
+time_t _gnutls_openpgp_get_raw_key_creation_time(const gnutls_datum * cert)
{
gnutls_openpgp_key key;
int ret;
@@ -210,13 +211,13 @@ time_t gnutls_openpgp_extract_key_creation_time(const gnutls_datum * cert)
/*-
- * gnutls_openpgp_extract_key_expiration_time - Extract the expire date
+ * gnutls_openpgp_get_raw_key_expiration_time - Extract the expire date
* @cert: the raw data that contains the OpenPGP public key.
*
* Returns the time when the OpenPGP key expires. A value of '0' means
* that the key doesn't expire at all.
-*/
-time_t gnutls_openpgp_extract_key_expiration_time(const gnutls_datum * cert)
+time_t _gnutls_openpgp_get_raw_key_expiration_time(const gnutls_datum * cert)
{
gnutls_openpgp_key key;
int ret;
diff --git a/libextra/openpgp/extras.c b/libextra/openpgp/extras.c
index 48a36ccb7f..1de1b2eb8b 100644
--- a/libextra/openpgp/extras.c
+++ b/libextra/openpgp/extras.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright 2004 Free Software Foundation
*
* This file is part of GNUTLS-EXTRA.
*
diff --git a/libextra/openpgp/gnutls_openpgp.h b/libextra/openpgp/gnutls_openpgp.h
index 23a974b328..4d21e160c7 100644
--- a/libextra/openpgp/gnutls_openpgp.h
+++ b/libextra/openpgp/gnutls_openpgp.h
@@ -5,7 +5,6 @@
#ifndef GNUTLS_OPENPGP_H
#define GNUTLS_OPENPGP_H
-#include <gnutls/compat8.h>
#include <auth_cert.h>
#include <opencdk.h>
@@ -68,11 +67,15 @@ int gnutls_openpgp_recv_key(
gnutls_datum *key );
/* internal */
-int _gnutls_openpgp_cert2gnutls_cert(
+int _gnutls_openpgp_raw_key_to_gcert(
gnutls_cert *cert,
const gnutls_datum *raw );
int
+_gnutls_openpgp_raw_privkey_to_gkey( gnutls_privkey *pkey,
+ const gnutls_datum *raw_key);
+
+int
_gnutls_openpgp_request_key(
gnutls_session,
gnutls_datum* ret,
@@ -84,15 +87,14 @@ keybox_blob* kbx_read_blob( const gnutls_datum* keyring, size_t pos );
cdk_keydb_hd_t kbx_to_keydb( keybox_blob *blob );
void kbx_blob_release( keybox_blob *ctx );
-int gnutls_openpgp_verify_key(const char *trustdb,
+int _gnutls_openpgp_verify_key(const char *trustdb,
const gnutls_datum * keyring,
const gnutls_datum * cert_list,
int cert_list_length);
-int gnutls_openpgp_fingerprint(const gnutls_datum * cert,
+int _gnutls_openpgp_fingerprint(const gnutls_datum * cert,
unsigned char *fpr, size_t * fprlen);
-time_t gnutls_openpgp_extract_key_creation_time(const gnutls_datum * cert);
-time_t gnutls_openpgp_extract_key_expiration_time(const gnutls_datum * cert);
-
+time_t _gnutls_openpgp_get_raw_key_creation_time(const gnutls_datum * cert);
+time_t _gnutls_openpgp_get_raw_key_expiration_time(const gnutls_datum * cert);
#endif /*GNUTLS_OPENPGP_H*/
diff --git a/libextra/openpgp/openpgp.c b/libextra/openpgp/openpgp.c
index 4813424fbf..8ad688f67e 100644
--- a/libextra/openpgp/openpgp.c
+++ b/libextra/openpgp/openpgp.c
@@ -1,23 +1,23 @@
/*
- * Copyright (C) 2002 Timo Schulz
- * Portions Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2002 Timo Schulz
+ * Portions Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright 2004 Free Software Foundation
*
- * This file is part of GNUTLS-EXTRA.
+ * This file is part of GNUTLS.
*
- * The GNUTLS library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * 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.
*
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 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
*/
/* Functions on OpenPGP key parsing
@@ -207,7 +207,7 @@ int
gnutls_openpgp_key_get_fingerprint( gnutls_openpgp_key key,
void *fpr, size_t *fprlen )
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
cdk_pkt_pubkey_t pk = NULL;
if( !fpr || !fprlen ) {
@@ -235,7 +235,7 @@ int
_gnutls_openpgp_count_key_names( gnutls_openpgp_key key)
{
cdk_kbnode_t p, ctx = NULL;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
int nuids = 0;
if( key == NULL ) {
@@ -271,7 +271,7 @@ gnutls_openpgp_key_get_name( gnutls_openpgp_key key,
char *buf, size_t *sizeof_buf)
{
cdk_kbnode_t ctx = NULL, p;
- CDK_PACKET *pkt = NULL;
+ cdk_packet_t pkt = NULL;
cdk_pkt_userid_t uid = NULL;
int pos = 0;
size_t size = 0;
@@ -344,7 +344,7 @@ leave:
int
gnutls_openpgp_key_get_pk_algorithm( gnutls_openpgp_key key, unsigned int *bits)
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
int algo = 0;
if( !key )
@@ -376,7 +376,7 @@ gnutls_openpgp_key_get_pk_algorithm( gnutls_openpgp_key key, unsigned int *bits)
int
gnutls_openpgp_key_get_version( gnutls_openpgp_key key)
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
int version = 0;
if( !key)
@@ -399,7 +399,7 @@ gnutls_openpgp_key_get_version( gnutls_openpgp_key key)
time_t
gnutls_openpgp_key_get_creation_time( gnutls_openpgp_key key)
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
time_t timestamp = 0;
if( !key)
@@ -423,7 +423,7 @@ gnutls_openpgp_key_get_creation_time( gnutls_openpgp_key key)
time_t
gnutls_openpgp_key_get_expiration_time( gnutls_openpgp_key key)
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
time_t expiredate = 0;
if( !key)
@@ -447,7 +447,7 @@ int
gnutls_openpgp_key_get_id( gnutls_openpgp_key key,
unsigned char keyid[8])
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
cdk_pkt_pubkey_t pk = NULL;
unsigned long kid[2];
@@ -505,7 +505,7 @@ int gnutls_openpgp_key_check_hostname(gnutls_openpgp_key key,
dnsname, &dnsnamesize);
if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
}
@@ -514,4 +514,41 @@ int gnutls_openpgp_key_check_hostname(gnutls_openpgp_key key,
return 0;
}
+/**
+ * gnutls_openpgp_key_get_key_usage - This function returns the key's usage
+ * @key: should contain a gnutls_openpgp_key structure
+ * @key_usage: where the key usage bits will be stored
+ *
+ * This function will return certificate's key usage, by checking the
+ * key algorithm. The key usage value will ORed values of the:
+ * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT.
+ *
+ * A negative value may be returned in case of parsing error.
+ *
+ **/
+int gnutls_openpgp_key_get_key_usage(gnutls_openpgp_key key, unsigned int *key_usage)
+{
+cdk_packet_t pkt;
+int algo = 0;
+
+ if( !key )
+ return GNUTLS_E_INVALID_REQUEST;
+
+ *key_usage = 0;
+
+ pkt = cdk_kbnode_find_packet( key->knode, CDK_PKT_PUBLIC_KEY);
+ if( pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY ) {
+ algo = pkt->pkt.public_key->pubkey_algo;
+
+ if( is_DSA(algo) || algo == GCRY_PK_RSA_S )
+ *key_usage |= KEY_DIGITAL_SIGNATURE;
+ else if( algo == GCRY_PK_RSA_E )
+ *key_usage |= KEY_KEY_ENCIPHERMENT;
+ else if( algo == GCRY_PK_RSA )
+ *key_usage |= KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
+ }
+
+ return 0;
+}
+
#endif
diff --git a/libextra/openpgp/openpgp.h b/libextra/openpgp/openpgp.h
index 1f9127f85e..bb76a7401f 100644
--- a/libextra/openpgp/openpgp.h
+++ b/libextra/openpgp/openpgp.h
@@ -15,6 +15,10 @@ typedef struct gnutls_openpgp_key_int {
cdk_stream_t inp;
} gnutls_openpgp_key_int;
+typedef struct gnutls_openpgp_privkey_int {
+ gnutls_privkey pkey;
+} gnutls_openpgp_privkey_int;
+
typedef struct gnutls_openpgp_keyring_int {
cdk_keydb_hd_t hd;
} gnutls_openpgp_keyring_int;
@@ -24,6 +28,7 @@ typedef struct gnutls_openpgp_trustdb_int {
} gnutls_openpgp_trustdb_int;
typedef struct gnutls_openpgp_key_int *gnutls_openpgp_key;
+typedef struct gnutls_openpgp_privkey_int *gnutls_openpgp_privkey;
typedef struct gnutls_openpgp_keyring_int *gnutls_openpgp_keyring;
typedef struct gnutls_openpgp_trustdb_int *gnutls_openpgp_trustdb;
@@ -46,7 +51,9 @@ int gnutls_openpgp_key_init(gnutls_openpgp_key * key);
void gnutls_openpgp_key_deinit(gnutls_openpgp_key key);
int gnutls_openpgp_key_import(gnutls_openpgp_key key,
const gnutls_datum * data, gnutls_openpgp_key_fmt format);
-
+int gnutls_openpgp_key_export(gnutls_openpgp_key key,
+ gnutls_openpgp_key_fmt format, void* output_data,
+ size_t* output_data_size);
void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring keyring);
int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring * keyring);
@@ -70,6 +77,11 @@ int gnutls_openpgp_key_verify_trustdb( gnutls_openpgp_key key,
int gnutls_openpgp_key_verify_self( gnutls_openpgp_key key,
unsigned int flags, unsigned int *verify);
+int _gnutls_openpgp_key_to_gcert(gnutls_cert * gcert, gnutls_openpgp_key cert);
+int _gnutls_openpgp_privkey_to_gkey( gnutls_privkey* dest, gnutls_openpgp_privkey src);
+
+void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey key);
+
#endif
#endif /* HAVE_LIBOPENCDK */
diff --git a/libextra/openpgp/privkey.c b/libextra/openpgp/privkey.c
new file mode 100644
index 0000000000..0331ad1bf5
--- /dev/null
+++ b/libextra/openpgp/privkey.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright 2004 Free Software Foundation
+ *
+ * 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
+ */
+
+/* Functions on OpenPGP privkey parsing
+ */
+
+#include <gnutls_int.h>
+
+#ifdef HAVE_LIBOPENCDK
+
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <opencdk.h>
+#include <openpgp.h>
+#include <gnutls_openpgp.h>
+#include <x509/rfc2818.h>
+#include <gnutls_cert.h>
+
+/**
+ * gnutls_openpgp_privkey_init - This function initializes a gnutls_openpgp_privkey structure
+ * @key: The structure to be initialized
+ *
+ * This function will initialize an OpenPGP key structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey * key)
+{
+ *key = gnutls_calloc( 1, sizeof(gnutls_openpgp_privkey_int));
+
+ if (*key) {
+ return 0; /* success */
+ }
+ return GNUTLS_E_MEMORY_ERROR;
+}
+
+/**
+ * gnutls_openpgp_privkey_deinit - This function deinitializes memory used by a gnutls_openpgp_privkey structure
+ * @key: The structure to be initialized
+ *
+ * This function will deinitialize a key structure.
+ *
+ **/
+void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey key)
+{
+ if (!key) return;
+
+ _gnutls_gkey_deinit( &key->pkey);
+ gnutls_free(key);
+}
+
+/**
+ * gnutls_openpgp_privkey_import - This function will import a RAW or BASE64 encoded key
+ * @key: The structure to store the parsed key.
+ * @data: The RAW or BASE64 encoded key.
+ * @format: One of gnutls_openpgp_key_fmt elements.
+ * @pass: Unused for now
+ * @flags: should be zero
+ *
+ * This function will convert the given RAW or Base64 encoded key
+ * to the native gnutls_openpgp_privkey format. The output will be stored in 'key'.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_openpgp_privkey_import(gnutls_openpgp_privkey key,
+ const gnutls_datum * data, gnutls_openpgp_key_fmt format,
+ const char* pass, unsigned int flags)
+{
+int rc;
+
+ rc = _gnutls_openpgp_raw_privkey_to_gkey( &key->pkey, data);
+ if( rc) {
+ gnutls_assert();
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm
+ * @key: is an OpenPGP key
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of an OpenPGP
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public exponent.
+ *
+ * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+int
+gnutls_openpgp_privkey_get_pk_algorithm( gnutls_openpgp_privkey key, unsigned int *bits)
+{
+ int pk = key->pkey.pk_algorithm;
+
+ if (bits) {
+ *bits = 0;
+ if (pk == GNUTLS_PK_RSA)
+ *bits = _gnutls_mpi_get_nbits( key->pkey.params[0]);
+ if (pk == GNUTLS_PK_DSA)
+ *bits = _gnutls_mpi_get_nbits( key->pkey.params[3]);
+ }
+ return pk;
+}
+
+
+#endif
diff --git a/libextra/openpgp/verify.c b/libextra/openpgp/verify.c
index 764fe761a1..7472b4e353 100644
--- a/libextra/openpgp/verify.c
+++ b/libextra/openpgp/verify.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 Timo Schulz
* Portions Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright 2004 Free Software Foundation
*
* This file is part of GNUTLS-EXTRA.
*
@@ -34,7 +35,7 @@ static int
openpgp_get_key_trust( gnutls_openpgp_trustdb trustdb,
gnutls_openpgp_key key, unsigned int *r_trustval )
{
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
cdk_pkt_pubkey_t pk = NULL;
int flags = 0, ot = 0;
int rc = 0;
diff --git a/libextra/openpgp/xml.c b/libextra/openpgp/xml.c
index 0f835dbbde..d95e10e85a 100644
--- a/libextra/openpgp/xml.c
+++ b/libextra/openpgp/xml.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 Timo Schulz <twoaday@freakmail.de>
* Portions Copyright 2003 Nikos Mavroyanopoulos <nmav@gnutls.org>
+ * Copyright 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -338,7 +339,7 @@ gnutls_openpgp_key_to_xml( gnutls_openpgp_key key,
gnutls_datum *xmlkey, int ext )
{
cdk_kbnode_t node, ctx = NULL;
- CDK_PACKET *pkt;
+ cdk_packet_t pkt;
char name[MAX_CN];
size_t name_len;
const char *s;
diff --git a/src/serv.c b/src/serv.c
index 00fa77f75b..7dc7a69eb0 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2001,2002 Paul Sheer
* Portions Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -137,6 +138,7 @@ static const char *safe_strerror(int value)
static void listener_free(listener_item * j)
{
+
if (j->http_request)
free(j->http_request);
if (j->http_response)
@@ -665,7 +667,7 @@ int main(int argc, char **argv)
if (generate != 0 || read_dh_params != NULL) {
gnutls_certificate_set_dh_params(cert_cred, dh_params);
- gnutls_certificate_set_rsa_params(cert_cred, rsa_params);
+ gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params);
}
/* this is a password file (created with the included srpcrypt utility)
@@ -1128,8 +1130,8 @@ static int wrap_db_delete(void *dbf, gnutls_datum key)
void print_serv_license(void)
{
- fprintf(stdout,
- "\nCopyright (C) 2001-2003 Paul Sheer, Nikos Mavroyanopoulos\n"
+ fputs( "\nCopyright (C) 2001-2003 Paul Sheer, Nikos Mavroyanopoulos\n"
+ "\nCopyright (C) 2004 Free Software Foundation\n"
"This program is free software; you can redistribute it and/or modify \n"
"it under the terms of the GNU General Public License as published by \n"
"the Free Software Foundation; either version 2 of the License, or \n"
@@ -1140,7 +1142,7 @@ void print_serv_license(void)
"GNU General Public License for more details. \n" "\n"
"You should have received a copy of the GNU General Public License \n"
"along with this program; if not, write to the Free Software \n"
- "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
+ "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n", stdout);
}
#ifdef HAVE_LIBOPENCDK