Exemple #1
0
/**
 * gnutls_fingerprint:
 * @algo: is a digest algorithm
 * @data: is the data
 * @result: is the place where the result will be copied (may be null).
 * @result_size: should hold the size of the result. The actual size
 * of the returned result will also be copied there.
 *
 * This function will calculate a fingerprint (actually a hash), of
 * the given data.  The result is not printable data.  You should
 * convert it to hex, or to something else printable.
 *
 * This is the usual way to calculate a fingerprint of an X.509 DER
 * encoded certificate.  Note however that the fingerprint of an
 * OpenPGP certificate is not just a hash and cannot be calculated with this
 * function.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_fingerprint(gnutls_digest_algorithm_t algo,
		   const gnutls_datum_t * data, void *result,
		   size_t * result_size)
{
	int ret;
	int hash_len = _gnutls_hash_get_algo_len(hash_to_entry(algo));

	if (hash_len < 0 || (unsigned) hash_len > *result_size
	    || result == NULL) {
		*result_size = hash_len;
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}
	*result_size = hash_len;

	if (result) {
		ret =
		    _gnutls_hash_fast(algo, data->data, data->size,
				      result);
		if (ret < 0)
			return gnutls_assert_val(ret);
	}

	return 0;
}
Exemple #2
0
/**
 * gnutls_encode_ber_digest_info:
 * @info: an RSA BER encoded DigestInfo structure
 * @hash: the hash algorithm that was used to get the digest
 * @digest: must contain the digest data
 * @output: will contain the allocated DigestInfo BER encoded data
 *
 * This function will encode the provided digest data, and its
 * algorithm into an RSA PKCS#1 1.5 DigestInfo structure. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 *
 * Since: 3.5.0
 *
 **/
int
gnutls_encode_ber_digest_info(gnutls_digest_algorithm_t hash,
			      const gnutls_datum_t * digest,
			      gnutls_datum_t * output)
{
	const mac_entry_st *e = hash_to_entry(hash);
	if (unlikely(e == NULL))
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	return encode_ber_digest_info(e , digest, output);
}
Exemple #3
0
/**
 * gnutls_sign_is_secure:
 * @algorithm: is a sign algorithm
 *
 * Returns: Non-zero if the provided signature algorithm is considered to be secure.
 **/
int gnutls_sign_is_secure(gnutls_sign_algorithm_t algorithm)
{
	gnutls_sign_algorithm_t sign = algorithm;
	gnutls_digest_algorithm_t dig = GNUTLS_DIG_UNKNOWN;

	/* avoid prefix */
	GNUTLS_SIGN_ALG_LOOP(dig = p->mac);

	if (dig != GNUTLS_DIG_UNKNOWN)
		return _gnutls_digest_is_secure(hash_to_entry(dig));

	return 0;
}
Exemple #4
0
/**
 * gnutls_store_commitment:
 * @db_name: A file specifying the stored keys (use NULL for the default)
 * @tdb: A storage structure or NULL to use the default
 * @host: The peer's name
 * @service: non-NULL if this key is specific to a service (e.g. http)
 * @hash_algo: The hash algorithm type
 * @hash: The raw hash
 * @expiration: The expiration time (use 0 to disable expiration)
 * @flags: should be 0.
 *
 * This function will store the provided hash commitment to 
 * the list of stored public keys. The key with the given
 * hash will be considered valid until the provided expiration time.
 *
 * The @store variable if non-null specifies a custom backend for
 * the storage of entries. If it is NULL then the
 * default file backend will be used.
 *
 * Note that this function is not thread safe with the default backend.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_store_commitment(const char *db_name,
			gnutls_tdb_t tdb,
			const char *host,
			const char *service,
			gnutls_digest_algorithm_t hash_algo,
			const gnutls_datum_t * hash,
			time_t expiration, unsigned int flags)
{
	FILE *fd = NULL;
	int ret;
	char local_file[MAX_FILENAME];
	const mac_entry_st *me = hash_to_entry(hash_algo);

	if (me == NULL || _gnutls_digest_is_secure(me) == 0)
		return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

	if (_gnutls_hash_get_algo_len(me) != hash->size)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	if (db_name == NULL && tdb == NULL) {
		ret =
		    _gnutls_find_config_path(local_file,
					     sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_debug_log("Configuration path: %s\n", local_file);
		mkdir(local_file, 0700);

		ret = find_config_file(local_file, sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);
		db_name = local_file;
	}

	if (tdb == NULL)
		tdb = &default_tdb;

	_gnutls_debug_log("Configuration file: %s\n", db_name);

	tdb->cstore(db_name, host, service, expiration, 
		(gnutls_digest_algorithm_t)me->id, hash);

	ret = 0;

	if (fd != NULL)
		fclose(fd);

	return ret;
}
Exemple #5
0
/**
 * gnutls_x509_privkey_sign_data:
 * @key: Holds the key
 * @digest: should be MD5 or SHA1
 * @flags: should be 0 for now
 * @data: holds the data to be signed
 * @signature: will contain the signature
 * @signature_size: holds the size of signature (and will be replaced
 *   by the new size)
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
 *
 * If the buffer provided is not long enough to hold the output, then
 * *@signature_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
 * be returned.
 *
 * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Deprecated: Use gnutls_privkey_sign_data().
 */
