00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <gnutls_int.h>
00026 #include "gnutls_auth_int.h"
00027 #include "gnutls_errors.h"
00028 #include <gnutls_cert.h>
00029 #include <auth_cert.h>
00030 #include "gnutls_dh.h"
00031 #include "gnutls_num.h"
00032 #include "gnutls_datum.h"
00033 #include <gnutls_pk.h>
00034 #include <gnutls_algorithms.h>
00035 #include <gnutls_global.h>
00036 #include <gnutls_record.h>
00037 #include <gnutls_sig.h>
00038 #include <gnutls_state.h>
00039 #include <gnutls_pk.h>
00040 #include <gnutls_str.h>
00041 #include <debug.h>
00042 #include <x509_b64.h>
00043 #include <gnutls_x509.h>
00044 #include <sys/types.h>
00045 #include <sys/stat.h>
00046 #include <fcntl.h>
00047
00048
00049 #include "common.h"
00050 #include "x509.h"
00051 #include "mpi.h"
00052 #include "privkey.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 inline static int
00063 check_bits (MHD_gnutls_x509_crt_t crt, unsigned int max_bits)
00064 {
00065 int ret;
00066 unsigned int bits;
00067
00068 ret = MHD_gnutls_x509_crt_get_pk_algorithm (crt, &bits);
00069 if (ret < 0)
00070 {
00071 MHD_gnutls_assert ();
00072 return ret;
00073 }
00074
00075 if (bits > max_bits && max_bits > 0)
00076 {
00077 MHD_gnutls_assert ();
00078 return GNUTLS_E_CONSTRAINT_ERROR;
00079 }
00080
00081 return 0;
00082 }
00083
00084
00085 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) { \
00086 if (peer_certificate_list[x]) \
00087 MHD_gnutls_x509_crt_deinit(peer_certificate_list[x]); \
00088 } \
00089 MHD_gnutls_free( peer_certificate_list)
00090
00091
00092
00093
00094
00095
00096
00097
00098 static int
00099 MHD__gnutls_check_key_cert_match (MHD_gtls_cert_credentials_t res)
00100 {
00101 MHD_gnutls_datum_t cid;
00102 MHD_gnutls_datum_t kid;
00103 unsigned pk = res->cert_list[res->ncerts - 1][0].subject_pk_algorithm;
00104
00105 if (res->pkey[res->ncerts - 1].pk_algorithm != pk)
00106 {
00107 MHD_gnutls_assert ();
00108 return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
00109 }
00110
00111 MHD__gnutls_x509_write_rsa_params (res->pkey[res->ncerts - 1].params,
00112 res->pkey[res->ncerts -
00113 1].params_size, &kid);
00114
00115
00116 MHD__gnutls_x509_write_rsa_params (res->
00117 cert_list[res->ncerts - 1][0].params,
00118 res->cert_list[res->ncerts -
00119 1][0].params_size, &cid);
00120
00121 if (cid.size != kid.size)
00122 {
00123 MHD_gnutls_assert ();
00124 MHD__gnutls_free_datum (&kid);
00125 MHD__gnutls_free_datum (&cid);
00126 return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
00127 }
00128
00129 if (memcmp (kid.data, cid.data, kid.size) != 0)
00130 {
00131 MHD_gnutls_assert ();
00132 MHD__gnutls_free_datum (&kid);
00133 MHD__gnutls_free_datum (&cid);
00134 return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
00135 }
00136
00137 MHD__gnutls_free_datum (&kid);
00138 MHD__gnutls_free_datum (&cid);
00139 return 0;
00140 }
00141
00142
00143
00144
00145
00146 static int
00147 parse_crt_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
00148 MHD_gnutls_x509_crt_t cert)
00149 {
00150 int i;
00151 int ret;
00152
00153 i = *ncerts + 1;
00154
00155 *cert_list =
00156 (MHD_gnutls_cert *) MHD_gtls_realloc_fast (*cert_list,
00157 i * sizeof (MHD_gnutls_cert));
00158
00159 if (*cert_list == NULL)
00160 {
00161 MHD_gnutls_assert ();
00162 return GNUTLS_E_MEMORY_ERROR;
00163 }
00164
00165 ret = MHD_gtls_x509_crt_to_gcert (&cert_list[0][i - 1], cert, 0);
00166 if (ret < 0)
00167 {
00168 MHD_gnutls_assert ();
00169 return ret;
00170 }
00171
00172 *ncerts = i;
00173
00174 return 1;
00175 }
00176
00177
00178
00179
00180
00181 static int
00182 parse_der_cert_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
00183 const void *input_cert, int input_cert_size)
00184 {
00185 MHD_gnutls_datum_t tmp;
00186 MHD_gnutls_x509_crt_t cert;
00187 int ret;
00188
00189 ret = MHD_gnutls_x509_crt_init (&cert);
00190 if (ret < 0)
00191 {
00192 MHD_gnutls_assert ();
00193 return ret;
00194 }
00195
00196 tmp.data = (opaque *) input_cert;
00197 tmp.size = input_cert_size;
00198
00199 ret = MHD_gnutls_x509_crt_import (cert, &tmp, GNUTLS_X509_FMT_DER);
00200 if (ret < 0)
00201 {
00202 MHD_gnutls_assert ();
00203 MHD_gnutls_x509_crt_deinit (cert);
00204 return ret;
00205 }
00206
00207 ret = parse_crt_mem (cert_list, ncerts, cert);
00208 MHD_gnutls_x509_crt_deinit (cert);
00209
00210 return ret;
00211 }
00212
00213
00214
00215
00216 static int
00217 parse_pem_cert_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
00218 const char *input_cert, int input_cert_size)
00219 {
00220 int size, siz2, i;
00221 const char *ptr;
00222 opaque *ptr2;
00223 MHD_gnutls_datum_t tmp;
00224 int ret, count;
00225
00226
00227
00228 ptr = memmem (input_cert, input_cert_size,
00229 PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
00230 if (ptr == NULL)
00231 ptr = memmem (input_cert, input_cert_size,
00232 PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);
00233
00234 if (ptr == NULL)
00235 {
00236 MHD_gnutls_assert ();
00237 return GNUTLS_E_BASE64_DECODING_ERROR;
00238 }
00239 size = input_cert_size - (ptr - input_cert);
00240
00241 i = *ncerts + 1;
00242 count = 0;
00243
00244 do
00245 {
00246
00247 siz2 =
00248 MHD__gnutls_fbase64_decode (NULL, (const unsigned char *) ptr, size,
00249 &ptr2);
00250
00251 if (siz2 < 0)
00252 {
00253 MHD_gnutls_assert ();
00254 return GNUTLS_E_BASE64_DECODING_ERROR;
00255 }
00256
00257 *cert_list =
00258 (MHD_gnutls_cert *) MHD_gtls_realloc_fast (*cert_list,
00259 i *
00260 sizeof (MHD_gnutls_cert));
00261
00262 if (*cert_list == NULL)
00263 {
00264 MHD_gnutls_assert ();
00265 return GNUTLS_E_MEMORY_ERROR;
00266 }
00267
00268 tmp.data = ptr2;
00269 tmp.size = siz2;
00270
00271 ret = MHD_gtls_x509_raw_cert_to_gcert (&cert_list[0][i - 1], &tmp, 0);
00272 if (ret < 0)
00273 {
00274 MHD_gnutls_assert ();
00275 return ret;
00276 }
00277 MHD__gnutls_free_datum (&tmp);
00278
00279
00280
00281 ptr++;
00282
00283
00284 size = input_cert_size - (ptr - input_cert);
00285
00286 if (size > 0)
00287 {
00288 char *ptr3;
00289
00290 ptr3 = memmem (ptr, size, PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
00291 if (ptr3 == NULL)
00292 ptr3 = memmem (ptr, size, PEM_CERT_SEP2,
00293 sizeof (PEM_CERT_SEP2) - 1);
00294
00295 ptr = ptr3;
00296 }
00297 else
00298 ptr = NULL;
00299
00300 i++;
00301 count++;
00302
00303 }
00304 while (ptr != NULL);
00305
00306 *ncerts = i - 1;
00307
00308 return count;
00309 }
00310
00311
00312
00313
00314
00315 static int
00316 read_cert_mem (MHD_gtls_cert_credentials_t res, const void *cert,
00317 int cert_size, MHD_gnutls_x509_crt_fmt_t type)
00318 {
00319 int ret;
00320
00321
00322
00323 res->cert_list = MHD_gtls_realloc_fast (res->cert_list,
00324 (1 +
00325 res->ncerts) *
00326 sizeof (MHD_gnutls_cert *));
00327 if (res->cert_list == NULL)
00328 {
00329 MHD_gnutls_assert ();
00330 return GNUTLS_E_MEMORY_ERROR;
00331 }
00332
00333 res->cert_list_length = MHD_gtls_realloc_fast (res->cert_list_length,
00334 (1 +
00335 res->ncerts) *
00336 sizeof (int));
00337 if (res->cert_list_length == NULL)
00338 {
00339 MHD_gnutls_assert ();
00340 return GNUTLS_E_MEMORY_ERROR;
00341 }
00342
00343 res->cert_list[res->ncerts] = NULL;
00344 res->cert_list_length[res->ncerts] = 0;
00345
00346 if (type == GNUTLS_X509_FMT_DER)
00347 ret = parse_der_cert_mem (&res->cert_list[res->ncerts],
00348 &res->cert_list_length[res->ncerts],
00349 cert, cert_size);
00350 else
00351 ret =
00352 parse_pem_cert_mem (&res->cert_list[res->ncerts],
00353 &res->cert_list_length[res->ncerts], cert,
00354 cert_size);
00355
00356 if (ret < 0)
00357 {
00358 MHD_gnutls_assert ();
00359 return ret;
00360 }
00361
00362 return ret;
00363 }
00364
00365
00366 int
00367 MHD__gnutls_x509_privkey_to_gkey (MHD_gnutls_privkey * dest,
00368 MHD_gnutls_x509_privkey_t src)
00369 {
00370 int i, ret;
00371
00372 memset (dest, 0, sizeof (MHD_gnutls_privkey));
00373
00374 for (i = 0; i < src->params_size; i++)
00375 {
00376 dest->params[i] = MHD__gnutls_mpi_copy (src->params[i]);
00377 if (dest->params[i] == NULL)
00378 {
00379 MHD_gnutls_assert ();
00380 ret = GNUTLS_E_MEMORY_ERROR;
00381 goto cleanup;
00382 }
00383 }
00384
00385 dest->pk_algorithm = src->pk_algorithm;
00386 dest->params_size = src->params_size;
00387
00388 return 0;
00389
00390 cleanup:
00391
00392 for (i = 0; i < src->params_size; i++)
00393 {
00394 MHD_gtls_mpi_release (&dest->params[i]);
00395 }
00396 return ret;
00397 }
00398
00399 void
00400 MHD_gtls_gkey_deinit (MHD_gnutls_privkey * key)
00401 {
00402 int i;
00403 if (key == NULL)
00404 return;
00405
00406 for (i = 0; i < key->params_size; i++)
00407 {
00408 MHD_gtls_mpi_release (&key->params[i]);
00409 }
00410 }
00411
00412 int
00413 MHD__gnutls_x509_raw_privkey_to_gkey (MHD_gnutls_privkey * privkey,
00414 const MHD_gnutls_datum_t * raw_key,
00415 MHD_gnutls_x509_crt_fmt_t type)
00416 {
00417 MHD_gnutls_x509_privkey_t tmpkey;
00418 int ret;
00419
00420 ret = MHD_gnutls_x509_privkey_init (&tmpkey);
00421 if (ret < 0)
00422 {
00423 MHD_gnutls_assert ();
00424 return ret;
00425 }
00426
00427 ret = MHD_gnutls_x509_privkey_import (tmpkey, raw_key, type);
00428 if (ret < 0)
00429 {
00430 MHD_gnutls_assert ();
00431 MHD_gnutls_x509_privkey_deinit (tmpkey);
00432 return ret;
00433 }
00434
00435 ret = MHD__gnutls_x509_privkey_to_gkey (privkey, tmpkey);
00436 if (ret < 0)
00437 {
00438 MHD_gnutls_assert ();
00439 MHD_gnutls_x509_privkey_deinit (tmpkey);
00440 return ret;
00441 }
00442
00443 MHD_gnutls_x509_privkey_deinit (tmpkey);
00444
00445 return 0;
00446 }
00447
00448
00449
00450
00451
00452 static int
00453 read_key_mem (MHD_gtls_cert_credentials_t res,
00454 const void *key, int key_size, MHD_gnutls_x509_crt_fmt_t type)
00455 {
00456 int ret;
00457 MHD_gnutls_datum_t tmp;
00458
00459
00460
00461 res->pkey =
00462 MHD_gtls_realloc_fast (res->pkey,
00463 (res->ncerts + 1) * sizeof (MHD_gnutls_privkey));
00464 if (res->pkey == NULL)
00465 {
00466 MHD_gnutls_assert ();
00467 return GNUTLS_E_MEMORY_ERROR;
00468 }
00469
00470 if (key)
00471 {
00472 tmp.data = (opaque *) key;
00473 tmp.size = key_size;
00474
00475 ret =
00476 MHD__gnutls_x509_raw_privkey_to_gkey (&res->pkey[res->ncerts], &tmp,
00477 type);
00478 if (ret < 0)
00479 {
00480 MHD_gnutls_assert ();
00481 return ret;
00482 }
00483 }
00484 else
00485 memset (&res->pkey[res->ncerts], 0, sizeof (MHD_gnutls_privkey));
00486
00487 return 0;
00488 }
00489
00520 int
00521 MHD__gnutls_certificate_set_x509_key_mem (MHD_gtls_cert_credentials_t
00522 res,
00523 const MHD_gnutls_datum_t * cert,
00524 const MHD_gnutls_datum_t * key,
00525 MHD_gnutls_x509_crt_fmt_t type)
00526 {
00527 int ret;
00528
00529
00530
00531 if ((ret = read_key_mem (res, key ? key->data : NULL,
00532 key ? key->size : 0, type)) < 0)
00533 return ret;
00534
00535 if ((ret = read_cert_mem (res, cert->data, cert->size, type)) < 0)
00536 return ret;
00537
00538 res->ncerts++;
00539
00540 if (key && (ret = MHD__gnutls_check_key_cert_match (res)) < 0)
00541 {
00542 MHD_gnutls_assert ();
00543 return ret;
00544 }
00545
00546 return 0;
00547 }
00548
00549
00550
00551
00552 int
00553 MHD__gnutls_check_key_usage (const MHD_gnutls_cert * cert,
00554 enum MHD_GNUTLS_KeyExchangeAlgorithm alg)
00555 {
00556 unsigned int key_usage = 0;
00557 int encipher_type;
00558
00559 if (cert == NULL)
00560 {
00561 MHD_gnutls_assert ();
00562 return GNUTLS_E_INTERNAL_ERROR;
00563 }
00564
00565 if (MHD_gtls_map_kx_get_cred (alg, 1) == MHD_GNUTLS_CRD_CERTIFICATE ||
00566 MHD_gtls_map_kx_get_cred (alg, 0) == MHD_GNUTLS_CRD_CERTIFICATE)
00567 {
00568
00569 key_usage = cert->key_usage;
00570
00571 encipher_type = MHD_gtls_kx_encipher_type (alg);
00572
00573 if (key_usage != 0 && encipher_type != CIPHER_IGN)
00574 {
00575
00576
00577
00578 if (encipher_type == CIPHER_ENCRYPT)
00579 {
00580
00581
00582
00583
00584 if (!(key_usage & KEY_KEY_ENCIPHERMENT))
00585 {
00586 MHD_gnutls_assert ();
00587 return GNUTLS_E_KEY_USAGE_VIOLATION;
00588 }
00589 }
00590
00591 if (encipher_type == CIPHER_SIGN)
00592 {
00593
00594
00595 if (!(key_usage & KEY_DIGITAL_SIGNATURE))
00596 {
00597 MHD_gnutls_assert ();
00598 return GNUTLS_E_KEY_USAGE_VIOLATION;
00599 }
00600 }
00601 }
00602 }
00603 return 0;
00604 }