common.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 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 #include <gnutls_int.h>
00026 #include <libtasn1.h>
00027 #include <gnutls_datum.h>
00028 #include <gnutls_global.h>
00029 #include <gnutls_errors.h>
00030 #include <gnutls_str.h>
00031 #include <gnutls_x509.h>
00032 #include <gnutls_num.h>
00033 #include <x509_b64.h>
00034 #include <common.h>
00035 #include <mpi.h>
00036 #include <time.h>
00037 
00038 /* A generic export function. Will export the given ASN.1 encoded data
00039  * to PEM or DER raw data.
00040  */
00041 int
00042 MHD__gnutls_x509_export_int (ASN1_TYPE MHD__asn1_data,
00043                              MHD_gnutls_x509_crt_fmt_t format,
00044                              char *pem_header,
00045                              unsigned char *output_data,
00046                              size_t * output_data_size)
00047 {
00048   int result, len;
00049 
00050   if (format == GNUTLS_X509_FMT_DER)
00051     {
00052 
00053       if (output_data == NULL)
00054         *output_data_size = 0;
00055 
00056       len = *output_data_size;
00057 
00058       if ((result =
00059            MHD__asn1_der_coding (MHD__asn1_data, "", output_data, &len,
00060                                  NULL)) != ASN1_SUCCESS)
00061         {
00062           *output_data_size = len;
00063           if (result == ASN1_MEM_ERROR)
00064             {
00065               return GNUTLS_E_SHORT_MEMORY_BUFFER;
00066             }
00067           MHD_gnutls_assert ();
00068           return MHD_gtls_asn2err (result);
00069         }
00070 
00071       *output_data_size = len;
00072 
00073     }
00074   else
00075     {                           /* PEM */
00076       opaque *out;
00077       MHD_gnutls_datum_t tmp;
00078 
00079       result = MHD__gnutls_x509_der_encode (MHD__asn1_data, "", &tmp, 0);
00080       if (result < 0)
00081         {
00082           MHD_gnutls_assert ();
00083           return result;
00084         }
00085 
00086       result =
00087         MHD__gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, &out);
00088 
00089       MHD__gnutls_free_datum (&tmp);
00090 
00091       if (result < 0)
00092         {
00093           MHD_gnutls_assert ();
00094           return result;
00095         }
00096 
00097       if (result == 0)
00098         {                       /* oooops */
00099           MHD_gnutls_assert ();
00100           return GNUTLS_E_INTERNAL_ERROR;
00101         }
00102 
00103       if ((unsigned) result > *output_data_size)
00104         {
00105           MHD_gnutls_assert ();
00106           MHD_gnutls_free (out);
00107           *output_data_size = result;
00108           return GNUTLS_E_SHORT_MEMORY_BUFFER;
00109         }
00110 
00111       *output_data_size = result;
00112 
00113       if (output_data)
00114         {
00115           memcpy (output_data, out, result);
00116 
00117           /* do not include the null character into output size.
00118            */
00119           *output_data_size = result - 1;
00120         }
00121       MHD_gnutls_free (out);
00122 
00123     }
00124 
00125   return 0;
00126 }
00127 
00128 /* Decodes an octet string. Leave string_type null for a normal
00129  * octet string. Otherwise put something like BMPString, PrintableString
00130  * etc.
00131  */
00132 static int
00133 MHD__gnutls_x509_decode_octet_string (const char *string_type,
00134                                       const opaque * der,
00135                                       size_t der_size,
00136                                       opaque * output, size_t * output_size)
00137 {
00138   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
00139   int result, tmp_output_size;
00140   char strname[64];
00141 
00142   if (string_type == NULL)
00143     MHD_gtls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data");
00144   else
00145     {
00146       MHD_gtls_str_cpy (strname, sizeof (strname), "PKIX1.");
00147       MHD_gtls_str_cat (strname, sizeof (strname), string_type);
00148     }
00149 
00150   if ((result =
00151        MHD__asn1_create_element (MHD__gnutls_get_pkix (), strname,
00152                                  &c2)) != ASN1_SUCCESS)
00153     {
00154       MHD_gnutls_assert ();
00155       result = MHD_gtls_asn2err (result);
00156       goto cleanup;
00157     }
00158 
00159   result = MHD__asn1_der_decoding (&c2, der, der_size, NULL);
00160   if (result != ASN1_SUCCESS)
00161     {
00162       MHD_gnutls_assert ();
00163       result = MHD_gtls_asn2err (result);
00164       goto cleanup;
00165     }
00166 
00167   tmp_output_size = *output_size;
00168   result = MHD__asn1_read_value (c2, "", output, &tmp_output_size);
00169   *output_size = tmp_output_size;
00170 
00171   if (result != ASN1_SUCCESS)
00172     {
00173       MHD_gnutls_assert ();
00174       result = MHD_gtls_asn2err (result);
00175       goto cleanup;
00176     }
00177 
00178   return 0;
00179 
00180 cleanup:if (c2)
00181     MHD__asn1_delete_structure (&c2);
00182 
00183   return result;
00184 }
00185 
00186 /* Reads a value from an ASN1 tree, and puts the output
00187  * in an allocated variable in the given datum.
00188  * flags == 0 do nothing  with the DER output
00189  * flags == 1 parse the DER output as OCTET STRING
00190  * flags == 2 the value is a BIT STRING
00191  */
00192 int
00193 MHD__gnutls_x509_read_value (ASN1_TYPE c,
00194                              const char *root, MHD_gnutls_datum_t * ret,
00195                              int flags)
00196 {
00197   int len = 0, result;
00198   size_t slen;
00199   opaque *tmp = NULL;
00200 
00201   result = MHD__asn1_read_value (c, root, NULL, &len);
00202   if (result != ASN1_MEM_ERROR)
00203     {
00204       MHD_gnutls_assert ();
00205       result = MHD_gtls_asn2err (result);
00206       return result;
00207     }
00208 
00209   if (flags == 2)
00210     len /= 8;
00211 
00212   tmp = MHD_gnutls_malloc (len);
00213   if (tmp == NULL)
00214     {
00215       MHD_gnutls_assert ();
00216       result = GNUTLS_E_MEMORY_ERROR;
00217       goto cleanup;
00218     }
00219 
00220   result = MHD__asn1_read_value (c, root, tmp, &len);
00221   if (result != ASN1_SUCCESS)
00222     {
00223       MHD_gnutls_assert ();
00224       result = MHD_gtls_asn2err (result);
00225       goto cleanup;
00226     }
00227 
00228   if (flags == 2)
00229     len /= 8;
00230 
00231   /* Extract the OCTET STRING.
00232    */
00233 
00234   if (flags == 1)
00235     {
00236       slen = len;
00237       result =
00238         MHD__gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen);
00239       if (result < 0)
00240         {
00241           MHD_gnutls_assert ();
00242           goto cleanup;
00243         }
00244       len = slen;
00245     }
00246 
00247   ret->data = tmp;
00248   ret->size = len;
00249 
00250   return 0;
00251 
00252 cleanup:MHD_gnutls_free (tmp);
00253   return result;
00254 
00255 }
00256 
00257 /* DER Encodes the src ASN1_TYPE and stores it to
00258  * the given datum. If str is non null then the data are encoded as
00259  * an OCTET STRING.
00260  */
00261 int
00262 MHD__gnutls_x509_der_encode (ASN1_TYPE src,
00263                              const char *src_name, MHD_gnutls_datum_t * res,
00264                              int str)
00265 {
00266   int size, result;
00267   int asize;
00268   opaque *data = NULL;
00269   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
00270 
00271   size = 0;
00272   result = MHD__asn1_der_coding (src, src_name, NULL, &size, NULL);
00273   if (result != ASN1_MEM_ERROR)
00274     {
00275       MHD_gnutls_assert ();
00276       result = MHD_gtls_asn2err (result);
00277       goto cleanup;
00278     }
00279 
00280   /* allocate data for the der
00281    */
00282 
00283   if (str)
00284     size += 16;                 /* for later to include the octet tags */
00285   asize = size;
00286 
00287   data = MHD_gnutls_malloc (size);
00288   if (data == NULL)
00289     {
00290       MHD_gnutls_assert ();
00291       result = GNUTLS_E_MEMORY_ERROR;
00292       goto cleanup;
00293     }
00294 
00295   result = MHD__asn1_der_coding (src, src_name, data, &size, NULL);
00296   if (result != ASN1_SUCCESS)
00297     {
00298       MHD_gnutls_assert ();
00299       result = MHD_gtls_asn2err (result);
00300       goto cleanup;
00301     }
00302 
00303   if (str)
00304     {
00305       if ((result =
00306            MHD__asn1_create_element (MHD__gnutls_get_pkix (),
00307                                      "PKIX1.pkcs-7-Data",
00308                                      &c2)) != ASN1_SUCCESS)
00309         {
00310           MHD_gnutls_assert ();
00311           result = MHD_gtls_asn2err (result);
00312           goto cleanup;
00313         }
00314 
00315       result = MHD__asn1_write_value (c2, "", data, size);
00316       if (result != ASN1_SUCCESS)
00317         {
00318           MHD_gnutls_assert ();
00319           result = MHD_gtls_asn2err (result);
00320           goto cleanup;
00321         }
00322 
00323       result = MHD__asn1_der_coding (c2, "", data, &asize, NULL);
00324       if (result != ASN1_SUCCESS)
00325         {
00326           MHD_gnutls_assert ();
00327           result = MHD_gtls_asn2err (result);
00328           goto cleanup;
00329         }
00330 
00331       size = asize;
00332 
00333       MHD__asn1_delete_structure (&c2);
00334     }
00335 
00336   res->data = data;
00337   res->size = size;
00338   return 0;
00339 
00340 cleanup:MHD_gnutls_free (data);
00341   MHD__asn1_delete_structure (&c2);
00342   return result;
00343 
00344 }
00345 
00346 /* Reads and returns the PK algorithm of the given certificate-like
00347  * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo".
00348  */
00349 int
00350 MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src,
00351                                    const char *src_name, unsigned int *bits)
00352 {
00353   int result;
00354   opaque *str = NULL;
00355   int algo;
00356   char oid[64];
00357   int len;
00358   mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
00359   char name[128];
00360 
00361   MHD_gtls_str_cpy (name, sizeof (name), src_name);
00362   MHD_gtls_str_cat (name, sizeof (name), ".algorithm.algorithm");
00363 
00364   len = sizeof (oid);
00365   result = MHD__asn1_read_value (src, name, oid, &len);
00366 
00367   if (result != ASN1_SUCCESS)
00368     {
00369       MHD_gnutls_assert ();
00370       return MHD_gtls_asn2err (result);
00371     }
00372 
00373   algo = MHD_gtls_x509_oid2pk_algorithm (oid);
00374 
00375   if (bits == NULL)
00376     {
00377       MHD_gnutls_free (str);
00378       return algo;
00379     }
00380 
00381   /* Now read the parameters' bits
00382    */
00383   MHD_gtls_str_cpy (name, sizeof (name), src_name);
00384   MHD_gtls_str_cat (name, sizeof (name), ".subjectPublicKey");
00385 
00386   len = 0;
00387   result = MHD__asn1_read_value (src, name, NULL, &len);
00388   if (result != ASN1_MEM_ERROR)
00389     {
00390       MHD_gnutls_assert ();
00391       return MHD_gtls_asn2err (result);
00392     }
00393 
00394   if (len % 8 != 0)
00395     {
00396       MHD_gnutls_assert ();
00397       return GNUTLS_E_CERTIFICATE_ERROR;
00398     }
00399 
00400   len /= 8;
00401 
00402   str = MHD_gnutls_malloc (len);
00403   if (str == NULL)
00404     {
00405       MHD_gnutls_assert ();
00406       return GNUTLS_E_MEMORY_ERROR;
00407     }
00408 
00409   MHD_gtls_str_cpy (name, sizeof (name), src_name);
00410   MHD_gtls_str_cat (name, sizeof (name), ".subjectPublicKey");
00411 
00412   result = MHD__asn1_read_value (src, name, str, &len);
00413 
00414   if (result != ASN1_SUCCESS)
00415     {
00416       MHD_gnutls_assert ();
00417       MHD_gnutls_free (str);
00418       return MHD_gtls_asn2err (result);
00419     }
00420 
00421   len /= 8;
00422 
00423   switch (algo)
00424     {
00425     case MHD_GNUTLS_PK_RSA:
00426       {
00427         if ((result =
00428              MHD__gnutls_x509_read_rsa_params (str, len, params)) < 0)
00429           {
00430             MHD_gnutls_assert ();
00431             return result;
00432           }
00433 
00434         bits[0] = MHD__gnutls_mpi_get_nbits (params[0]);
00435 
00436         MHD_gtls_mpi_release (&params[0]);
00437         MHD_gtls_mpi_release (&params[1]);
00438       }
00439       break;
00440     default:
00441       MHD__gnutls_x509_log
00442         ("MHD__gnutls_x509_get_pk_algorithm: unhandled algorithm %d\n", algo);
00443     }
00444 
00445   MHD_gnutls_free (str);
00446   return algo;
00447 }
Generated by  doxygen 1.6.2-20100208