int
gnutls_x509_privkey_sign_data(gnutls_x509_privkey_t key,
			      gnutls_digest_algorithm_t digest,
			      unsigned int flags,
			      const gnutls_datum_t * data,
			      void *signature, size_t * signature_size)
{
	int result;
	gnutls_datum_t sig = { NULL, 0 };
	gnutls_datum_t hash;
	const mac_entry_st *me = hash_to_entry(digest);

	if (key == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	result =
	    pk_hash_data(key->pk_algorithm, me, &key->params, data, &hash);
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	result =
	    _gnutls_x509_privkey_sign_hash2(key, me, flags, &hash, &sig);

	_gnutls_free_datum(&hash);

	if (result < 0) {
		gnutls_assert();
		return result;
	}

	if (*signature_size < sig.size) {
		*signature_size = sig.size;
		_gnutls_free_datum(&sig);
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	*signature_size = sig.size;
	memcpy(signature, sig.data, sig.size);

	_gnutls_free_datum(&sig);

	return 0;
}
Exemple #6
0
/* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
 */
static int
_gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
				  gnutls_pcert_st * cert,
				  gnutls_privkey_t pkey,
				  gnutls_datum_t * signature)
{
	gnutls_datum_t dconcat;
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	gnutls_sign_algorithm_t sign_algo;
	const mac_entry_st *me;

	sign_algo = _gnutls_session_get_sign_algo(session, cert);
	if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	gnutls_sign_algorithm_set_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	_gnutls_debug_log("sign handshake cert vrfy: picked %s with %s\n",
			  gnutls_sign_algorithm_get_name(sign_algo),
			  _gnutls_mac_get_name(me));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.handshake_hash_buffer.
			      length, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

	dconcat.data = concat;
	dconcat.size = _gnutls_hash_get_algo_len(me);

	ret = sign_tls_hash(session, me, cert, pkey, &dconcat, signature);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return sign_algo;
}
Exemple #7
0
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
				    gnutls_pcert_st * cert,
				    gnutls_datum_t * signature,
				    gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_HASH_SIZE];
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
	const mac_entry_st *me;

	ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_sign_algorithm_set_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.
			      handshake_hash_buffer_prev_len, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

	dconcat.data = concat;
	dconcat.size = _gnutls_hash_get_algo_len(me);

	ret =
	    verify_tls_hash(session, ver, cert, &dconcat, signature, 0,
			    sign_algo, pk);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}
