/* This function reads the RSA parameters from peer's certificate; */ int _gnutls_get_public_rsa_params(gnutls_session_t session, gnutls_pk_params_st * params) { int ret; cert_auth_info_t info; unsigned key_usage; gnutls_pcert_st peer_cert; /* normal non export case */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL || info->ncerts == 0) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_get_auth_info_pcert(&peer_cert, session->security_parameters. cert_type, info); if (ret < 0) { gnutls_assert(); return ret; } gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage); ret = check_key_usage_for_enc(session, key_usage); if (ret < 0) { gnutls_assert(); goto cleanup2; } gnutls_pk_params_init(params); ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); goto cleanup2; } gnutls_pcert_deinit(&peer_cert); return 0; cleanup2: gnutls_pcert_deinit(&peer_cert); return ret; }
/** * gnutls_certificate_free_keys: * @sc: is a #gnutls_certificate_credentials_t structure. * * This function will delete all the keys and the certificates associated * with the given credentials. This function must not be called when a * TLS negotiation that uses the credentials is in progress. * **/ void gnutls_certificate_free_keys (gnutls_certificate_credentials_t sc) { unsigned i, j; for (i = 0; i < sc->ncerts; i++) { for (j = 0; j < sc->certs[i].cert_list_length; j++) { gnutls_pcert_deinit (&sc->certs[i].cert_list[j]); } gnutls_free (sc->certs[i].cert_list); _gnutls_str_array_clear (&sc->certs[i].names); } gnutls_free (sc->certs); sc->certs = NULL; for (i = 0; i < sc->ncerts; i++) { gnutls_privkey_deinit (sc->pkey[i]); } gnutls_free (sc->pkey); sc->pkey = NULL; sc->ncerts = 0; }
/* if the peer's certificate is of 512 bits or less, returns non zero. */ int _gnutls_peers_cert_less_512 (gnutls_session_t session) { gnutls_pcert_st peer_cert; int ret; cert_auth_info_t info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return 0; } if ((ret = _gnutls_get_auth_info_pcert (&peer_cert, session->security_parameters.cert_type, info)) < 0) { gnutls_assert (); return 0; } if (gnutls_pubkey_get_pk_algorithm(peer_cert.pubkey, NULL) != GNUTLS_PK_RSA) { gnutls_assert (); gnutls_pcert_deinit (&peer_cert); return 0; } if (_gnutls_pubkey_is_over_rsa_512(peer_cert.pubkey) < 0) { gnutls_pcert_deinit (&peer_cert); return 1; } gnutls_pcert_deinit (&peer_cert); return 0; }
void doit(void) { server_check(); reset_buffers(); client_check(); if (g_pcert) { gnutls_pcert_deinit(g_pcert); gnutls_free(g_pcert); } if (g_pkey) { gnutls_privkey_deinit(g_pkey); } }
static int proc_rsa_export_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { uint16_t n_m, n_e; size_t _n_m, _n_e; uint8_t *data_m; uint8_t *data_e; int i, sigsize; gnutls_datum_t vparams, signature; int ret; ssize_t data_size = _data_size; cert_auth_info_t info; gnutls_pcert_st peer_cert; info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } i = 0; DECR_LEN (data_size, 2); n_m = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_m); data_m = &data[i]; i += n_m; DECR_LEN (data_size, 2); n_e = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_e); data_e = &data[i]; i += n_e; _n_e = n_e; _n_m = n_m; if (_gnutls_mpi_scan_nz (&session->key->rsa[0], data_m, _n_m) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key->rsa[1], data_e, _n_e) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_rsa_export_set_pubkey (session, session->key->rsa[1], session->key->rsa[0]); /* VERIFY SIGNATURE */ vparams.size = n_m + n_e + 4; vparams.data = data; DECR_LEN (data_size, 2); sigsize = _gnutls_read_uint16 (&data[vparams.size]); DECR_LEN (data_size, sigsize); signature.data = &data[vparams.size + 2]; signature.size = sigsize; if ((ret = _gnutls_get_auth_info_pcert (&peer_cert, session->security_parameters.cert_type, info)) < 0) { gnutls_assert (); return ret; } ret = _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature, GNUTLS_SIGN_UNKNOWN); gnutls_pcert_deinit (&peer_cert); if (ret < 0) { gnutls_assert (); } return ret; }
static int proc_srp_cert_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { ssize_t ret; int sigsize; gnutls_datum_t vparams, signature; ssize_t data_size; cert_auth_info_t info; gnutls_pcert_st peer_cert; uint8_t *p; gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; const version_entry_st *ver = get_version(session); if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ret = _gnutls_proc_srp_server_kx(session, data, _data_size); if (ret < 0) return ret; data_size = _data_size - ret; info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL || info->ncerts == 0) { gnutls_assert(); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } /* VERIFY SIGNATURE */ vparams.size = ret; /* all the data minus the signature */ vparams.data = data; p = &data[vparams.size]; if (_gnutls_version_has_selectable_sighash(ver)) { sign_algorithm_st aid; DECR_LEN(data_size, 1); aid.hash_algorithm = *p++; DECR_LEN(data_size, 1); aid.sign_algorithm = *p++; sign_algo = _gnutls_tls_aid_to_sign(&aid); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { _gnutls_debug_log("unknown signature %d.%d\n", aid.sign_algorithm, aid.hash_algorithm); gnutls_assert(); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } } DECR_LEN(data_size, 2); sigsize = _gnutls_read_uint16(p); DECR_LEN(data_size, sigsize); signature.data = &p[2]; signature.size = sigsize; ret = _gnutls_get_auth_info_pcert(&peer_cert, session->security_parameters. cert_type, info); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_handshake_verify_data(session, &peer_cert, &vparams, &signature, sign_algo); gnutls_pcert_deinit(&peer_cert); if (ret < 0) { gnutls_assert(); return ret; } return 0; }
static int proc_dhe_server_kx (gnutls_session_t session, uint8_t * data, size_t _data_size) { int sigsize; uint8_t *sigdata; gnutls_datum_t vparams, signature; int ret; cert_auth_info_t info = _gnutls_get_auth_info (session); ssize_t data_size = _data_size; gnutls_pcert_st peer_cert; gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; gnutls_protocol_t ver = gnutls_protocol_get_version (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } if (!_gnutls_session_is_ecc (session)) ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size); else ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size); if (ret < 0) { gnutls_assert (); return ret; } /* VERIFY SIGNATURE */ vparams.size = ret; vparams.data = data; sigdata = &data[vparams.size]; if (_gnutls_version_has_selectable_sighash (ver)) { sign_algorithm_st aid; DECR_LEN (data_size, 1); aid.hash_algorithm = *sigdata++; DECR_LEN (data_size, 1); aid.sign_algorithm = *sigdata++; sign_algo = _gnutls_tls_aid_to_sign (&aid); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { _gnutls_debug_log("unknown signature %d.%d\n", aid.sign_algorithm, aid.hash_algorithm); gnutls_assert (); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } } DECR_LEN (data_size, 2); sigsize = _gnutls_read_uint16 (sigdata); sigdata += 2; DECR_LEN (data_size, sigsize); signature.data = sigdata; signature.size = sigsize; if ((ret = _gnutls_get_auth_info_pcert (&peer_cert, session->security_parameters.cert_type, info)) < 0) { gnutls_assert (); return ret; } ret = _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature, sign_algo); gnutls_pcert_deinit (&peer_cert); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
/* Reads a base64 encoded certificate list from memory and stores it to * a gnutls_cert structure. Returns the number of certificate parsed. */ static int parse_pem_cert_mem(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *input_cert, int input_cert_size) { int size; const char *ptr; gnutls_datum_t tmp; int ret, count, i; unsigned ncerts = 0; gnutls_pcert_st *pcerts = NULL; gnutls_str_array_t names; gnutls_x509_crt_t unsorted[DEFAULT_MAX_VERIFY_DEPTH]; _gnutls_str_array_init(&names); /* move to the certificate */ ptr = memmem(input_cert, input_cert_size, PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1); if (ptr == NULL) ptr = memmem(input_cert, input_cert_size, PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1); if (ptr == NULL) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } size = input_cert_size - (ptr - input_cert); count = 0; do { tmp.data = (void *) ptr; tmp.size = size; ret = gnutls_x509_crt_init(&unsorted[count]); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_crt_import(unsorted[count], &tmp, GNUTLS_X509_FMT_PEM); if (ret < 0) { gnutls_assert(); goto cleanup; } count++; /* now we move ptr after the pem header */ ptr++; size--; /* find the next certificate (if any) */ if (size > 0) { char *ptr3; ptr3 = memmem(ptr, size, PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1); if (ptr3 == NULL) ptr3 = memmem(ptr, size, PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1); ptr = ptr3; size = input_cert_size - (ptr - input_cert); } else ptr = NULL; } while (ptr != NULL && count < DEFAULT_MAX_VERIFY_DEPTH); ret = _gnutls_get_x509_name(unsorted[0], &names); if (ret < 0) { gnutls_assert(); goto cleanup; } pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count); if (pcerts == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } ncerts = count; ret = gnutls_pcert_import_x509_list(pcerts, unsorted, &ncerts, GNUTLS_X509_CRT_LIST_SORT); if (ret < 0) { gnutls_free(pcerts); gnutls_assert(); goto cleanup; } ret = _gnutls_certificate_credential_append_keypair(res, key, names, pcerts, ncerts); if (ret < 0) { gnutls_assert(); goto cleanup; } for (i = 0; i < count; i++) gnutls_x509_crt_deinit(unsorted[i]); return ncerts; cleanup: _gnutls_str_array_clear(&names); for (i = 0; i < count; i++) gnutls_x509_crt_deinit(unsorted[i]); if (pcerts) { for (i = 0; i < count; i++) gnutls_pcert_deinit(&pcerts[i]); gnutls_free(pcerts); } return ret; }