Esempio n. 1
0
/**
 * Load a RSA public key from DNSKEY RR data
 */
static dnskey_public_key_t *parse_rsa_public_key(chunk_t blob)
{
	chunk_t n, e;

	if (blob.len < 3)
	{
		DBG1(DBG_LIB, "RFC 3110 public key blob too short for exponent length");
		return NULL;
	}

	if (blob.ptr[0])
	{
		e.len = blob.ptr[0];
		blob = chunk_skip(blob, 1);
	}
	else
	{
		e.len = blob.ptr[1] * 256 + blob.ptr[2];
		blob = chunk_skip(blob, 3);
	}
	e.ptr = blob.ptr;
	if (e.len >= blob.len)
	{
		DBG1(DBG_LIB, "RFC 3110 public key blob too short for exponent");
		return NULL;
	}
	n = chunk_skip(blob, e.len);

	return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
						BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e,
						BUILD_END);
}
/**
 * Build a PGPv3 fingerprint
 */
static bool build_v3_fingerprint(chunk_t *encoding, va_list args)
{
	hasher_t *hasher;
	chunk_t n, e;

	if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
						   CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
	{
		hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
		if (!hasher)
		{
			DBG1(DBG_LIB, "MD5 hash algorithm not supported, PGP"
				 " fingerprinting failed");
			return FALSE;
		}
		/* remove leading zero bytes before hashing modulus and exponent */
		while (n.len > 0 && n.ptr[0] == 0x00)
		{
			n = chunk_skip(n, 1);
		}
		while (e.len > 0 && e.ptr[0] == 0x00)
		{
			e = chunk_skip(e, 1);
		}
		hasher->allocate_hash(hasher, n, NULL);
		hasher->allocate_hash(hasher, e, encoding);
		hasher->destroy(hasher);
		return TRUE;
	}
	return FALSE;
}
Esempio n. 3
0
/**
 * Encode an RSA public key in DNSKEY format (RFC 3110)
 */
static bool build_pub(chunk_t *encoding, va_list args)
{
	chunk_t n, e, pubkey;
	size_t exp_len;
	u_char *pos;

	if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
						   CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
	{
		/* remove leading zeros in exponent and modulus */
		while (*e.ptr == 0)
		{
			e = chunk_skip(e, 1);
		}
		while (*n.ptr == 0)
		{
			n = chunk_skip(n, 1);
		}

		if (e.len < 256)
		{
			/* exponent length fits into a single octet */
			exp_len = 1;
			pubkey = chunk_alloc(exp_len + e.len + n.len);
			pubkey.ptr[0] = (char)e.len;
		}
		else if (e.len < 65536)
		{
			/* exponent length fits into two octets preceded by zero octet */
			exp_len = 3;
			pubkey = chunk_alloc(exp_len + e.len + n.len);
			pubkey.ptr[0] = 0x00;
			htoun16(pubkey.ptr + 1, e.len);
		}
		else
		{
			/* exponent length is too large */
			return FALSE;
		}

		/* copy exponent and modulus and convert to base64 format */
		pos = pubkey.ptr + exp_len;
		memcpy(pos, e.ptr, e.len);
		pos += e.len;
		memcpy(pos, n.ptr, n.len);
		*encoding = chunk_to_base64(pubkey, NULL);
		chunk_free(&pubkey);

		return TRUE;
	}
	return FALSE;
}
Esempio n. 4
0
/**
 * Load a generic public key from a DNSKEY RR blob
 */