Exemple #8
0
/**
 * gnutls_privkey_sign_hash:
 * @signer: Holds the signer's key
 * @hash_algo: The hash algorithm used
 * @flags: Zero or one of %gnutls_privkey_flags_t
 * @hash_data: holds the data to be signed
 * @signature: will contain newly allocated signature
 *
 * This function will sign the given hashed data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
 *
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Note that if %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA flag is specified this function
 * will ignore @hash_algo and perform a raw PKCS1 signature.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_privkey_sign_hash(gnutls_privkey_t signer,
			 gnutls_digest_algorithm_t hash_algo,
			 unsigned int flags,
			 const gnutls_datum_t * hash_data,
			 gnutls_datum_t * signature)
{
	int ret;
	gnutls_datum_t digest;

	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
		return _gnutls_privkey_sign_raw_data(signer, flags,
						    hash_data, signature);

	digest.data = gnutls_malloc(hash_data->size);
	if (digest.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}
	digest.size = hash_data->size;
	memcpy(digest.data, hash_data->data, digest.size);

	ret =
	    pk_prepare_hash(signer->pk_algorithm, hash_to_entry(hash_algo),
			    &digest);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_privkey_sign_raw_data(signer, flags, &digest, signature);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;

 cleanup:
	_gnutls_free_datum(&digest);
	return ret;
}
Exemple #9
0
/**
 * gnutls_privkey_sign_data:
 * @signer: Holds the key
 * @hash: should be a digest algorithm
 * @flags: Zero or one of %gnutls_privkey_flags_t
 * @data: holds the data to be signed
 * @signature: will contain the signature allocated with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only the SHA family for the DSA keys.
 *
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 * negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_privkey_sign_data(gnutls_privkey_t signer,
			 gnutls_digest_algorithm_t hash,
			 unsigned int flags,
			 const gnutls_datum_t * data,
			 gnutls_datum_t * signature)
{
	int ret;
	gnutls_datum_t digest;
	const mac_entry_st *me = hash_to_entry(hash);

	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = pk_prepare_hash(signer->pk_algorithm, me, &digest);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_privkey_sign_raw_data(signer, flags, &digest, signature);
	_gnutls_free_datum(&digest);

	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return 0;

 cleanup:
	_gnutls_free_datum(&digest);
	return ret;
}
Exemple #10
0
static void print_req(gnutls_buffer_st * str, gnutls_ocsp_req_t req)
{
	int ret;
	unsigned indx;

	/* Version. */
	{
		int version = gnutls_ocsp_req_get_version(req);
		if (version < 0)
			addf(str, "error: get_version: %s\n",
			     gnutls_strerror(version));
		else
			addf(str, _("\tVersion: %d\n"), version);
	}

	/* XXX requestorName */

	/* requestList */
	addf(str, "\tRequest List:\n");
	for (indx = 0;; indx++) {
		gnutls_digest_algorithm_t digest;
		gnutls_datum_t in, ik, sn;

		ret =
		    gnutls_ocsp_req_get_cert_id(req, indx, &digest, &in,
						&ik, &sn);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		addf(str, "\t\tCertificate ID:\n");
		if (ret != GNUTLS_E_SUCCESS) {
			addf(str, "error: get_cert_id: %s\n",
			     gnutls_strerror(ret));
			continue;
		}
		addf(str, "\t\t\tHash Algorithm: %s\n",
		     _gnutls_digest_get_name(hash_to_entry(digest)));

		adds(str, "\t\t\tIssuer Name Hash: ");
		_gnutls_buffer_hexprint(str, in.data, in.size);
		adds(str, "\n");

		adds(str, "\t\t\tIssuer Key Hash: ");
		_gnutls_buffer_hexprint(str, ik.data, ik.size);
		adds(str, "\n");

		adds(str, "\t\t\tSerial Number: ");
		_gnutls_buffer_hexprint(str, sn.data, sn.size);
		adds(str, "\n");

		gnutls_free(in.data);
		gnutls_free(ik.data);
		gnutls_free(sn.data);

		/* XXX singleRequestExtensions */
	}

	for (indx = 0;; indx++) {
		gnutls_datum_t oid;
		unsigned int critical;
		gnutls_datum_t data;

		ret =
		    gnutls_ocsp_req_get_extension(req, indx, &oid,
						  &critical, &data);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		else if (ret != GNUTLS_E_SUCCESS) {
			addf(str, "error: get_extension: %s\n",
			     gnutls_strerror(ret));
			continue;
		}
		if (indx == 0)
			adds(str, "\tExtensions:\n");

		if (oid.size == sizeof(GNUTLS_OCSP_NONCE) &&
		    memcmp(oid.data, GNUTLS_OCSP_NONCE, oid.size) == 0) {
			gnutls_datum_t nonce;
			unsigned int ncrit;

			ret =
			    gnutls_ocsp_req_get_nonce(req, &ncrit,
						      &nonce);
			if (ret != GNUTLS_E_SUCCESS) {
				addf(str, "error: get_nonce: %s\n",
				     gnutls_strerror(ret));
			} else {
				addf(str, "\t\tNonce%s: ",
				     ncrit ? " (critical)" : "");
				_gnutls_buffer_hexprint(str, nonce.data,
							nonce.size);
				adds(str, "\n");
				gnutls_free(nonce.data);
			}
		} else {
			addf(str, "\t\tUnknown extension %s (%s):\n",
			     oid.data,
			     critical ? "critical" : "not critical");

			adds(str, _("\t\t\tASCII: "));
			_gnutls_buffer_asciiprint(str, (char *) data.data,
						  data.size);
			addf(str, "\n");

			adds(str, _("\t\t\tHexdump: "));
			_gnutls_buffer_hexprint(str, (char *) data.data,
						data.size);
			adds(str, "\n");
		}

		gnutls_free(oid.data);
		gnutls_free(data.data);
	}

	/* XXX Signature */
}
Exemple #11
0
static void
print_resp(gnutls_buffer_st * str, gnutls_ocsp_resp_t resp,
	   gnutls_ocsp_print_formats_t format)
{
	int ret;
	unsigned indx;

	ret = gnutls_ocsp_resp_get_status(resp);
	if (ret < 0) {
		addf(str, "error: ocsp_resp_get_status: %s\n",
		     gnutls_strerror(ret));
		return;
	}

	adds(str, "\tResponse Status: ");
	switch (ret) {
	case GNUTLS_OCSP_RESP_SUCCESSFUL:
		adds(str, "Successful\n");
		break;

	case GNUTLS_OCSP_RESP_MALFORMEDREQUEST:
		adds(str, "malformedRequest\n");
		return;

	case GNUTLS_OCSP_RESP_INTERNALERROR:
		adds(str, "internalError\n");
		return;

	case GNUTLS_OCSP_RESP_TRYLATER:
		adds(str, "tryLater\n");
		return;

	case GNUTLS_OCSP_RESP_SIGREQUIRED:
		adds(str, "sigRequired\n");
		return;

	case GNUTLS_OCSP_RESP_UNAUTHORIZED:
		adds(str, "unauthorized\n");
		return;

	default:
		adds(str, "unknown\n");
		return;
	}

	{
		gnutls_datum_t oid;

		ret = gnutls_ocsp_resp_get_response(resp, &oid, NULL);
		if (ret < 0) {
			addf(str, "error: get_response: %s\n",
			     gnutls_strerror(ret));
			return;
		}

		adds(str, "\tResponse Type: ");
#define OCSP_BASIC "1.3.6.1.5.5.7.48.1.1"

		if (oid.size == sizeof(OCSP_BASIC)
		    && memcmp(oid.data, OCSP_BASIC, oid.size) == 0) {
			adds(str, "Basic OCSP Response\n");
			gnutls_free(oid.data);
		} else {
			addf(str, "Unknown response type (%.*s)\n",
			     oid.size, oid.data);
			gnutls_free(oid.data);
			return;
		}
	}

	/* Version. */
	{
		int version = gnutls_ocsp_resp_get_version(resp);
		if (version < 0)
			addf(str, "error: get_version: %s\n",
			     gnutls_strerror(version));
		else
			addf(str, _("\tVersion: %d\n"), version);
	}

	/* responderID */
	{
		gnutls_datum_t dn;

		ret = gnutls_ocsp_resp_get_responder(resp, &dn);
		if (ret < 0 || dn.data == NULL) {
			if (dn.data == 0) {
				ret = gnutls_ocsp_resp_get_responder_raw_id(resp, GNUTLS_OCSP_RESP_ID_KEY, &dn);

				if (ret >= 0) {
					addf(str, _("\tResponder Key ID: "));
					_gnutls_buffer_hexprint(str, dn.data, dn.size);
					adds(str, "\n");
				}
				gnutls_free(dn.data);
			} else {
				addf(str, "error: get_dn: %s\n",
				     gnutls_strerror(ret));
			}
		} else {
			if (dn.data != NULL) {
				addf(str, _("\tResponder ID: %.*s\n"), dn.size,
				     dn.data);
				gnutls_free(dn.data);
			}
		}
	}

	{
		char s[42];
		size_t max = sizeof(s);
		struct tm t;
		time_t tim = gnutls_ocsp_resp_get_produced(resp);

		if (tim == (time_t) - 1)
			addf(str, "error: ocsp_resp_get_produced\n");
		else if (gmtime_r(&tim, &t) == NULL)
			addf(str, "error: gmtime_r (%ld)\n",
			     (unsigned long) tim);
		else if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t)
			 == 0)
			addf(str, "error: strftime (%ld)\n",
			     (unsigned long) tim);
		else
			addf(str, _("\tProduced At: %s\n"), s);
	}

	addf(str, "\tResponses:\n");
	for (indx = 0;; indx++) {
		gnutls_digest_algorithm_t digest;
		gnutls_datum_t in, ik, sn;
		unsigned int cert_status;
		time_t this_update;
		time_t next_update;
		time_t revocation_time;
		unsigned int revocation_reason;

		ret = gnutls_ocsp_resp_get_single(resp,
						  indx,
						  &digest, &in, &ik, &sn,
						  &cert_status,
						  &this_update,
						  &next_update,
						  &revocation_time,
						  &revocation_reason);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		addf(str, "\t\tCertificate ID:\n");
		if (ret != GNUTLS_E_SUCCESS) {
			addf(str, "error: get_singleresponse: %s\n",
			     gnutls_strerror(ret));
			continue;
		}
		addf(str, "\t\t\tHash Algorithm: %s\n",
		     _gnutls_digest_get_name(hash_to_entry(digest)));

		adds(str, "\t\t\tIssuer Name Hash: ");
		_gnutls_buffer_hexprint(str, in.data, in.size);
		adds(str, "\n");

		adds(str, "\t\t\tIssuer Key Hash: ");
		_gnutls_buffer_hexprint(str, ik.data, ik.size);
		adds(str, "\n");

		adds(str, "\t\t\tSerial Number: ");
		_gnutls_buffer_hexprint(str, sn.data, sn.size);
		adds(str, "\n");

		gnutls_free(in.data);
		gnutls_free(ik.data);
		gnutls_free(sn.data);

		{
			const char *p = NULL;

			switch (cert_status) {
			case GNUTLS_OCSP_CERT_GOOD:
				p = "good";
				break;

			case GNUTLS_OCSP_CERT_REVOKED:
				p = "revoked";
				break;

			case GNUTLS_OCSP_CERT_UNKNOWN:
				p = "unknown";
				break;

			default:
				addf(str,
				     "\t\tCertificate Status: unexpected value %d\n",
				     cert_status);
				break;
			}

			if (p)
				addf(str, "\t\tCertificate Status: %s\n",
				     p);
		}

		/* XXX revocation reason */

		if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
			char s[42];
			size_t max = sizeof(s);
			struct tm t;

			if (revocation_time == (time_t) - 1)
				addf(str, "error: revocation_time\n");
			else if (gmtime_r(&revocation_time, &t) == NULL)
				addf(str, "error: gmtime_r (%ld)\n",
				     (unsigned long) revocation_time);
			else if (strftime
				 (s, max, "%a %b %d %H:%M:%S UTC %Y",
				  &t) == 0)
				addf(str, "error: strftime (%ld)\n",
				     (unsigned long) revocation_time);
			else
				addf(str, _("\t\tRevocation time: %s\n"),
				     s);
		}

		{
			char s[42];
			size_t max = sizeof(s);
			struct tm t;

			if (this_update == (time_t) - 1)
				addf(str, "error: this_update\n");
			else if (gmtime_r(&this_update, &t) == NULL)
				addf(str, "error: gmtime_r (%ld)\n",
				     (unsigned long) this_update);
			else if (strftime
				 (s, max, "%a %b %d %H:%M:%S UTC %Y",
				  &t) == 0)
				addf(str, "error: strftime (%ld)\n",
				     (unsigned long) this_update);
			else
				addf(str, _("\t\tThis Update: %s\n"), s);
		}

		{
			char s[42];
			size_t max = sizeof(s);
			struct tm t;

			if (next_update != (time_t) - 1) {
				if (gmtime_r(&next_update, &t) == NULL)
					addf(str, "error: gmtime_r (%ld)\n",
					     (unsigned long) next_update);
				else if (strftime
					 (s, max, "%a %b %d %H:%M:%S UTC %Y",
					  &t) == 0)
					addf(str, "error: strftime (%ld)\n",
					     (unsigned long) next_update);
				else
					addf(str, _("\t\tNext Update: %s\n"), s);
			}
		}

		/* XXX singleRequestExtensions */
	}

	adds(str, "\tExtensions:\n");
	for (indx = 0;; indx++) {
		gnutls_datum_t oid;
		unsigned int critical;
		gnutls_datum_t data;

		ret =
		    gnutls_ocsp_resp_get_extension(resp, indx, &oid,
						   &critical, &data);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		else if (ret != GNUTLS_E_SUCCESS) {
			addf(str, "error: get_extension: %s\n",
			     gnutls_strerror(ret));
			continue;
		}

		if (oid.size == sizeof(GNUTLS_OCSP_NONCE) &&
		    memcmp(oid.data, GNUTLS_OCSP_NONCE, oid.size) == 0) {
			gnutls_datum_t nonce;
			unsigned int ncrit;

			ret =
			    gnutls_ocsp_resp_get_nonce(resp, &ncrit,
						       &nonce);
			if (ret != GNUTLS_E_SUCCESS) {
				addf(str, "error: get_nonce: %s\n",
				     gnutls_strerror(ret));
			} else {
				addf(str, "\t\tNonce%s: ",
				     ncrit ? " (critical)" : "");
				_gnutls_buffer_hexprint(str, nonce.data,
							nonce.size);
				adds(str, "\n");
				gnutls_free(nonce.data);
			}
		} else {
			addf(str, "\t\tUnknown extension %s (%s):\n",
			     oid.data,
			     critical ? "critical" : "not critical");

			adds(str, _("\t\t\tASCII: "));
			_gnutls_buffer_asciiprint(str, (char *) data.data,
						  data.size);
			addf(str, "\n");

			adds(str, _("\t\t\tHexdump: "));
			_gnutls_buffer_hexprint(str, (char *) data.data,
						data.size);
			adds(str, "\n");
		}

		gnutls_free(oid.data);
		gnutls_free(data.data);
	}

	/* Signature. */
	if (format == GNUTLS_OCSP_PRINT_FULL) {
		gnutls_datum_t sig;

		ret = gnutls_ocsp_resp_get_signature_algorithm(resp);
		if (ret < 0)
			addf(str, "error: get_signature_algorithm: %s\n",
			     gnutls_strerror(ret));
		else {
			const char *name =
			    gnutls_sign_algorithm_get_name(ret);
			if (name == NULL)
				name = _("unknown");
			addf(str, _("\tSignature Algorithm: %s\n"), name);
		}
		if (ret != GNUTLS_SIGN_UNKNOWN && gnutls_sign_is_secure(ret) == 0) {
			adds(str,
			     _("warning: signed using a broken signature "
			       "algorithm that can be forged.\n"));
		}

		ret = gnutls_ocsp_resp_get_signature(resp, &sig);
		if (ret < 0)
			addf(str, "error: get_signature: %s\n",
			     gnutls_strerror(ret));
		else {
			adds(str, _("\tSignature:\n"));
			_gnutls_buffer_hexdump(str, sig.data, sig.size,
					       "\t\t");

			gnutls_free(sig.data);
		}
	}

	/* certs */
	if (format == GNUTLS_OCSP_PRINT_FULL) {
		gnutls_x509_crt_t *certs;
		size_t ncerts, i;
		gnutls_datum_t out;

		ret = gnutls_ocsp_resp_get_certs(resp, &certs, &ncerts);
		if (ret < 0)
			addf(str, "error: get_certs: %s\n",
			     gnutls_strerror(ret));
		else {
			if (ncerts > 0)
				addf(str, "\tAdditional certificates:\n");

			for (i = 0; i < ncerts; i++) {
				size_t s = 0;

				ret =
				    gnutls_x509_crt_print(certs[i],
							  GNUTLS_CRT_PRINT_FULL,
							  &out);
				if (ret < 0)
					addf(str, "error: crt_print: %s\n",
					     gnutls_strerror(ret));
				else {
					addf(str, "%.*s", out.size,
					     out.data);
					gnutls_free(out.data);
				}

				ret =
				    gnutls_x509_crt_export(certs[i],
							   GNUTLS_X509_FMT_PEM,
							   NULL, &s);
				if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
					addf(str,
					     "error: crt_export: %s\n",
					     gnutls_strerror(ret));
				else {
					out.data = gnutls_malloc(s);
					if (out.data == NULL)
						addf(str,
						     "error: malloc: %s\n",
						     gnutls_strerror
						     (GNUTLS_E_MEMORY_ERROR));
					else {
						ret =
						    gnutls_x509_crt_export
						    (certs[i],
						     GNUTLS_X509_FMT_PEM,
						     out.data, &s);
						if (ret < 0)
							addf(str,
							     "error: crt_export: %s\n",
							     gnutls_strerror
							     (ret));
						else {
							out.size = s;
							addf(str, "%.*s",
							     out.size,
							     out.data);
						}
						gnutls_free(out.data);
					}
				}

				gnutls_x509_crt_deinit(certs[i]);
			}
			gnutls_free(certs);
		}
	}
}
Exemple #12
0
/* verifies if the certificate is properly signed.
 * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
 * 
 * 'data' is the signed data
 * 'signature' is the signature!
 */
