Exemplo n.º 1
0
/**
 * Generates a unique fingerprint of the pkcs10 request
 * by computing an MD5 hash over it
 */
chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10)
{
	chunk_t digest = chunk_alloca(HASH_SIZE_MD5);
	hasher_t *hasher;

	hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
	hasher->get_hash(hasher, pkcs10, digest.ptr);
	hasher->destroy(hasher);

	return chunk_to_hex(digest, NULL, FALSE);
}
Exemplo n.º 2
0
/**
 * write back the last serial number to file
 */
static void write_serial(chunk_t serial)
{
	FILE *fd = fopen(OPENAC_SERIAL, "w");

	if (fd)
	{
		chunk_t hex_serial;

		DBG1(DBG_LIB, "  serial number is %#B", &serial);
		hex_serial = chunk_to_hex(serial, NULL, FALSE);
		fprintf(fd, "%.*s\n", (int)hex_serial.len, hex_serial.ptr);
		fclose(fd);
		free(hex_serial.ptr);
	}
	else
	{
		DBG1(DBG_LIB, "  could not open file '%s' for writing", OPENAC_SERIAL);
	}
}
Exemplo n.º 3
0
/**
 * Generate a transaction id as the MD5 hash of an public key
 * the transaction id is also used as a unique serial number
 */