static dnskey_public_key_t *parse_public_key(chunk_t blob)
{
	dnskey_rr_t *rr = (dnskey_rr_t*)blob.ptr;

	if (blob.len < sizeof(dnskey_rr_t))
	{
		DBG1(DBG_LIB, "DNSKEY too short");
		return NULL;
	}
	blob = chunk_skip(blob, sizeof(dnskey_rr_t));

	switch (rr->algorithm)
	{
		case DNSKEY_ALG_RSA_MD5:
		case DNSKEY_ALG_RSA_SHA1:
		case DNSKEY_ALG_RSA_SHA1_NSEC3_SHA1:
		case DNSKEY_ALG_RSA_SHA256:
		case DNSKEY_ALG_RSA_SHA512:
			return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
									  BUILD_BLOB_DNSKEY, blob, BUILD_END);
		default:
			DBG1(DBG_LIB, "DNSKEY public key algorithm %d not supported",
				 rr->algorithm);
			return NULL;
	}
}
Esempio n. 5
0
/**
 * find a boundary of the form -----tag name-----
 */
static bool find_boundary(char* tag, chunk_t *line)
{
	chunk_t name = chunk_empty;

	if (!present("-----", line) ||
		!present(tag, line) ||
		*line->ptr != ' ')
	{
		return FALSE;
	}
	*line = chunk_skip(*line, 1);

	/* extract name */
	name.ptr = line->ptr;
	while (line->len > 0)
	{
		if (present("-----", line))
		{
			DBG2(DBG_ASN, "  -----%s %.*s-----", tag, (int)name.len, name.ptr);
			return TRUE;
		}
		line->ptr++;  line->len--;  name.len++;
	}
	return FALSE;
}
Esempio n. 6
0
static int fmemwrite(chunk_t *cookie, const char *buf, int size)
{
	int len;

	len = min(size, cookie->len);
	memcpy(cookie->ptr, buf, len);
	*cookie = chunk_skip(*cookie, len);

	return len;
}
Esempio n. 7
0
static int fmemread(chunk_t *cookie, char *buf, int size)
{
	int len;

	len = min(size, cookie->len);
	memcpy(buf, cookie->ptr, len);
	*cookie = chunk_skip(*cookie, len);

	return len;
}
Esempio n. 8
0
/*
 * See header.
 */
int asn1_unwrap(chunk_t *blob, chunk_t *inner)
{
	chunk_t res;
	u_char len;
	int type;

	if (blob->len < 2)
	{
		return ASN1_INVALID;
	}
	type = blob->ptr[0];
	len = blob->ptr[1];
	*blob = chunk_skip(*blob, 2);

	if ((len & 0x80) == 0)
	{	/* single length octet */
		res.len = len;
	}
	else
	{	/* composite length, determine number of length octets */
		len &= 0x7f;
		if (len == 0 || len > sizeof(res.len))
		{
			return ASN1_INVALID;
		}
		res.len = 0;
		while (len-- > 0)
		{
			res.len = 256 * res.len + blob->ptr[0];
			*blob = chunk_skip(*blob, 1);
		}
	}
	if (res.len > blob->len)
	{
		return ASN1_INVALID;
	}
	res.ptr = blob->ptr;
	*blob = chunk_skip(*blob, res.len);
	/* updating inner not before we are finished allows a caller to pass
	 * blob = inner */
	*inner = res;
	return type;
}
Esempio n. 9
0
/**
 * Load a generic public key from an ASN.1 encoded blob
 */
static public_key_t *parse_public_key(chunk_t blob)
{
	asn1_parser_t *parser;
	chunk_t object;
	int objectID;
	public_key_t *key = NULL;
	key_type_t type = KEY_ANY;

	parser = asn1_parser_create(pkinfoObjects, blob);

	while (parser->iterate(parser, &objectID, &object))
	{
		switch (objectID)
		{
			case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
			{
				int oid = asn1_parse_algorithmIdentifier(object,
										parser->get_level(parser)+1, NULL);

				if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP)
				{
					type = KEY_RSA;
				}
				else if (oid == OID_EC_PUBLICKEY)
				{
					/* we need the whole subjectPublicKeyInfo for EC public keys */
					key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
								KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
					goto end;
				}
				else
				{
					/* key type not supported */
					goto end;
				}
				break;
			}
			case PKINFO_SUBJECT_PUBLIC_KEY:
				if (object.len > 0 && *object.ptr == 0x00)
				{
					/* skip initial bit string octet defining 0 unused bits */
					object = chunk_skip(object, 1);
				}
				DBG2(DBG_ASN, "-- > --");
				key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
										 BUILD_BLOB_ASN1_DER, object, BUILD_END);
				DBG2(DBG_ASN, "-- < --");
				break;
		}
	}

