osmo-cc-misdn-endpoint/src/libmisdnuser/asn1/asn1_enc.c

174 lines
3.9 KiB
C

/*
* Encode basic ASN1 elements
*
* Copyright 2009,2010 by Karsten Keil <kkeil@linux-pingi.de>
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
* version 2.1 as published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU LESSER GENERAL PUBLIC LICENSE for more details.
*
*/
#include "asn1.h"
#include <string.h>
int encodeLen_Long_u8(__u8 * dest, __u8 length)
{
dest[0] = 0x80 + ASN1_NUM_OCTETS_LONG_LENGTH_u8 - 1;
dest[1] = length;
return ASN1_NUM_OCTETS_LONG_LENGTH_u8;
} /* end encodeLen_Long_u8() */
int encodeLen_Long_u16(__u8 * dest, __u16 length)
{
dest[0] = 0x80 + ASN1_NUM_OCTETS_LONG_LENGTH_u16 - 1;
dest[1] = (length >> 8) & 0xFF;
dest[2] = length & 0xFF;
return ASN1_NUM_OCTETS_LONG_LENGTH_u16;
} /* end encodeLen_Long_u16() */
int encodeNull(__u8 * dest, __u8 tagType)
{
dest[0] = tagType;
dest[1] = 0; /* length */
return 2;
}
int encodeBoolean(__u8 * dest, __u8 tagType, __u32 i)
{
dest[0] = tagType;
dest[1] = 1; /* length */
dest[2] = i ? 1 : 0; /* value */
return 3;
}
int encodeInt(__u8 * dest, __u8 tagType, __s32 i)
{
unsigned count;
__u32 test_mask;
__u32 value;
__u8 *p;
dest[0] = tagType;
/* Find most significant octet of 32 bit integer that carries meaning. */
test_mask = 0xFF800000;
value = (__u32) i;
for (count = 4; --count;) {
if ((value & test_mask) != test_mask && (value & test_mask) != 0) {
/*
* The first 9 bits of a multiple octet integer is not
* all ones or zeroes.
*/
break;
}
test_mask >>= 8;
} /* end for */
/* length */
dest[1] = count + 1;
/* Store value */
p = &dest[2];
do {
value = (__u32) i;
value >>= (8 * count);
*p++ = value & 0xFF;
} while (count--);
return p - dest;
}
int encodeEnum(__u8 * dest, __u8 tagType, __s32 i)
{
return encodeInt(dest, tagType, i);
}
/*
* Use to encode the following string types:
* ASN1_TAG_OCTET_STRING
* ASN1_TAG_NUMERIC_STRING
* ASN1_TAG_PRINTABLE_STRING
* ASN1_TAG_IA5_STRING
*
* Note The string length MUST be less than 128 characters.
*/
static int encodeString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
{
__u8 *p;
int i;
dest[0] = tagType;
/* Store value */
p = &dest[2];
for (i = 0; i < len; i++)
*p++ = *str++;
/* length */
dest[1] = p - &dest[2];
return p - dest;
}
int encodeOctetString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
{
return encodeString(dest, tagType, str, len);
} /* end encodeOctetString() */
int encodeNumericString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
{
return encodeString(dest, tagType, str, len);
} /* end encodeNumericString() */
int encodePrintableString(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
{
return encodeString(dest, tagType, str, len);
} /* end encodePrintableString() */
int encodeIA5String(__u8 * dest, __u8 tagType, const __s8 * str, __u8 len)
{
return encodeString(dest, tagType, str, len);
} /* end encodeIA5String() */
int encodeOid(__u8 * dest, __u8 tagType, const struct asn1Oid *oid)
{
unsigned numValues;
unsigned count;
__u32 value;
__u8 *p;
dest[0] = tagType;
/* For all OID subidentifer values */
p = &dest[2];
for (numValues = 0; numValues < oid->numValues; ++numValues) {
/*
* Count the number of 7 bit chunks that are needed
* to encode the integer.
*/
value = oid->value[numValues] >> 7;
for (count = 0; value; ++count) {
/* There are bits still set */
value >>= 7;
} /* end for */
/* Store OID subidentifier value */
do {
value = oid->value[numValues];
value >>= (7 * count);
*p++ = (value & 0x7F) | (count ? 0x80 : 0);
} while (count--);
} /* end for */
/* length */
dest[1] = p - &dest[2];
return p - dest;
} /* end encodeOid() */