static int
_gnutls_x509_verify_data(gnutls_sign_algorithm_t sign,
			 const gnutls_datum_t * data,
			 const gnutls_datum_t * signature,
			 gnutls_x509_crt_t cert,
			 gnutls_x509_crt_t issuer,
			 unsigned vflags)
{
	gnutls_pk_params_st params;
	gnutls_pk_algorithm_t issuer_pk;
	int ret;
	gnutls_x509_spki_st sign_params;
	const gnutls_sign_entry_st *se;

	/* Read the MPI parameters from the issuer's certificate.
	 */
	ret = _gnutls_x509_crt_get_mpis(issuer, &params);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	issuer_pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL);

	se = _gnutls_sign_to_entry(sign);
	if (se == NULL)
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);

	if (cert != NULL) {
		ret = _gnutls_x509_read_sign_params(cert->cert,
						    "signatureAlgorithm",
						    &sign_params);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = _gnutls_x509_validate_sign_params(issuer_pk,
							issuer->cert,
							"tbsCertificate."
							"subjectPublicKeyInfo."
							"algorithm",
							&sign_params);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		memcpy(&sign_params, &params.spki,
		       sizeof(gnutls_x509_spki_st));

		sign_params.pk = se->pk;
		if (sign_params.pk == GNUTLS_PK_RSA_PSS)
			sign_params.rsa_pss_dig = se->hash;
	}

	ret = pubkey_verify_data(se, hash_to_entry(se->hash), data, signature, &params,
				 &sign_params, vflags);
	if (ret < 0) {
		gnutls_assert();
	}

 cleanup:
	/* release all allocated MPIs
	 */
	gnutls_pk_params_release(&params);

	return ret;
}
Exemple #13
0
/* Generates a signature of all the previous sent packets in the 
 * handshake procedure. 
 * 20040227: now it works for SSL 3.0 as well
 * 20091031: works for TLS 1.2 too!
 *
 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
 */