end:
	parser->destroy(parser);
	return key;
}
Esempio n. 10
0
/*
 * Defined in header.
 */
size_t asn1_length(chunk_t *blob)
{
	u_char n;
	size_t len;

	if (blob->len < 2)
	{
		DBG2(DBG_LIB, "insufficient number of octets to parse ASN.1 length");
		return ASN1_INVALID_LENGTH;
	}

	/* read length field, skip tag and length */
	n = blob->ptr[1];
	*blob = chunk_skip(*blob, 2);

	if ((n & 0x80) == 0)
	{	/* single length octet */
		if (n > blob->len)
		{
			DBG2(DBG_LIB, "length is larger than remaining blob size");
			return ASN1_INVALID_LENGTH;
		}
		return n;
	}

	/* composite length, determine number of length octets */
	n &= 0x7f;

	if (n == 0 || n > blob->len)
	{
		DBG2(DBG_LIB, "number of length octets invalid");
		return ASN1_INVALID_LENGTH;
	}

	if (n > sizeof(len))
	{
		DBG2(DBG_LIB, "number of length octets is larger than limit of"
			 " %d octets", (int)sizeof(len));
		return ASN1_INVALID_LENGTH;
	}

	len = 0;

	while (n-- > 0)
	{
		len = 256*len + *blob->ptr++;
		blob->len--;
	}
	if (len > blob->len)
	{
		DBG2(DBG_LIB, "length is larger than remaining blob size");
		return ASN1_INVALID_LENGTH;
	}
	return len;
}
Esempio n. 11
0
/**
 * check the presence of a pattern in a character string, skip if found
 */
static bool present(char* pattern, chunk_t* ch)
{
	u_int len = strlen(pattern);

	if (ch->len >= len && strneq(ch->ptr, pattern, len))
	{
		*ch = chunk_skip(*ch, len);
		return TRUE;
	}
	return FALSE;
}
Esempio n. 12
0
END_TEST

/*******************************************************************************
 * chunk_skip[_zero]
 */

START_TEST(test_chunk_skip)
{
	chunk_t foobar, a;

	foobar = chunk_from_str("foobar");
	a = foobar;
	a = chunk_skip(a, 0);
	ck_assert(chunk_equals(a, foobar));
	a = chunk_skip(a, 1);
	ck_assert(chunk_equals(a, chunk_from_str("oobar")));
	a = chunk_skip(a, 2);
	ck_assert(chunk_equals(a, chunk_from_str("bar")));
	a = chunk_skip(a, 3);
	assert_chunk_empty(a);

	a = foobar;
	a = chunk_skip(a, 6);
	assert_chunk_empty(a);

	a = foobar;
	a = chunk_skip(a, 10);
	assert_chunk_empty(a);
}
Esempio n. 13
0
/*
 * Defined in header.
 */
char *asn1_oid_to_string(chunk_t oid)
{
	char buf[64], *pos = buf;
	int len;
	u_int val;

	if (!oid.len)
	{
		return NULL;
	}
	val = oid.ptr[0] / 40;
	len = snprintf(buf, sizeof(buf), "%u.%u", val, oid.ptr[0] - val * 40);
	oid = chunk_skip(oid, 1);
	if (len < 0 || len >= sizeof(buf))
	{
		return NULL;
	}
	pos += len;
	val = 0;

	while (oid.len)
	{
		val = (val << 7) + (u_int)(oid.ptr[0] & 0x7f);

		if (oid.ptr[0] < 128)
		{
			len = snprintf(pos, sizeof(buf) + buf - pos, ".%u", val);
			if (len < 0 || len >= sizeof(buf) + buf - pos)
			{
				return NULL;
			}
			pos += len;
			val = 0;
		}
		oid = chunk_skip(oid, 1);
	}
	return (val == 0) ? strdup(buf) : NULL;
}
Esempio n. 14
0
/**
 * Described in header.
 */
