18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ASN.1 DER parsing
350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "asn1.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtstruct asn1_oid asn1_sha1_oid = {
1550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	.oid = { 1, 3, 14, 3, 2, 26 },
1650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	.len = 6
1750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt};
1850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
1950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtstruct asn1_oid asn1_sha256_oid = {
2050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	.oid = { 2, 16, 840, 1, 101, 3, 4, 2, 1 },
2150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	.len = 9
2250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt};
2350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
2450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 tmp;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(hdr, 0, sizeof(*hdr));
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + len;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->identifier = *pos++;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->class = hdr->identifier >> 6;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->constructed = !!(hdr->identifier & (1 << 5));
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((hdr->identifier & 0x1f) == 0x1f) {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->tag = 0;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		do {
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos >= end) {
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "underflow");
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = *pos++;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "0x%02x", tmp);
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} while (tmp & 0x80);
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->tag = hdr->identifier & 0x1f;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = *pos++;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp & 0x80) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tmp == 0xff) {
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "value 0xff used");
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp &= 0x7f; /* number of subsequent octets */
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->length = 0;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tmp > 4) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (tmp--) {
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos >= end) {
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "ASN.1: Length "
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "underflow");
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hdr->length = (hdr->length << 8) | *pos++;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Short form - length 0..127 in one octet */
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->length = tmp;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end < pos || hdr->length > (unsigned int) (end - pos)) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->payload = pos;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid)
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long val;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 tmp;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(oid, 0, sizeof(*oid));
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + len;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val = 0;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		do {
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos >= end)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = *pos++;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			val = (val << 7) | (tmp & 0x7f);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} while (tmp & 0x80);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oid->len >= ASN1_MAX_OID_LEN) {
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (oid->len == 0) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * The first octet encodes the first two object
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * identifier components in (X*40) + Y formula.
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * X = 0..2.
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oid->oid[0] = val / 40;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (oid->oid[0] > 2)
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				oid->oid[0] = 2;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oid->oid[1] = val - oid->oid[0] * 40;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oid->len = 2;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			oid->oid[oid->len++] = val;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 const u8 **next)
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct asn1_hdr hdr;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "tag 0x%x", hdr.class, hdr.tag);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*next = hdr.payload + hdr.length;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return asn1_parse_oid(hdr.payload, hdr.length, oid);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtvoid asn1_oid_to_str(const struct asn1_oid *oid, char *buf, size_t len)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0)
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[0] = '\0';
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < oid->len; i++) {
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(pos, buf + len - pos,
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "%s%lu",
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  i == 0 ? "" : ".", oid->oid[i]);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= buf + len - pos)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ret;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[len - 1] = '\0';
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 rotate_bits(u8 octet)
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 res;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = 0;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 8; i++) {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res <<= 1;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (octet & 1)
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res |= 1;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		octet >>= 1;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long val = 0;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = buf;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* BER requires that unused bits are zero, so we can ignore the number
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * of unused bits */
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= 2)
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val |= rotate_bits(*pos++);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= 3)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val |= ((unsigned long) rotate_bits(*pos++)) << 8;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= 4)
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val |= ((unsigned long) rotate_bits(*pos++)) << 16;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= 5)
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val |= ((unsigned long) rotate_bits(*pos++)) << 24;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len >= 6)
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(BIT STRING length %lu)",
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned long) len);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return val;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
21950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtint asn1_oid_equal(const struct asn1_oid *a, const struct asn1_oid *b)
22150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt{
22250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	size_t i;
22350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (a->len != b->len)
22550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return 0;
22650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	for (i = 0; i < a->len; i++) {
22850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		if (a->oid[i] != b->oid[i])
22950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			return 0;
23050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
23150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
23250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	return 1;
23350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt}
234