int
_gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
				gnutls_pcert_st * cert,
				gnutls_privkey_t pkey,
				gnutls_datum_t * signature)
{
	gnutls_datum_t dconcat;
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_privkey_get_pk_algorithm(pkey, NULL);

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	if (_gnutls_version_has_selectable_sighash(ver))
		return _gnutls_handshake_sign_crt_vrfy12(session, cert,
							 pkey, signature);

	ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha,
		     session->internals.handshake_hash_buffer.data,
		     session->internals.handshake_hash_buffer.length);

	if (ver->id == GNUTLS_SSL3) {
		ret = _gnutls_generate_master(session, 1);
		if (ret < 0) {
			gnutls_assert();
			_gnutls_hash_deinit(&td_sha, NULL);
			return ret;
		}

		ret =
		    _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
						      session->security_parameters.
						      master_secret,
						      GNUTLS_MASTER_SIZE);
		if (ret < 0)
			return gnutls_assert_val(ret);
	} else
		_gnutls_hash_deinit(&td_sha, &concat[16]);

	/* ensure 1024 bit DSA keys are used */
	ret =
	    _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
					       GNUTLS_SIGN_UNKNOWN);
	if (ret < 0)
		return gnutls_assert_val(ret);

	switch (pk) {
	case GNUTLS_PK_RSA:
		ret =
		    _gnutls_hash_init(&td_md5,
				      hash_to_entry(GNUTLS_DIG_MD5));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_hash(&td_md5,
			     session->internals.handshake_hash_buffer.data,
			     session->internals.handshake_hash_buffer.
			     length);

		if (ver->id == GNUTLS_SSL3) {
			ret =
			    _gnutls_mac_deinit_ssl3_handshake(&td_md5,
							      concat,
							      session->security_parameters.
							      master_secret,
							      GNUTLS_MASTER_SIZE);
			if (ret < 0)
				return gnutls_assert_val(ret);
		} else
			_gnutls_hash_deinit(&td_md5, concat);

		dconcat.data = concat;
		dconcat.size = 36;
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:

		dconcat.data = &concat[16];
		dconcat.size = 20;
		break;

	default:
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
	}
	ret =
	    sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;
}
Exemple #14
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_sign_data(gnutls_session_t session,
			    gnutls_pcert_st * cert, gnutls_privkey_t pkey,
			    gnutls_datum_t * params,
			    gnutls_datum_t * signature,
			    gnutls_sign_algorithm_t * sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	const mac_entry_st *hash_algo;

	*sign_algo = _gnutls_session_get_sign_algo(session, cert);
	if (*sign_algo == GNUTLS_SIGN_UNKNOWN) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	gnutls_sign_algorithm_set_server(session, *sign_algo);

	hash_algo =
	    hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo));
	if (hash_algo == NULL)
		return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);

	_gnutls_handshake_log
	    ("HSK[%p]: signing handshake data: using %s\n", session,
	     gnutls_sign_algorithm_get_name(*sign_algo));

	ret = _gnutls_hash_init(&td_sha, hash_algo);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha, session->security_parameters.client_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, session->security_parameters.server_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, params->data, params->size);

	switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) {
	case GNUTLS_PK_RSA:
		if (!_gnutls_version_has_selectable_sighash(ver)) {
			digest_hd_st td_md5;

			ret =
			    _gnutls_hash_init(&td_md5,
					      hash_to_entry
					      (GNUTLS_DIG_MD5));
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}

			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     client_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     server_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5, params->data, params->size);

			_gnutls_hash_deinit(&td_md5, concat);
			_gnutls_hash_deinit(&td_sha, &concat[16]);

			dconcat.data = concat;
			dconcat.size = 36;
		} else {	/* TLS 1.2 way */

			_gnutls_hash_deinit(&td_sha, concat);

			dconcat.data = concat;
			dconcat.size =
			    _gnutls_hash_get_algo_len(hash_algo);
		}
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:
		_gnutls_hash_deinit(&td_sha, concat);

		if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) {
			gnutls_assert();
			return GNUTLS_E_INTERNAL_ERROR;
		}
		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(hash_algo);
		break;

	default:
		gnutls_assert();
		_gnutls_hash_deinit(&td_sha, NULL);
		return GNUTLS_E_INTERNAL_ERROR;
	}

	ret =
	    sign_tls_hash(session, hash_algo, cert, pkey, &dconcat,
			  signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;

}
Exemple #15
0
/* Verifies a TLS signature (like the one in the client certificate
 * verify message). 
 */