void chunk_split(chunk_t chunk, const char *mode, ...)
{
	va_list chunks;
	u_int len;
	chunk_t *ch;

	va_start(chunks, mode);
	while (TRUE)
	{
		if (*mode == '\0')
		{
			break;
		}
		len = va_arg(chunks, u_int);
		ch = va_arg(chunks, chunk_t*);
		/* a null chunk means skip len bytes */
		if (ch == NULL)
		{
			chunk = chunk_skip(chunk, len);
			continue;
		}
		switch (*mode++)
		{
			case 'm':
			{
				ch->len = min(chunk.len, len);
				if (ch->len)
				{
					ch->ptr = chunk.ptr;
				}
				else
				{
					ch->ptr = NULL;
				}
				chunk = chunk_skip(chunk, ch->len);
				continue;
			}
			case 'a':
			{
				ch->len = min(chunk.len, len);
				if (ch->len)
				{
					ch->ptr = malloc(ch->len);
					memcpy(ch->ptr, chunk.ptr, ch->len);
				}
				else
				{
					ch->ptr = NULL;
				}
				chunk = chunk_skip(chunk, ch->len);
				continue;
			}
			case 'c':
			{
				ch->len = min(ch->len, chunk.len);
				ch->len = min(ch->len, len);
				if (ch->len)
				{
					memcpy(ch->ptr, chunk.ptr, ch->len);
				}
				else
				{
					ch->ptr = NULL;
				}
				chunk = chunk_skip(chunk, ch->len);
				continue;
			}
			default:
				break;
		}
		break;
	}
	va_end(chunks);
}
Esempio n. 15
0
/**
 * Encode the public key as Base64 encoded SSH key blob
 */
