asn1.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2001,2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <stdio.h>
#include "snmp_msg.h"
#include "asn1.h"
/*
* asn_parse_int - pulls a int32_t out of an ASN int type.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the end of this object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
uint32_t asn_length = 0;
error_label[0] = '\0';
return NULL;
}
return NULL;
}
/* LINTED */
return NULL;
}
if (asn_length > intsize){
return NULL;
}
/* LINTED */
if (*bufp & 0x80)
while(asn_length--)
return bufp;
}
/*
* asn_parse_unsigned_int - pulls an unsigned int32_t out of an ASN int type.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the end of this object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
error_label[0] = '\0';
return NULL;
}
return NULL;
}
/* LINTED */
return NULL;
}
return NULL;
}
/* LINTED */
if (*bufp & 0x80)
while(asn_length--)
return bufp;
}
/*
* asn_build_int - builds an ASN object containing an integer.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the end of this object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
error_label[0] = '\0';
return NULL;
/*
* Truncate "unnecessary" bytes off of the most significant end of this 2's
* complement integer. There should be no sequence of 9 consecutive 1's or
* 0's at the most significant end of the integer.
*/
/* mask is 0xFF800000 on a big-endian machine */
intsize--;
integer <<= 8;
}
return NULL;
if (*datalength < intsize)
return NULL;
*datalength -= intsize;
/* mask is 0xFF000000 on a big-endian machine */
while(intsize--){
/* LINTED */
integer <<= 8;
}
return data;
}
/*
* asn_build_unsigned_int - builds an ASN object containing an integer.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the end of this object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
int add_null_byte = 0;
error_label[0] = '\0';
return NULL;
/* mask is 0xFF000000 on a big-endian machine */
/* LINTED */
/* if MSB is set */
add_null_byte = 1;
intsize++;
} else {
/*
* Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
* There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
* integer.
*/
/* mask is 0xFF800000 on a big-endian machine */
intsize--;
integer <<= 8;
}
}
return NULL;
if (*datalength < intsize)
return NULL;
*datalength -= intsize;
if (add_null_byte == 1){
*data++ = '\0';
intsize--;
}
/* mask is 0xFF000000 on a big-endian machine */
while(intsize--){
/* LINTED */
integer <<= 8;
}
return data;
}
/*
* asn_parse_string - pulls an octet string out of an ASN octet string type.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* "string" is filled with the octet string.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 octet string ::= primstring | cmpdstring
* primstring ::= 0x04 asnlength byte {byte}*
* cmpdstring ::= 0x24 asnlength string {string}*
* This doesn't yet support the compound string.
*/
uint32_t asn_length = 0;
error_label[0] = '\0';
return NULL;
/* LINTED */
return NULL;
}
if (asn_length > *strlength){
return NULL;
}
*strlength = asn_length;
/* LINTED */
return bufp + asn_length;
}
/*
* asn_build_string - Builds an ASN octet string object containing the input string.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 octet string ::= primstring | cmpdstring
* primstring ::= 0x04 asnlength byte {byte}*
* cmpdstring ::= 0x24 asnlength string {string}*
* This code will never send a compound string.
*/
error_label[0] = '\0';
return NULL;
if (*datalength < strlength)
return NULL;
*datalength -= strlength;
}
/*
* asn_parse_header - interprets the ID and length of the current object.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* Returns a pointer to the first byte of the contents of this object.
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
uint32_t asn_length = 0;
error_label[0] = '\0';
/* this only works on data types < 30, i.e. no extension octets */
if (IS_EXTENSION_ID(*bufp)){
return NULL;
}
return NULL;
/* LINTED */
return NULL;
}
*datalength = asn_length;
return bufp;
}
/*
* asn_build_header - builds an ASN header for an object with the ID and
* length specified.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* This only works on data types < 30, i.e. no extension octets.
* The maximum length is 0xFFFF;
*
* Returns a pointer to the first byte of the contents of this object.
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
error_label[0] = '\0';
if (*datalength == 0)
return NULL;
(*datalength)--;
}
/*
* asn_parse_length - interprets the length of the current object.
* On exit, length contains the value of this length field.
*
* Returns a pointer to the first byte after this length
* field (aka: the start of the data field).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
error_label[0] = '\0';
if (lengthbyte & ASN_LONG_LEN){
if (lengthbyte == 0){
return NULL;
}
if (lengthbyte > sizeof(int32_t)){
return NULL;
}
} else { /* short asnlength */
return data + 1;
}
}
u_char *
char *error_label)
{
error_label[0] = '\0';
/* no indefinite lengths sent */
if (length < 0x80){
if (*datalength < 1)
goto errout;
/* LINTED */
} else if (length <= 0xFF){
if (*datalength < 2)
goto errout;
/* LINTED */
/* LINTED */
} else { /* 0xFF < length <= 0xFFFF */
if (*datalength < 3)
goto errout;
/* LINTED */
/* LINTED */
/* LINTED */
}
/* LINTED */
return data;
return NULL;
}
/*
* asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* "objid" is filled with the object identifier.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
* subidentifier ::= {leadingbyte}* lastbyte
* leadingbyte ::= 1 7bitvalue
* lastbyte ::= 0 7bitvalue
*/
uint32_t asn_length = 0;
error_label[0] = '\0';
return NULL;
/* LINTED */
return NULL;
}
/* LINTED */
length = asn_length;
(*objidlength)--; /* account for expansion of first byte */
while (length > 0 && (*objidlength)-- > 0){
subidentifier = 0;
do { /* shift and add in low order 7 bits */
length--;
return NULL;
}
}
/*
* The first two subidentifiers are encoded into the first component
* with the value (X * 40) + Y, where:
* X is the value of the first subidentifier.
* Y is the value of the second subidentifier.
*/
/* LINTED */
/* LINTED */
/* LINTED */
return bufp;
}
/*
* asn_build_objid - Builds an ASN object identifier object containing the input string.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
* subidentifier ::= {leadingbyte}* lastbyte
* leadingbyte ::= 1 7bitvalue
* lastbyte ::= 0 7bitvalue
*/
error_label[0] = '\0';
if (objidlength > MAX_OID_LEN)
return (NULL);
/* transform size in bytes to size in subid's */
/* encode the first two components into the first subidentifier */
op++;
objidlength--;
while (objidlength-- > 0){
bits = 0;
/* testmask *MUST* !!!! be of an unsigned type */
}
}
/* mask can't be zero here */
if (mask == 0x1E00000)
/* fix a mask that got truncated above */
mask = 0xFE00000;
/* LINTED */
}
/* LINTED */
}
/* LINTED */
return (NULL);
if (*datalength < asnlength)
return (NULL);
*datalength -= asnlength;
}
/*
* asn_parse_null - Interprets an ASN null type.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 null ::= 0x05 0x00
*/
uint32_t asn_length = 0;
error_label[0] = '\0';
return NULL;
if (asn_length != 0){
return NULL;
}
/* LINTED */
}
/*
* asn_build_null - Builds an ASN null object.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the beginning of the next object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
u_char *
char *error_label)
{
/*
* ASN.1 null ::= 0x05 0x00
*/
error_label[0] = '\0';
}