int
_gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
				  gnutls_pcert_st * cert,
				  gnutls_datum_t * signature,
				  gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);

	_gnutls_handshake_log("HSK[%p]: verify cert vrfy: using %s\n",
			      session,
			      gnutls_sign_algorithm_get_name(sign_algo));

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	if (_gnutls_version_has_selectable_sighash(ver))
		return _gnutls_handshake_verify_crt_vrfy12(session, cert,
							   signature,
							   sign_algo);

	ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
	if (ret < 0) {
		gnutls_assert();
		_gnutls_hash_deinit(&td_md5, NULL);
		return GNUTLS_E_HASH_FAILED;
	}

	_gnutls_hash(&td_sha,
		     session->internals.handshake_hash_buffer.data,
		     session->internals.handshake_hash_buffer_prev_len);
	_gnutls_hash(&td_md5,
		     session->internals.handshake_hash_buffer.data,
		     session->internals.handshake_hash_buffer_prev_len);

	if (ver->id == GNUTLS_SSL3) {
		ret = _gnutls_generate_master(session, 1);
		if (ret < 0) {
			_gnutls_hash_deinit(&td_md5, NULL);
			_gnutls_hash_deinit(&td_sha, NULL);
			return gnutls_assert_val(ret);
		}

		ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat,
							session->security_parameters.
							master_secret,
							GNUTLS_MASTER_SIZE);
		if (ret < 0) {
			_gnutls_hash_deinit(&td_sha, NULL);
			return gnutls_assert_val(ret);
		}

		ret =
		    _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
						      session->security_parameters.
						      master_secret,
						      GNUTLS_MASTER_SIZE);
		if (ret < 0) {
			return gnutls_assert_val(ret);
		}
	} else {
		_gnutls_hash_deinit(&td_md5, concat);
		_gnutls_hash_deinit(&td_sha, &concat[16]);
	}

	dconcat.data = concat;
	dconcat.size = 20 + 16;	/* md5+ sha */

	ret =
	    verify_tls_hash(session, ver, cert, &dconcat, signature, 16,
			    GNUTLS_SIGN_UNKNOWN,
			    gnutls_pubkey_get_pk_algorithm(cert->pubkey,
							   NULL));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;
}
Exemple #16
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_verify_data(gnutls_session_t session,
			      gnutls_pcert_st * cert,
			      const gnutls_datum_t * params,
			      gnutls_datum_t * signature,
			      gnutls_sign_algorithm_t sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	gnutls_digest_algorithm_t hash_algo;
	const mac_entry_st *me;

	if (_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_handshake_log
		    ("HSK[%p]: verify handshake data: using %s\n", session,
		     gnutls_sign_algorithm_get_name(sign_algo));

		ret =
		    _gnutls_pubkey_compatible_with_sig(session,
						       cert->pubkey, ver,
						       sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret =
		    _gnutls_session_sign_algo_enabled(session, sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
		me = hash_to_entry(hash_algo);
	} else {
		me = hash_to_entry(GNUTLS_DIG_MD5);
		ret = _gnutls_hash_init(&td_md5, me);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		_gnutls_hash(&td_md5,
			     session->security_parameters.client_random,
			     GNUTLS_RANDOM_SIZE);
		_gnutls_hash(&td_md5,
			     session->security_parameters.server_random,
			     GNUTLS_RANDOM_SIZE);
		_gnutls_hash(&td_md5, params->data, params->size);

		me = hash_to_entry(GNUTLS_DIG_SHA1);
	}

	ret = _gnutls_hash_init(&td_sha, me);
	if (ret < 0) {
		gnutls_assert();
		if (!_gnutls_version_has_selectable_sighash(ver))
			_gnutls_hash_deinit(&td_md5, NULL);
		return ret;
	}

	_gnutls_hash(&td_sha, session->security_parameters.client_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, session->security_parameters.server_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, params->data, params->size);

	if (!_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_hash_deinit(&td_md5, concat);
		_gnutls_hash_deinit(&td_sha, &concat[16]);
		dconcat.data = concat;
		dconcat.size = 36;
	} else {
		_gnutls_hash_deinit(&td_sha, concat);

		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(me);
	}

	ret = verify_tls_hash(session, ver, cert, &dconcat, signature,
			      dconcat.size - _gnutls_hash_get_algo_len(me),
			      sign_algo,
			      gnutls_sign_get_pk_algorithm(sign_algo));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}