gnutls_cert.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
00003  *
00004  * Author: Nikos Mavrogiannopoulos
00005  *
00006  * This file is part of GNUTLS.
00007  *
00008  * The GNUTLS library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021  * USA
00022  *
00023  */
00024 
00025 /* Some of the stuff needed for Certificate authentication is contained
00026  * in this file.
00027  */
00028 
00029 #include <gnutls_int.h>
00030 #include <gnutls_errors.h>
00031 #include <auth_cert.h>
00032 #include <gnutls_cert.h>
00033 #include <gnutls_datum.h>
00034 #include <gnutls_mpi.h>
00035 #include <gnutls_global.h>
00036 #include <gnutls_algorithms.h>
00037 #include <gnutls_dh.h>
00038 #include <gnutls_str.h>
00039 #include <gnutls_state.h>
00040 #include <gnutls_auth_int.h>
00041 #include <gnutls_x509.h>
00042 /* x509 */
00043 #include "x509.h"
00044 #include "mpi.h"
00045 
00055 void
00056 MHD__gnutls_certificate_free_keys (MHD_gtls_cert_credentials_t sc)
00057 {
00058   unsigned i, j;
00059 
00060   for (i = 0; i < sc->ncerts; i++)
00061     {
00062       for (j = 0; j < sc->cert_list_length[i]; j++)
00063         {
00064           MHD_gtls_gcert_deinit (&sc->cert_list[i][j]);
00065         }
00066       MHD_gnutls_free (sc->cert_list[i]);
00067     }
00068 
00069   MHD_gnutls_free (sc->cert_list_length);
00070   sc->cert_list_length = NULL;
00071 
00072   MHD_gnutls_free (sc->cert_list);
00073   sc->cert_list = NULL;
00074 
00075   for (i = 0; i < sc->ncerts; i++)
00076     {
00077       MHD_gtls_gkey_deinit (&sc->pkey[i]);
00078     }
00079 
00080   MHD_gnutls_free (sc->pkey);
00081   sc->pkey = NULL;
00082 
00083   sc->ncerts = 0;
00084 
00085 }
00086 
00097 void
00098 MHD__gnutls_certificate_free_cas (MHD_gtls_cert_credentials_t sc)
00099 {
00100   unsigned j;
00101 
00102   for (j = 0; j < sc->x509_ncas; j++)
00103     {
00104       MHD_gnutls_x509_crt_deinit (sc->x509_ca_list[j]);
00105     }
00106 
00107   sc->x509_ncas = 0;
00108 
00109   MHD_gnutls_free (sc->x509_ca_list);
00110   sc->x509_ca_list = NULL;
00111 
00112 }
00113 
00126 void
00127 MHD__gnutls_certificate_free_ca_names (MHD_gtls_cert_credentials_t sc)
00128 {
00129   MHD__gnutls_free_datum (&sc->x509_rdn_sequence);
00130 }
00131 
00132 /*-
00133   * MHD_gtls_certificate_get_rsa_params - Returns the RSA parameters pointer
00134   * @rsa_params: holds the RSA parameters or NULL.
00135   * @func: function to retrieve the parameters or NULL.
00136   * @session: The session.
00137   *
00138   * This function will return the rsa parameters pointer.
00139   *
00140   -*/
00141 MHD_gtls_rsa_params_t
00142 MHD_gtls_certificate_get_rsa_params (MHD_gtls_rsa_params_t rsa_params,
00143                                      MHD_gnutls_params_function * func,
00144                                      MHD_gtls_session_t session)
00145 {
00146   MHD_gnutls_params_st params;
00147   int ret;
00148 
00149   if (session->internals.params.rsa_params)
00150     {
00151       return session->internals.params.rsa_params;
00152     }
00153 
00154   if (rsa_params)
00155     {
00156       session->internals.params.rsa_params = rsa_params;
00157     }
00158   else if (func)
00159     {
00160       ret = func (session, GNUTLS_PARAMS_RSA_EXPORT, &params);
00161       if (ret == 0 && params.type == GNUTLS_PARAMS_RSA_EXPORT)
00162         {
00163           session->internals.params.rsa_params = params.params.rsa_export;
00164           session->internals.params.free_rsa_params = params.deinit;
00165         }
00166     }
00167 
00168   return session->internals.params.rsa_params;
00169 }
00170 
00171 
00183 void
00184 MHD__gnutls_certificate_free_credentials (MHD_gtls_cert_credentials_t sc)
00185 {
00186   MHD__gnutls_certificate_free_keys (sc);
00187   MHD__gnutls_certificate_free_cas (sc);
00188   MHD__gnutls_certificate_free_ca_names (sc);
00189 #ifdef KEYRING_HACK
00190   MHD__gnutls_free_datum (&sc->keyring);
00191 #endif
00192 
00193   MHD_gnutls_free (sc);
00194 }
00195 
00196 
00206 int
00207 MHD__gnutls_certificate_allocate_credentials (MHD_gtls_cert_credentials_t *
00208                                               res)
00209 {
00210   *res = MHD_gnutls_calloc (1, sizeof (MHD_gtls_cert_credentials_st));
00211 
00212   if (*res == NULL)
00213     return GNUTLS_E_MEMORY_ERROR;
00214 
00215   (*res)->verify_bits = DEFAULT_VERIFY_BITS;
00216   (*res)->verify_depth = DEFAULT_VERIFY_DEPTH;
00217 
00218   return 0;
00219 }
00220 
00221 
00222 /* returns the KX algorithms that are supported by a
00223  * certificate. (Eg a certificate with RSA params, supports
00224  * GNUTLS_KX_RSA algorithm).
00225  * This function also uses the KeyUsage field of the certificate
00226  * extensions in order to disable unneded algorithms.
00227  */
00228 int
00229 MHD_gtls_selected_cert_supported_kx (MHD_gtls_session_t session,
00230                                      enum MHD_GNUTLS_KeyExchangeAlgorithm
00231                                      **alg, int *alg_size)
00232 {
00233   enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
00234   enum MHD_GNUTLS_PublicKeyAlgorithm pk;
00235   enum MHD_GNUTLS_KeyExchangeAlgorithm kxlist[MAX_ALGOS];
00236   MHD_gnutls_cert *cert;
00237   int i;
00238 
00239   if (session->internals.selected_cert_list_length == 0)
00240     {
00241       *alg_size = 0;
00242       *alg = NULL;
00243       return 0;
00244     }
00245 
00246   cert = &session->internals.selected_cert_list[0];
00247   i = 0;
00248 
00249   for (kx = 0; kx < MAX_ALGOS; kx++)
00250     {
00251       pk = MHD_gtls_map_pk_get_pk (kx);
00252       if (pk == cert->subject_pk_algorithm)
00253         {
00254           /* then check key usage */
00255           if (MHD__gnutls_check_key_usage (cert, kx) == 0)
00256             {
00257               kxlist[i] = kx;
00258               i++;
00259             }
00260         }
00261     }
00262 
00263   if (i == 0)
00264     {
00265       MHD_gnutls_assert ();
00266       return GNUTLS_E_INVALID_REQUEST;
00267     }
00268 
00269   *alg =
00270     MHD_gnutls_calloc (1, sizeof (enum MHD_GNUTLS_KeyExchangeAlgorithm) * i);
00271   if (*alg == NULL)
00272     return GNUTLS_E_MEMORY_ERROR;
00273 
00274   *alg_size = i;
00275 
00276   memcpy (*alg, kxlist, i * sizeof (enum MHD_GNUTLS_KeyExchangeAlgorithm));
00277 
00278   return 0;
00279 }
00280 
00281 
00282 
00283 int
00284 MHD_gtls_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
00285                             enum MHD_GNUTLS_CertificateType type,
00286                             const MHD_gnutls_datum_t * raw_cert,
00287                             int flags /* OR of ConvFlags */ )
00288 {
00289   switch (type)
00290     {
00291     case MHD_GNUTLS_CRT_X509:
00292       return MHD_gtls_x509_raw_cert_to_gcert (gcert, raw_cert, flags);
00293     default:
00294       MHD_gnutls_assert ();
00295       return GNUTLS_E_INTERNAL_ERROR;
00296     }
00297 }
00298 
00299 /* This function will convert a der certificate to a format
00300  * (structure) that gnutls can understand and use. Actually the
00301  * important thing on this function is that it extracts the
00302  * certificate's (public key) parameters.
00303  *
00304  * The noext flag is used to complete the handshake even if the
00305  * extensions found in the certificate are unsupported and critical.
00306  * The critical extensions will be catched by the verification functions.
00307  */
00308 int
00309 MHD_gtls_x509_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
00310                                  const MHD_gnutls_datum_t * derCert,
00311                                  int flags /* OR of ConvFlags */ )
00312 {
00313   int ret;
00314   MHD_gnutls_x509_crt_t cert;
00315 
00316   ret = MHD_gnutls_x509_crt_init (&cert);
00317   if (ret < 0)
00318     {
00319       MHD_gnutls_assert ();
00320       return ret;
00321     }
00322 
00323   ret = MHD_gnutls_x509_crt_import (cert, derCert, GNUTLS_X509_FMT_DER);
00324   if (ret < 0)
00325     {
00326       MHD_gnutls_assert ();
00327       MHD_gnutls_x509_crt_deinit (cert);
00328       return ret;
00329     }
00330 
00331   ret = MHD_gtls_x509_crt_to_gcert (gcert, cert, flags);
00332   MHD_gnutls_x509_crt_deinit (cert);
00333 
00334   return ret;
00335 }
00336 
00337 /* Like above but it accepts a parsed certificate instead.
00338  */
00339 int
00340 MHD_gtls_x509_crt_to_gcert (MHD_gnutls_cert * gcert,
00341                             MHD_gnutls_x509_crt_t cert, unsigned int flags)
00342 {
00343   int ret = 0;
00344 
00345   memset (gcert, 0, sizeof (MHD_gnutls_cert));
00346   gcert->cert_type = MHD_GNUTLS_CRT_X509;
00347 
00348   if (!(flags & CERT_NO_COPY))
00349     {
00350 #define SMALL_DER 512
00351       opaque *der;
00352       size_t der_size = SMALL_DER;
00353 
00354       /* initially allocate a bogus size, just in case the certificate
00355        * fits in it. That way we minimize the DER encodings performed.
00356        */
00357       der = MHD_gnutls_malloc (SMALL_DER);
00358       if (der == NULL)
00359         {
00360           MHD_gnutls_assert ();
00361           return GNUTLS_E_MEMORY_ERROR;
00362         }
00363 
00364       ret =
00365         MHD_gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
00366                                     &der_size);
00367       if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
00368         {
00369           MHD_gnutls_assert ();
00370           MHD_gnutls_free (der);
00371           return ret;
00372         }
00373 
00374       if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
00375         {
00376           der = MHD_gnutls_realloc (der, der_size);
00377           if (der == NULL)
00378             {
00379               MHD_gnutls_assert ();
00380               return GNUTLS_E_MEMORY_ERROR;
00381             }
00382 
00383           ret =
00384             MHD_gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
00385                                         &der_size);
00386           if (ret < 0)
00387             {
00388               MHD_gnutls_assert ();
00389               MHD_gnutls_free (der);
00390               return ret;
00391             }
00392         }
00393 
00394       gcert->raw.data = der;
00395       gcert->raw.size = der_size;
00396     }
00397   else
00398     /* now we have 0 or a bitwise or of things to decode */
00399     flags ^= CERT_NO_COPY;
00400 
00401 
00402   if (flags & CERT_ONLY_EXTENSIONS || flags == 0)
00403     {
00404       MHD_gnutls_x509_crt_get_key_usage (cert, &gcert->key_usage, NULL);
00405       gcert->version = MHD_gnutls_x509_crt_get_version (cert);
00406     }
00407   gcert->subject_pk_algorithm =
00408     MHD_gnutls_x509_crt_get_pk_algorithm (cert, NULL);
00409 
00410   if (flags & CERT_ONLY_PUBKEY || flags == 0)
00411     {
00412       gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
00413       ret =
00414         MHD__gnutls_x509_crt_get_mpis (cert, gcert->params,
00415                                        &gcert->params_size);
00416       if (ret < 0)
00417         {
00418           MHD_gnutls_assert ();
00419           return ret;
00420         }
00421     }
00422 
00423   return 0;
00424 
00425 }
00426 
00427 void
00428 MHD_gtls_gcert_deinit (MHD_gnutls_cert * cert)
00429 {
00430   int i;
00431 
00432   if (cert == NULL)
00433     return;
00434 
00435   for (i = 0; i < cert->params_size; i++)
00436     {
00437       MHD_gtls_mpi_release (&cert->params[i]);
00438     }
00439 
00440   MHD__gnutls_free_datum (&cert->raw);
00441 }

Generated on Fri Feb 27 18:31:19 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1