static bool build_public_key(chunk_t *encoding, va_list args)
{
	bio_writer_t *writer;
	chunk_t n, e;

	if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
						   CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
	{
		writer = bio_writer_create(0);
		writer->write_data32(writer, chunk_from_str("ssh-rsa"));

		writer->write_data32(writer, e);
		writer->write_data32(writer, n);
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	else if (cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER, &n,
								CRED_PART_END))
	{
		chunk_t alg;
		char *prefix;
		int oid;

		/* parse subjectPublicKeyInfo */
		if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE)
		{
			return FALSE;
		}
		oid = asn1_parse_algorithmIdentifier(n, 1, NULL);
		switch (oid)
		{
			case OID_ED25519:
				prefix = "ssh-ed25519";
				break;
			case OID_ED448:
				prefix = "ssh-ed448";
				break;
			default:
				return FALSE;
		}
		if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE ||
			asn1_unwrap(&n, &n) != ASN1_BIT_STRING || !n.len)
		{
			return FALSE;
		}
		writer = bio_writer_create(0);
		writer->write_data32(writer, chunk_from_str(prefix));
		writer->write_data32(writer, chunk_skip(n, 1));
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	else if (cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER, &n,
								CRED_PART_END))
	{
		chunk_t params, alg, q;
		int oid;

		/* parse subjectPublicKeyInfo */
		if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE)
		{
			return FALSE;
		}
		oid = asn1_parse_algorithmIdentifier(n, 1, &params);
		if (oid != OID_EC_PUBLICKEY ||
			asn1_unwrap(&params, &params) != ASN1_OID)
		{
			return FALSE;
		}
		oid = asn1_known_oid(params);
		if (oid == OID_UNKNOWN)
		{
			return FALSE;
		}
		if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE ||
			asn1_unwrap(&n, &q) != ASN1_BIT_STRING)
		{
			return FALSE;
		}
		writer = bio_writer_create(0);
		write_ec_identifier(writer, ECDSA_PREFIX, oid, params);
		write_ec_identifier(writer, "", oid, params);

		q = chunk_skip_zero(q);
		writer->write_data32(writer, q);
		*encoding = chunk_to_base64(writer->get_buf(writer), NULL);
		writer->destroy(writer);
		return TRUE;
	}
	return FALSE;
}
Esempio n. 16
0
static GstFlowReturn
gst_smfdec_chain (GstPad * pad, GstBuffer * data)
{
	GstSmfdec *dec = GST_SMFDEC (gst_pad_get_parent (pad));
	gint i, ticks;
	guint len, midi_len;

	/* we must be negotiated */
	g_assert ( dec != NULL );
	g_assert (dec->buf_denom > 0);

	gst_adapter_push (dec->adapter, GST_BUFFER (data));
	if (dec->chunk.fourcc) {
		chunk_ensure (dec->adapter, &dec->chunk, 0);
	}

	while (dec->chunk.fourcc || get_next_chunk (dec->adapter, &dec->chunk)) {
		switch (dec->chunk.fourcc) {
			case GST_MAKE_FOURCC ('M', 'T', 'h', 'd'):
				if (dec->format) {
					GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), 
							("got a header chunk while already initialized"));
					goto error;
				}
				if (dec->chunk.length != 6) {
					GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), 
							("header chunk %d bytes long, not 6", (int) dec->chunk.length));
					goto error;
				}
				if (!chunk_ensure (dec->adapter, &dec->chunk, 6))
					goto out;
				/* we add one, so we can use 0 for uninitialized */
				dec->format = GST_READ_UINT16_BE (dec->chunk.data) + 1;
				if (dec->format > 2)
					g_warning ("I have no clue if midi format %u works", dec->format - 1);
				dec->tracks_missing = GST_READ_UINT16_BE (dec->chunk.data + 2);
				//g_assert (dec->tracks_missing == 1);
				/* ignore the number of track atoms */
				i = (gint16) GST_READ_UINT16_BE (dec->chunk.data + 4);
				if (i < 0) {
					GST_ELEMENT_ERROR (dec, STREAM, NOT_IMPLEMENTED, (NULL), 
							("can't handle smpte timing"));
					goto error;
				} else {
					dec->start = 0;
					dec->division = i;
				}
				chunk_flush (dec->adapter, &dec->chunk);
				break;
			case GST_MAKE_FOURCC ('M', 'T', 'r', 'k'):
				if (dec->format == 0) {
					GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), 
							("got a track chunk while not yet initialized"));
					goto error;
				}
				/* figure out if we have enough data */
				ticks = gst_midi_data_parse_varlen (dec->chunk.data, dec->chunk.available, &len);
				if (ticks == -1) goto out;
				if (ticks == -2) {
					GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), 
							("invalid delta time value"));
					goto error;
				}
				midi_len = gst_midi_data_get_length (dec->chunk.data + len, 
						dec->chunk.available - len, dec->status);
				if (midi_len == 0) goto out;
				/* we have enough data, process */
				dec->ticks += ticks;
				//g_print ("got %u ticks, now %u\n", ticks, dec->ticks);
				if (dec->chunk.data[len] & 0x80) {
					dec->status = dec->chunk.data[len];
					len++;
					midi_len--;
				}
				if (dec->status == 0xFF) {
					if (!gst_smfdec_meta_event (dec, dec->chunk.data + len, midi_len))
						goto error;
				} else {
					gst_smfdec_buffer_append (dec, dec->status, dec->chunk.data + len, midi_len);
				}
				chunk_skip (dec->adapter, &dec->chunk, len + midi_len);
				if (dec->chunk.length == 0)
					chunk_clear (&dec->chunk);
				break;
			default:
				goto out;
		}
	}
out:
	gst_object_unref(dec);
	return GST_FLOW_OK;;

error:
	gst_smfdec_reset (dec);
	return GST_FLOW_ERROR;
}