void scep_generate_transaction_id(public_key_t *key, chunk_t *transID,
								  chunk_t *serialNumber)
{
	chunk_t digest = chunk_alloca(HASH_SIZE_MD5);
	chunk_t keyEncoding = chunk_empty, keyInfo;
	hasher_t *hasher;
	bool msb_set;
	u_char *pos;

	key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding);

	keyInfo = asn1_wrap(ASN1_SEQUENCE, "mm",
						asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
						asn1_bitstring("m", keyEncoding));

	hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
	if (!hasher || !hasher->get_hash(hasher, keyInfo, digest.ptr))
	{
		memset(digest.ptr, 0, digest.len);
	}
	DESTROY_IF(hasher);
	free(keyInfo.ptr);

	/* is the most significant bit of the digest set? */
	msb_set = (*digest.ptr & 0x80) == 0x80;

	/* allocate space for the serialNumber */
	serialNumber->len = msb_set + digest.len;
	serialNumber->ptr = malloc(serialNumber->len);

	/* the serial number as the two's complement of the digest */
	pos = serialNumber->ptr;
	if (msb_set)
	{
		*pos++ = 0x00;
	}
	memcpy(pos, digest.ptr, digest.len);

	/* the transaction id is the serial number in hex format */
	*transID = chunk_to_hex(digest, NULL, TRUE);
}
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
							 imv_state_t *state,
							 pts_meas_algorithms_t supported_algorithms,
							 pts_dh_group_t supported_dh_groups,
							 pts_database_t *pts_db,
							 credential_manager_t *pts_credmgr)
{
	imv_session_t *session;
	imv_attestation_state_t *attestation_state;
	pen_type_t attr_type;
	pts_t *pts;

	session = state->get_session(state);
	attestation_state = (imv_attestation_state_t*)state;
	pts = attestation_state->get_pts(attestation_state);
	attr_type = attr->get_type(attr);

	switch (attr_type.type)
	{
		case TCG_PTS_PROTO_CAPS:
		{
			tcg_pts_attr_proto_caps_t *attr_cast;
			pts_proto_caps_flag_t flags;

			attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
			flags = attr_cast->get_flags(attr_cast);
			pts->set_proto_caps(pts, flags);
			break;
		}
		case TCG_PTS_MEAS_ALGO_SELECTION:
		{
			tcg_pts_attr_meas_algo_t *attr_cast;
			pts_meas_algorithms_t selected_algorithm;

			attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
			selected_algorithm = attr_cast->get_algorithms(attr_cast);
			if (!(selected_algorithm & supported_algorithms))
			{
				DBG1(DBG_IMV, "PTS-IMC selected unsupported"
							  " measurement algorithm");
				return FALSE;
			}
			pts->set_meas_algorithm(pts, selected_algorithm);
			state->set_action_flags(state, IMV_ATTESTATION_ALGO);
			break;
		}
		case TCG_PTS_DH_NONCE_PARAMS_RESP:
		{
			tcg_pts_attr_dh_nonce_params_resp_t *attr_cast;
			int nonce_len, min_nonce_len;
			pts_dh_group_t dh_group;
			pts_meas_algorithms_t offered_algorithms, selected_algorithm;
			chunk_t responder_value, responder_nonce;

			attr_cast = (tcg_pts_attr_dh_nonce_params_resp_t*)attr;
			responder_nonce = attr_cast->get_responder_nonce(attr_cast);

			/* check compliance of responder nonce length */
			min_nonce_len = lib->settings->get_int(lib->settings,
						"%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns);
			nonce_len = responder_nonce.len;
			if (nonce_len < PTS_MIN_NONCE_LEN ||
			   (min_nonce_len > 0 && nonce_len < min_nonce_len))
			{
				attr = pts_dh_nonce_error_create(
									max(PTS_MIN_NONCE_LEN, min_nonce_len),
										PTS_MAX_NONCE_LEN);
				out_msg->add_attribute(out_msg, attr);
				break;
			}

			dh_group = attr_cast->get_dh_group(attr_cast);
			if (!(dh_group & supported_dh_groups))
			{
				DBG1(DBG_IMV, "PTS-IMC selected unsupported DH group");
				return FALSE;
			}

			offered_algorithms = attr_cast->get_hash_algo_set(attr_cast);
			selected_algorithm = pts_meas_algo_select(supported_algorithms,
													  offered_algorithms);
			if (selected_algorithm == PTS_MEAS_ALGO_NONE)
			{
				attr = pts_hash_alg_error_create(supported_algorithms);
				out_msg->add_attribute(out_msg, attr);
				break;
			}
			pts->set_dh_hash_algorithm(pts, selected_algorithm);

			if (!pts->create_dh_nonce(pts, dh_group, nonce_len))
			{
				return FALSE;
			}

			responder_value = attr_cast->get_responder_value(attr_cast);
			pts->set_peer_public_value(pts, responder_value,
											responder_nonce);

			/* Calculate secret assessment value */
			if (!pts->calculate_secret(pts))
			{
				return FALSE;
			}
			state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE);
			break;
		}
		case TCG_PTS_TPM_VERSION_INFO:
		{
			tcg_pts_attr_tpm_version_info_t *attr_cast;
			chunk_t tpm_version_info;

			attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr;
			tpm_version_info = attr_cast->get_tpm_version_info(attr_cast);
			pts->set_tpm_version_info(pts, tpm_version_info);
			break;
		}
		case TCG_PTS_AIK:
		{
			tcg_pts_attr_aik_t *attr_cast;
			certificate_t *aik, *issuer;
			public_key_t *public;
			chunk_t keyid, keyid_hex, device_id;
			int aik_id;
			enumerator_t *e;
			bool trusted = FALSE, trusted_chain = FALSE;

			attr_cast = (tcg_pts_attr_aik_t*)attr;
			aik = attr_cast->get_aik(attr_cast);
			if (!aik)
			{
				DBG1(DBG_IMV, "AIK unavailable");
				attestation_state->set_measurement_error(attestation_state,
									IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
				break;
			}

			/* check trust into public key as stored in the database */
			public = aik->get_public_key(aik);
			public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
			DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
			keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
			if (session->get_device_id(session, &device_id) &&
				chunk_equals(keyid_hex, device_id))
			{
				trusted = session->get_device_trust(session);
			}
			else
			{
				DBG1(DBG_IMV, "device ID unknown or different from AIK keyid");
			}
			DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not ");
			public->destroy(public);
Exemplo n.º 5
0
/**
 * Add ITA Device ID attribute to the send queue
 */
static void add_device_id(imc_msg_t *msg)
{
	pa_tnc_attr_t *attr;
	chunk_t value = chunk_empty, keyid;
	char *name, *device_id, *cert_path;
	certificate_t *cert = NULL;
	public_key_t *pubkey;

	/* Get the device ID as a character string */
	device_id = lib->settings->get_str(lib->settings,
						"%s.plugins.imc-os.device_id", NULL, lib->ns);
	if (device_id)
	{
		value = chunk_clone(chunk_from_str(device_id));
	}

	if (value.len == 0)
	{
		/* Derive the device ID from a raw public key */
		cert_path = lib->settings->get_str(lib->settings,
							"%s.plugins.imc-os.device_pubkey", NULL, lib->ns);
		if (cert_path)
		{
			cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
									  CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
									  cert_path, BUILD_END);
			if (cert)
			{
				DBG2(DBG_IMC, "loaded device public key from '%s'", cert_path);
			}
			else
			{
				DBG1(DBG_IMC, "loading device public key from '%s' failed",
							   cert_path);
			}
		}

		if (!cert)
		{
			/* Derive the device ID from the public key contained in a certificate */
			cert_path = lib->settings->get_str(lib->settings,
								"%s.plugins.imc-os.device_cert", NULL, lib->ns);
			if (cert_path)
			{
				cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
										  CERT_X509, BUILD_FROM_FILE,
										  cert_path, BUILD_END);
				if (cert)
				{
					DBG2(DBG_IMC, "loaded device certificate from '%s'", cert_path);
				}
				else
				{
					DBG1(DBG_IMC, "loading device certificate from '%s' failed",
								   cert_path);
				}
			}
		}

		/* Compute the SHA-1 keyid of the retrieved device public key */
		if (cert)
		{
			pubkey = cert->get_public_key(cert);
			if (pubkey)
			{
				if (pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_INFO_SHA1,
											&keyid))
				{
					value = chunk_to_hex(keyid, NULL, FALSE);
				}
				pubkey->destroy(pubkey);
			}
			cert->destroy(cert);
		}
	}

	if (value.len == 0)
	{
		/* Derive the device ID from some unique OS settings */
		name = os->get_type(os) == OS_TYPE_ANDROID ?
					  "android_id" : "/var/lib/dbus/machine-id";
		value = os->get_setting(os, name);

		/* Trim trailing newline character */
		if (value.len > 0 && value.ptr[value.len - 1] == '\n')
		{
			value.len--;
		}
	}

	if (value.len == 0)
	{
		DBG1(DBG_IMC, "no device ID available");
		return;
	}

	DBG1(DBG_IMC, "device ID is %.*s", value.len, value.ptr);
	attr = ita_attr_device_id_create(value);
	msg->add_attribute(msg, attr);
	free(value.ptr);
}
Exemplo n.º 6
0
/**
 * Extract subject DN
 */
static int dn()
{
	identification_t *id;
	certificate_t *cert;
	chunk_t chunk;
	enum {
		FORMAT_CONFIG,
		FORMAT_HEX,
		FORMAT_BASE64,
		FORMAT_BINARY,
	} format = FORMAT_CONFIG;
	char *arg, *file = NULL, *fmt;

	while (TRUE)
	{
		switch (command_getopt(&arg))
		{
			case 'h':
				return command_usage(NULL);
			case 'f':
				if (streq(arg, "hex"))
				{
					format = FORMAT_HEX;
				}
				else if (streq(arg, "base64"))
				{
					format = FORMAT_BASE64;
				}
				else if (streq(arg, "bin"))
				{
					format = FORMAT_BINARY;
				}
				else if (!streq(arg, "config"))
				{
					return command_usage( "invalid output format");
				}
				continue;
			case 'i':
				file = arg;
				continue;
			case EOF:
				break;
			default:
				return command_usage("invalid --print option");
		}
		break;
	}
	if (file)
	{
		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
								  BUILD_FROM_FILE, file, BUILD_END);
	}
	else
	{
		chunk_t chunk;

		set_file_mode(stdin, CERT_ASN1_DER);
		if (!chunk_from_fd(0, &chunk))
		{
			fprintf(stderr, "reading input failed: %s\n", strerror(errno));
			return 1;
		}
		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
								  BUILD_BLOB, chunk, BUILD_END);
		free(chunk.ptr);
	}
	if (!cert)
	{
		fprintf(stderr, "parsing input failed\n");
		return 1;
	}
	id = cert->get_subject(cert);
	if (!id)
	{
		fprintf(stderr, "failed to get certificate's subject DN\n");
		cert->destroy(cert);
		return 1;
	}
	fmt = "%.*s\n";
	switch (format)
	{
		case FORMAT_CONFIG:
			fmt = "\"asn1dn:#%.*s\"\n";
			/* fall-through */
		case FORMAT_HEX:
			chunk = chunk_to_hex(id->get_encoding(id), NULL, FALSE);
			printf(fmt, (int)chunk.len, chunk.ptr);
			chunk_free(&chunk);
			break;
		case FORMAT_BASE64:
			chunk = chunk_to_base64(id->get_encoding(id), NULL);
			printf(fmt, (int)chunk.len, chunk.ptr);
			chunk_free(&chunk);
			break;
		case FORMAT_BINARY:
			chunk = id->get_encoding(id);
			if (fwrite(chunk.ptr, chunk.len, 1, stdout) != 1)
			{
				fprintf(stderr, "writing subject DN failed\n");
			}
			break;
	}
	cert->destroy(cert);
	return 0;
}
Exemplo n.º 7
0
END_TEST

