Commit much improved ASN.1 compiler from joda-choice-branch.
Highlighs for the compiler is support for CHOICE and in general better support for tags. This compiler support most of what is needed for PK-INIT, LDAP, X.509, PKCS-12 and many other protocols. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15617 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2003 Kungliga Tekniska H<>gskolan
|
||||
* Copyright (c) 1997-2005 Kungliga Tekniska H<>gskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -43,10 +43,11 @@ RCSID("$Id$");
|
||||
* The return value is 0 or an error.
|
||||
*/
|
||||
|
||||
static int
|
||||
der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
|
||||
int
|
||||
der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
|
||||
{
|
||||
unsigned char *base = p;
|
||||
unsigned val = *v;
|
||||
|
||||
if (val) {
|
||||
while (len > 0 && val) {
|
||||
@@ -57,6 +58,11 @@ der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
|
||||
if (val != 0)
|
||||
return ASN1_OVERFLOW;
|
||||
else {
|
||||
if(p[1] >= 128) {
|
||||
if(len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = 0;
|
||||
}
|
||||
*size = base - p;
|
||||
return 0;
|
||||
}
|
||||
@@ -70,9 +76,10 @@ der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
|
||||
}
|
||||
|
||||
int
|
||||
der_put_int (unsigned char *p, size_t len, int val, size_t *size)
|
||||
der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
|
||||
{
|
||||
unsigned char *base = p;
|
||||
int val = *v;
|
||||
|
||||
if(val >= 0) {
|
||||
do {
|
||||
@@ -114,22 +121,26 @@ der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
|
||||
{
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
|
||||
if (val < 128) {
|
||||
*p = val;
|
||||
*size = 1;
|
||||
return 0;
|
||||
} else {
|
||||
size_t l;
|
||||
int e;
|
||||
size_t l = 0;
|
||||
|
||||
e = der_put_unsigned (p, len - 1, val, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
while(val > 0) {
|
||||
if(len < 2)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = val % 256;
|
||||
val /= 256;
|
||||
len--;
|
||||
l++;
|
||||
}
|
||||
*p = 0x80 | l;
|
||||
*size = l + 1;
|
||||
return 0;
|
||||
if(size)
|
||||
*size = l + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -160,6 +171,65 @@ der_put_general_string (unsigned char *p, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_utf8string (unsigned char *p, size_t len,
|
||||
const heim_utf8_string *str, size_t *size)
|
||||
{
|
||||
return der_put_general_string(p, len, str, size);
|
||||
}
|
||||
|
||||
int
|
||||
der_put_printable_string (unsigned char *p, size_t len,
|
||||
const heim_printable_string *str, size_t *size)
|
||||
{
|
||||
return der_put_general_string(p, len, str, size);
|
||||
}
|
||||
|
||||
int
|
||||
der_put_ia5_string (unsigned char *p, size_t len,
|
||||
const heim_ia5_string *str, size_t *size)
|
||||
{
|
||||
return der_put_general_string(p, len, str, size);
|
||||
}
|
||||
|
||||
int
|
||||
der_put_bmp_string (unsigned char *p, size_t len,
|
||||
const heim_bmp_string *data, size_t *size)
|
||||
{
|
||||
size_t i;
|
||||
if (len / 2 < data->length)
|
||||
return ASN1_OVERFLOW;
|
||||
p -= data->length * 2;
|
||||
len -= data->length * 2;
|
||||
for (i = 0; i < data->length; i++) {
|
||||
p[1] = (data->data[i] >> 8) & 0xff;
|
||||
p[2] = data->data[i] & 0xff;
|
||||
p += 2;
|
||||
}
|
||||
if (size) *size = data->length * 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_universal_string (unsigned char *p, size_t len,
|
||||
const heim_universal_string *data, size_t *size)
|
||||
{
|
||||
size_t i;
|
||||
if (len / 4 < data->length)
|
||||
return ASN1_OVERFLOW;
|
||||
p -= data->length * 4;
|
||||
len -= data->length * 4;
|
||||
for (i = 0; i < data->length; i++) {
|
||||
p[1] = (data->data[i] >> 24) & 0xff;
|
||||
p[2] = (data->data[i] >> 16) & 0xff;
|
||||
p[3] = (data->data[i] >> 8) & 0xff;
|
||||
p[4] = data->data[i] & 0xff;
|
||||
p += 4;
|
||||
}
|
||||
if (size) *size = data->length * 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_octet_string (unsigned char *p, size_t len,
|
||||
const heim_octet_string *data, size_t *size)
|
||||
@@ -173,6 +243,98 @@ der_put_octet_string (unsigned char *p, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_heim_integer (unsigned char *p, size_t len,
|
||||
const heim_integer *data, size_t *size)
|
||||
{
|
||||
unsigned char *buf = data->data;
|
||||
int hibitset = 0;
|
||||
|
||||
if (data->length == 0) {
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = 0;
|
||||
if (size)
|
||||
*size = 1;
|
||||
return 0;
|
||||
}
|
||||
if (len < data->length)
|
||||
return ASN1_OVERFLOW;
|
||||
|
||||
len -= data->length;
|
||||
|
||||
if (data->negative) {
|
||||
int i, carry;
|
||||
for (i = data->length - 1, carry = 1; i >= 0; i--) {
|
||||
*p = buf[i] ^ 0xff;
|
||||
if (carry)
|
||||
carry = !++*p;
|
||||
p--;
|
||||
}
|
||||
if (p[1] < 128) {
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = 0xff;
|
||||
len--;
|
||||
hibitset = 1;
|
||||
}
|
||||
} else {
|
||||
p -= data->length;
|
||||
memcpy(p + 1, buf, data->length);
|
||||
|
||||
if (p[1] >= 128) {
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
p[0] = 0;
|
||||
len--;
|
||||
hibitset = 1;
|
||||
}
|
||||
}
|
||||
if (size)
|
||||
*size = data->length + hibitset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_generalized_time (unsigned char *p, size_t len,
|
||||
const time_t *data, size_t *size)
|
||||
{
|
||||
heim_octet_string k;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = _heim_time2generalizedtime (*data, &k, 1);
|
||||
if (e)
|
||||
return e;
|
||||
e = der_put_octet_string(p, len, &k, &l);
|
||||
free(k.data);
|
||||
if(e)
|
||||
return e;
|
||||
if(size)
|
||||
*size = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_utctime (unsigned char *p, size_t len,
|
||||
const time_t *data, size_t *size)
|
||||
{
|
||||
heim_octet_string k;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = _heim_time2generalizedtime (*data, &k, 0);
|
||||
if (e)
|
||||
return e;
|
||||
e = der_put_octet_string(p, len, &k, &l);
|
||||
free(k.data);
|
||||
if(e)
|
||||
return e;
|
||||
if(size)
|
||||
*size = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_oid (unsigned char *p, size_t len,
|
||||
const heim_oid *data, size_t *size)
|
||||
@@ -205,18 +367,39 @@ der_put_oid (unsigned char *p, size_t len,
|
||||
|
||||
int
|
||||
der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
|
||||
int tag, size_t *size)
|
||||
unsigned int tag, size_t *size)
|
||||
{
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p = (class << 6) | (type << 5) | tag; /* XXX */
|
||||
*size = 1;
|
||||
if (tag <= 30) {
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p = MAKE_TAG(class, type, tag);
|
||||
*size = 1;
|
||||
} else {
|
||||
size_t ret = 0;
|
||||
unsigned int continuation = 0;
|
||||
|
||||
do {
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = tag % 128 | continuation;
|
||||
len--;
|
||||
ret++;
|
||||
tag /= 128;
|
||||
continuation = 0x80;
|
||||
} while(tag > 0);
|
||||
if (len < 1)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = MAKE_TAG(class, type, 0x1f);
|
||||
ret++;
|
||||
*size = ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
|
||||
Der_class class, Der_type type, int tag, size_t *size)
|
||||
Der_class class, Der_type type,
|
||||
unsigned int tag, size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
@@ -239,229 +422,55 @@ der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
|
||||
}
|
||||
|
||||
int
|
||||
encode_boolean (unsigned char *p, size_t len, const int *data,
|
||||
size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_boolean (p, len, data, &l);
|
||||
if(e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Boolean, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_integer (unsigned char *p, size_t len, const int *data, size_t *size)
|
||||
{
|
||||
int num = *data;
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_int (p, len, num, &l);
|
||||
if(e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_unsigned (unsigned char *p, size_t len, const unsigned *data,
|
||||
size_t *size)
|
||||
{
|
||||
unsigned num = *data;
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_unsigned (p, len, num, &l);
|
||||
if(e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
/* if first octet has msb set, we need to pad with a zero byte */
|
||||
if(p[1] >= 128) {
|
||||
if(len == 0)
|
||||
return ASN1_OVERFLOW;
|
||||
*p-- = 0;
|
||||
len--;
|
||||
ret++;
|
||||
l++;
|
||||
}
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_enumerated (unsigned char *p, size_t len, const unsigned *data,
|
||||
size_t *size)
|
||||
{
|
||||
unsigned num = *data;
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_int (p, len, num, &l);
|
||||
if(e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_general_string (unsigned char *p, size_t len,
|
||||
const heim_general_string *data, size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_general_string (p, len, data, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_GeneralString, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_octet_string (unsigned char *p, size_t len,
|
||||
const heim_octet_string *k, size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_octet_string (p, len, k, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_oid(unsigned char *p, size_t len,
|
||||
const heim_oid *k, size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
int e;
|
||||
|
||||
e = der_put_oid (p, len, k, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
time2generalizedtime (time_t t, heim_octet_string *s)
|
||||
_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
|
||||
{
|
||||
struct tm *tm;
|
||||
size_t len;
|
||||
|
||||
len = 15;
|
||||
const size_t len = gtimep ? 15 : 13;
|
||||
|
||||
s->data = malloc(len + 1);
|
||||
if (s->data == NULL)
|
||||
return ENOMEM;
|
||||
s->length = len;
|
||||
tm = gmtime (&t);
|
||||
snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
if (gtimep)
|
||||
snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
else
|
||||
snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
|
||||
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
encode_generalized_time (unsigned char *p, size_t len,
|
||||
const time_t *t, size_t *size)
|
||||
der_put_bit_string (unsigned char *p, size_t len,
|
||||
const heim_bit_string *data, size_t *size)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t l;
|
||||
heim_octet_string k;
|
||||
int e;
|
||||
|
||||
e = time2generalizedtime (*t, &k);
|
||||
if (e)
|
||||
return e;
|
||||
e = der_put_octet_string (p, len, &k, &l);
|
||||
free (k.data);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
e = der_put_length_and_tag (p, len, k.length, ASN1_C_UNIV, PRIM,
|
||||
UT_GeneralizedTime, &l);
|
||||
if (e)
|
||||
return e;
|
||||
p -= l;
|
||||
len -= l;
|
||||
ret += l;
|
||||
*size = ret;
|
||||
size_t data_size = (data->length + 7) / 8;
|
||||
if (len < data_size + 1)
|
||||
return ASN1_OVERFLOW;
|
||||
p -= data_size + 1;
|
||||
len -= data_size + 1;
|
||||
memcpy (p+2, data->data, data_size);
|
||||
if (data->length && (data->length % 8) != 0)
|
||||
p[1] = 8 - (data->length % 8);
|
||||
else
|
||||
p[1] = 0;
|
||||
*size = data_size + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_heim_der_set_sort(const void *a1, const void *a2)
|
||||
{
|
||||
const struct heim_octet_string *s1 = a1, *s2 = a2;
|
||||
int ret;
|
||||
|
||||
ret = memcmp(s1->data, s2->data,
|
||||
s1->length < s2->length ? s1->length : s2->length);
|
||||
if(ret)
|
||||
return ret;
|
||||
return s1->length - s2->length;
|
||||
}
|
||||
|
Reference in New Issue
Block a user