x509_privkey.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003, 2004, 2005, 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 #include <gnutls_int.h>
00026 #include <gnutls_datum.h>
00027 #include <gnutls_global.h>
00028 #include <gnutls_errors.h>
00029 #include <gnutls_rsa_export.h>
00030 #include <gnutls_sig.h>
00031 #include <common.h>
00032 #include <gnutls_x509.h>
00033 #include <x509_b64.h>
00034 #include <x509.h>
00035 #include <mpi.h>
00036 #include <extensions.h>
00037 
00038 /* remove this when libgcrypt can handle the PKCS #1 coefficients from
00039  * rsa keys
00040  */
00041 #define CALC_COEFF 1
00042 
00052 int
00053 MHD_gnutls_x509_privkey_init (MHD_gnutls_x509_privkey_t * key)
00054 {
00055   *key = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_x509_privkey_int));
00056 
00057   if (*key)
00058     {
00059       (*key)->key = ASN1_TYPE_EMPTY;
00060       (*key)->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
00061       return 0;                 /* success */
00062     }
00063 
00064   return GNUTLS_E_MEMORY_ERROR;
00065 }
00066 
00074 void
00075 MHD_gnutls_x509_privkey_deinit (MHD_gnutls_x509_privkey_t key)
00076 {
00077   int i;
00078 
00079   if (!key)
00080     return;
00081 
00082   for (i = 0; i < key->params_size; i++)
00083     {
00084       MHD_gtls_mpi_release (&key->params[i]);
00085     }
00086 
00087   MHD__asn1_delete_structure (&key->key);
00088   MHD_gnutls_free (key);
00089 }
00090 
00091 
00092 /* Converts an RSA PKCS#1 key to
00093  * an internal structure (MHD_gnutls_private_key)
00094  */
00095 ASN1_TYPE
00096 MHD__gnutls_privkey_decode_pkcs1_rsa_key (const MHD_gnutls_datum_t * raw_key,
00097                                           MHD_gnutls_x509_privkey_t pkey)
00098 {
00099   int result;
00100   ASN1_TYPE pkey_asn;
00101 
00102   if ((result = MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
00103                                           "GNUTLS.RSAPrivateKey",
00104                                           &pkey_asn)) != ASN1_SUCCESS)
00105     {
00106       MHD_gnutls_assert ();
00107       return NULL;
00108     }
00109 
00110   if ((sizeof (pkey->params) / sizeof (mpi_t)) < RSA_PRIVATE_PARAMS)
00111     {
00112       MHD_gnutls_assert ();
00113       /* internal error. Increase the mpi_ts in params */
00114       return NULL;
00115     }
00116 
00117   result =
00118     MHD__asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL);
00119   if (result != ASN1_SUCCESS)
00120     {
00121       MHD_gnutls_assert ();
00122       goto error;
00123     }
00124 
00125   if ((result =
00126        MHD__gnutls_x509_read_int (pkey_asn, "modulus", &pkey->params[0])) < 0)
00127     {
00128       MHD_gnutls_assert ();
00129       goto error;
00130     }
00131 
00132   if ((result = MHD__gnutls_x509_read_int (pkey_asn, "publicExponent",
00133                                            &pkey->params[1])) < 0)
00134     {
00135       MHD_gnutls_assert ();
00136       goto error;
00137     }
00138 
00139   if ((result = MHD__gnutls_x509_read_int (pkey_asn, "privateExponent",
00140                                            &pkey->params[2])) < 0)
00141     {
00142       MHD_gnutls_assert ();
00143       goto error;
00144     }
00145 
00146   if ((result =
00147        MHD__gnutls_x509_read_int (pkey_asn, "prime1", &pkey->params[3])) < 0)
00148     {
00149       MHD_gnutls_assert ();
00150       goto error;
00151     }
00152 
00153   if ((result =
00154        MHD__gnutls_x509_read_int (pkey_asn, "prime2", &pkey->params[4])) < 0)
00155     {
00156       MHD_gnutls_assert ();
00157       goto error;
00158     }
00159 
00160 #ifdef CALC_COEFF
00161   /* Calculate the coefficient. This is because the gcrypt
00162    * library is uses the p,q in the reverse order.
00163    */
00164   pkey->params[5] =
00165     MHD__gnutls_mpi_snew (MHD__gnutls_mpi_get_nbits (pkey->params[0]));
00166 
00167   if (pkey->params[5] == NULL)
00168     {
00169       MHD_gnutls_assert ();
00170       goto error;
00171     }
00172 
00173   MHD__gnutls_mpi_invm (pkey->params[5], pkey->params[3], pkey->params[4]);
00174   /* p, q */
00175 #else
00176   if ((result = MHD__gnutls_x509_read_int (pkey_asn, "coefficient",
00177                                            &pkey->params[5])) < 0)
00178     {
00179       MHD_gnutls_assert ();
00180       goto error;
00181     }
00182 #endif
00183   pkey->params_size = 6;
00184 
00185   return pkey_asn;
00186 
00187 error:MHD__asn1_delete_structure (&pkey_asn);
00188   MHD_gtls_mpi_release (&pkey->params[0]);
00189   MHD_gtls_mpi_release (&pkey->params[1]);
00190   MHD_gtls_mpi_release (&pkey->params[2]);
00191   MHD_gtls_mpi_release (&pkey->params[3]);
00192   MHD_gtls_mpi_release (&pkey->params[4]);
00193   MHD_gtls_mpi_release (&pkey->params[5]);
00194   return NULL;
00195 
00196 }
00197 
00198 #define PEM_KEY_RSA "RSA PRIVATE KEY"
00199 
00215 int
00216 MHD_gnutls_x509_privkey_import (MHD_gnutls_x509_privkey_t key,
00217                                 const MHD_gnutls_datum_t * data,
00218                                 MHD_gnutls_x509_crt_fmt_t format)
00219 {
00220   int result = 0, need_free = 0;
00221   MHD_gnutls_datum_t _data;
00222 
00223   if (key == NULL)
00224     {
00225       MHD_gnutls_assert ();
00226       return GNUTLS_E_INVALID_REQUEST;
00227     }
00228 
00229   _data.data = data->data;
00230   _data.size = data->size;
00231 
00232   key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
00233 
00234   /* If the Certificate is in PEM format then decode it */
00235   if (format == GNUTLS_X509_FMT_PEM)
00236     {
00237       opaque *out;
00238 
00239       /* Try the first header */
00240       result
00241         =
00242         MHD__gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size,
00243                                     &out);
00244       key->pk_algorithm = MHD_GNUTLS_PK_RSA;
00245 
00246       _data.data = out;
00247       _data.size = result;
00248 
00249       need_free = 1;
00250     }
00251 
00252   if (key->pk_algorithm == MHD_GNUTLS_PK_RSA)
00253     {
00254       key->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
00255       if (key->key == NULL)
00256         MHD_gnutls_assert ();
00257     }
00258   else
00259     {
00260       /* Try decoding with both, and accept the one that succeeds. */
00261       key->pk_algorithm = MHD_GNUTLS_PK_RSA;
00262       key->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
00263 
00264       // TODO rm
00265 //      if (key->key == NULL)
00266 //        {
00267 //          key->pk_algorithm = GNUTLS_PK_DSA;
00268 //          key->key = decode_dsa_key(&_data, key);
00269 //          if (key->key == NULL)
00270 //            MHD_gnutls_assert();
00271 //        }
00272     }
00273 
00274   if (key->key == NULL)
00275     {
00276       MHD_gnutls_assert ();
00277       result = GNUTLS_E_ASN1_DER_ERROR;
00278       key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
00279       return result;
00280     }
00281 
00282   if (need_free)
00283     MHD__gnutls_free_datum (&_data);
00284 
00285   /* The key has now been decoded.
00286    */
00287 
00288   return 0;
00289 }

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