/*******************************************************************************
 * BASE16 encoding test
 */

START_TEST(test_base16)
{
	/* test vectors from RFC 4648:
	 *
	 * BASE16("") = ""
	 * BASE16("f") = "66"
	 * BASE16("fo") = "666F"
	 * BASE16("foo") = "666F6F"
	 * BASE16("foob") = "666F6F62"
	 * BASE16("fooba") = "666F6F6261"
	 * BASE16("foobar") = "666F6F626172"
	 */
	typedef struct {
		bool upper;
		char *in;
		char *out;
	} testdata_t;

	testdata_t test[] = {
		{TRUE,  "", ""},
		{TRUE,  "f", "66"},
		{TRUE,  "fo", "666F"},
		{TRUE,  "foo", "666F6F"},
		{TRUE,  "foob", "666F6F62"},
		{TRUE,  "fooba", "666F6F6261"},
		{TRUE,  "foobar", "666F6F626172"},
		{FALSE, "", ""},
		{FALSE, "f", "66"},
		{FALSE, "fo", "666f"},
		{FALSE, "foo", "666f6f"},
		{FALSE, "foob", "666f6f62"},
		{FALSE, "fooba", "666f6f6261"},
		{FALSE, "foobar", "666f6f626172"},
	};
	testdata_t test_colon[] = {
		{TRUE,  "", ""},
		{TRUE,  "f", "66"},
		{TRUE,  "fo", "66:6F"},
		{TRUE,  "foo", "66:6F:6F"},
		{FALSE, "foob", "66:6f:6f:62"},
		{FALSE, "fooba", "66:6f:6f:62:61"},
		{FALSE, "foobar", "66:6f:6f:62:61:72"},
		{FALSE, "foobar", "66:6f6f:6261:72"},
	};
	int i;

	for (i = 0; i < countof(test); i++)
	{
		chunk_t out;

		out = chunk_to_hex(chunk_create(test[i].in, strlen(test[i].in)), NULL,
						   test[i].upper);
		ck_assert_str_eq(out.ptr, test[i].out);
		free(out.ptr);
	}

	for (i = 0; i < countof(test); i++)
	{
		chunk_t out;

		out = chunk_from_hex(chunk_create(test[i].out, strlen(test[i].out)), NULL);
		fail_unless(strneq(out.ptr, test[i].in, out.len),
					"base16 conversion error - should '%s', is %#B",
					test[i].in, &out);
		free(out.ptr);
	}

	for (i = 0; i < countof(test_colon); i++)
	{
		chunk_t out;

		out = chunk_from_hex(chunk_create(test_colon[i].out, strlen(test_colon[i].out)), NULL);
		fail_unless(strneq(out.ptr, test_colon[i].in, out.len),
					"base16 conversion error - should '%s', is %#B",
					test_colon[i].in, &out);
		free(out.ptr);
	}
}