www.pudn.com > SNMP·¶ÀýÔ´´úÂë.zip > Asn1.c
// asn1.c - ASN.1 encoding/decoding routines // DESCRIPTION // asn1 contains routines to do ASN.1 encoding/decoding #includeint asn1ErrStatus = ASN1_ERR_NOERROR; /* forward declarations */ /******************************************************************************* * * Asn1Opn - * * DESCRIPTION * * RETURNS * * NOMANUAL */ void Asn1Opn ( asn1_sck_t * Asn1, u8 * Buf, u32 Len, u32 Mde ) { Asn1->Begin = Buf; Asn1->End = Buf + Len; Asn1->Pointer = (Mde == ASN1_ENC) ? Buf + Len : Buf; } /******************************************************************************* * * Asn1Cls - * * DESCRIPTION * * RETURNS * * NOMANUAL */ void Asn1Cls ( asn1_sck_t * Asn1, u8 ** Buf, u32 * Len ) { *Buf = Asn1->Pointer; *Len = (u32) (Asn1->End - Asn1->Pointer); } /******************************************************************************* * * Asn1OctEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OctEnc( asn1_sck_t * Asn1, u8 Chr) { if (Asn1->Pointer <= Asn1->Begin) { asn1ErrStatus = ASN1_ERR_ENC_FULL; return FALSE; } *--(Asn1->Pointer) = Chr; return TRUE; } /******************************************************************************* * * Asn1OctDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OctDec ( asn1_sck_t * Asn1, u8 * Chr ) { if (Asn1->Pointer >= Asn1->End) { asn1ErrStatus = ASN1_ERR_DEC_EMPTY; return FALSE; } *Chr = *(Asn1->Pointer)++; return TRUE; } /******************************************************************************* * * Asn1TagEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ //???????????????????????? int Asn1TagEnc ( asn1_sck_t * Asn1, u32 Tag ) { u8 Chr; Chr = (u8) (Tag & 0x7F); Tag >>= 7; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; while (Tag > 0) { Chr = (u8) (Tag | 0x80); Tag >>= 7; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } return TRUE; } /******************************************************************************* * * Asn1TagDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ //?????????????????????????????? int Asn1TagDec ( asn1_sck_t * Asn1, u32 * Tag ) { u8 Chr; *Tag = 0; do { if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Tag <<= 7; *Tag |= Chr & 0x7F; } while ((Chr & 0x80) == 0x80); return TRUE; } /******************************************************************************* * * Asn1IdrEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IdrEnc ( asn1_sck_t * Asn1, u32 Cls, u32 Con, u32 Tag ) { u8 Chr; if (Tag >= 0x1F) { if (!Asn1TagEnc(Asn1, Tag)) return FALSE; Tag = 0x1F; } Chr = (u8) ((Cls << 6) | (Con << 5) | (Tag)); if (!Asn1OctEnc(Asn1, Chr)) return FALSE; return TRUE; } /******************************************************************************* * * Asn1IdrDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IdrDec ( asn1_sck_t * Asn1, u32 * Cls, u32 * Con, u32 * Tag ) { u8 Chr; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; if(Chr&0xC0>0x80) { u16 temp =Chr; temp = 0x00FF& temp; *Cls = temp>>6; } else { // *Cls = (Chr & 0xC0) >> 6; *Cls = Chr>>6; } *Con = (Chr & 0x20) >> 5; *Tag = (Chr & 0x1F); if (*Tag == 0x1F) { if (!Asn1TagDec(Asn1, Tag)) return FALSE; } return TRUE; } /******************************************************************************* * * Asn1LenEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1LenEnc ( asn1_sck_t * Asn1, u32 Def, u32 Len ) { u8 Chr, Cnt; if (!Def) { Chr = 0x80; } else { if (Len < 0x80) { Chr = (u8) Len; } else { Cnt = 0; while (Len > 0) { Chr = (u8) Len; Len >>= 8; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; Cnt++; } Chr = (u8) (Cnt | 0x80); } } if (!Asn1OctEnc(Asn1, Chr)) return FALSE; return TRUE; } /******************************************************************************* * * Asn1LenDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1LenDec ( asn1_sck_t * Asn1, u32 * Def, u32 * Len ) { u8 Chr, Cnt; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; if (Chr == 0x80) { *Def = 0; } else { *Def = 1; if (Chr < 0x80) { *Len = Chr; } else { Cnt = (u8) (Chr & 0x7F); *Len = 0; while (Cnt > 0) { if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Len <<= 8; *Len |= Chr; Cnt--; } } } return TRUE; } /******************************************************************************* * * Asn1HdrEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1HdrEnc ( asn1_sck_t * Asn1, u8 * Eoc, u32 Cls, u32 Con, u32 Tag ) { u32 Def, Len; if (Eoc == 0) { Def = 0; Len = 0; } else { Def = 1; Len = (u32) (Eoc - Asn1->Pointer); } if (!Asn1LenEnc(Asn1, Def, Len)) return FALSE; if (!Asn1IdrEnc(Asn1, Cls, Con, Tag)) return FALSE; return TRUE; } /******************************************************************************* * * Asn1HdrDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1HdrDec ( asn1_sck_t * Asn1, u8 ** Eoc, u32 * Cls, u32 * Con, u32 * Tag ) { u32 Def, Len; if (!Asn1IdrDec(Asn1, Cls, Con, Tag)) return FALSE; if (!Asn1LenDec(Asn1, &Def, &Len)) return FALSE; if (Def) *Eoc = Asn1->Pointer + Len; else *Eoc = 0; return TRUE; } /******************************************************************************* * * Asn1Eoc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1Eoc ( asn1_sck_t * Asn1, u8 * Eoc ) { if (Eoc == 0) return (Asn1->Pointer[0] == 0x00 && Asn1->Pointer[1] == 0x00); else return (Asn1->Pointer >= Eoc); } /******************************************************************************* * * Asn1EocEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1EocEnc ( asn1_sck_t * Asn1, u8 ** Eoc ) { if (Eoc == 0) { if (!Asn1OctEnc(Asn1, 0x00)) return FALSE; if (!Asn1OctEnc(Asn1, 0x00)) return FALSE; return TRUE; } else { *Eoc = Asn1->Pointer; return TRUE; } } /******************************************************************************* * * Asn1EocDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1EocDec ( asn1_sck_t * Asn1, u8 * Eoc ) { u8 Chr; if (Eoc == 0) { if (!Asn1OctDec(Asn1, &Chr)) return FALSE; if (Chr != 0x00) { asn1ErrStatus = ASN1_ERR_DEC_EOC_MISMATCH; return FALSE; } if (!Asn1OctDec(Asn1, &Chr)) return FALSE; if (Chr != 0x00) { asn1ErrStatus = ASN1_ERR_DEC_EOC_MISMATCH; return FALSE; } return TRUE; } else { if (Asn1->Pointer != Eoc) { asn1ErrStatus = ASN1_ERR_DEC_LENGTH_MISMATCH; return FALSE; } return TRUE; } } /******************************************************************************* * * Asn1NulEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1NulEnc ( asn1_sck_t * Asn1, u8 ** Eoc ) { *Eoc = Asn1->Pointer; return TRUE; } /******************************************************************************* * * Asn1NulDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1NulDec ( asn1_sck_t * Asn1, u8 * Eoc ) { Asn1->Pointer = Eoc; return TRUE; } /* Not used. */ #if 0 /******************************************************************************* * * Asn1IntEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntEnc ( asn1_sck_t * Asn1, u8 ** Eoc, i32 Int ) { u8 Chr, Sgn; i32 Lim; *Eoc = Asn1->Pointer; if (Int < 0) { Lim = -1; Sgn = 0x80; } else { Lim = 0; Sgn = 0x00; } do { Chr = (u8) Int; Int >>= 8; /*lint !e702 */ if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } while ((Int != Lim) || (u8) (Chr & 0x80) != Sgn); return TRUE; } /******************************************************************************* * * Asn1IntDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntDec ( asn1_sck_t * Asn1, u8 * Eoc, i32 * Int ) { u8 Chr; u32 Len; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int = (i32) Chr; Len = 1; while (Asn1->Pointer < Eoc) { if (++Len > sizeof(i32)) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int <<= 8; /*lint !e701 */ *Int |= Chr; } return TRUE; } #endif /******************************************************************************* * * Asn1IntEncLng - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntEncLng ( asn1_sck_t * Asn1, u8 ** Eoc, i32 Int ) { u8 Chr, Sgn; i32 Lim; *Eoc = Asn1->Pointer; #if(0) if (Int < 0) { Lim = -1; Sgn = 0x80; } else { Lim = 0; Sgn = 0x00; } if (Int == -1) { Lim = 0; Sgn = 0x80; } else #endif if (Int < 0) { Lim = 0; /* Was -1 */ Sgn = 0x80; } else { Lim = 0; Sgn = 0x00; } do { Chr = (u8) Int; Int = (i32) ((u32) Int >> 8); #if(0) PrintStr("\r\nChr=%#02x, Int=%#08x, Lim=%d, Sgn=%#02x", Chr, Int, Lim, Sgn); #endif if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } while ((Int != Lim) || (u8) (Chr & 0x80) != Sgn); return TRUE; } /******************************************************************************* * * Asn1IntDecLng - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntDecLng ( asn1_sck_t * Asn1, u8 * Eoc, i32 * Int ) { u8 Chr; u32 Len; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int = (i8) Chr; Len = 1; while (Asn1->Pointer < Eoc) { if (++Len > sizeof(u32)) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int <<= 8; /*lint !e701 */ *Int |= Chr; } return TRUE; } /******************************************************************************* * * Asn1IntEncUns - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntEncUns ( asn1_sck_t * Asn1, u8 ** Eoc, u32 Int ) { u8 Chr; *Eoc = Asn1->Pointer; do { Chr = (u8) Int; Int >>= 8; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } while ((Int != 0) || (Chr & 0x80) != 0x00); return TRUE; } /******************************************************************************* * * Asn1IntDecUns - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntDecUns ( asn1_sck_t * Asn1, u8 * Eoc, u32 * Int ) { u8 Chr; u32 Len; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int = Chr; if (Chr == 0) Len = 0; else Len = 1; while (Asn1->Pointer < Eoc) { if (++Len > sizeof(i32)) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int <<= 8; *Int |= Chr; } return TRUE; } /******************************************************************************* * * Asn1IntEncLngUns - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntEncLngUns ( asn1_sck_t * Asn1, u8 ** Eoc, u32 Int ) { u8 Chr; *Eoc = Asn1->Pointer; do { Chr = (u8) Int; Int >>= 8; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } while ((Int != 0) || (Chr & 0x80) != 0x00); return TRUE; } /******************************************************************************* * * Asn1IntDecLngUns - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1IntDecLngUns ( asn1_sck_t * Asn1, u8 * Eoc, u32 * Int ) { u8 Chr; u32 Len; if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int = Chr; if (Chr == 0) Len = 0; else Len = 1; while (Asn1->Pointer < Eoc) { if (++Len > sizeof(u32)) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Int <<= 8; *Int |= Chr; } return TRUE; } /******************************************************************************* * * Asn1OtsEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OtsEnc ( asn1_sck_t * Asn1, u8 ** Eoc, u8 * Ots, u32 OtsLen ) { *Eoc = Asn1->Pointer; Ots += OtsLen; while (OtsLen-- > 0) { if (!Asn1OctEnc(Asn1, *--Ots)) return FALSE; } return TRUE; } /******************************************************************************* * * Asn1OtsDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OtsDec ( asn1_sck_t * Asn1, u8 * Eoc, u8 * Ots, u32 OtsSze, u32 * OtsLen ) { *OtsLen = 0; while (Asn1->Pointer < Eoc) { if (++(*OtsLen) > OtsSze) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1OctDec(Asn1, (u8 *) Ots++)) return FALSE; } return TRUE; } /******************************************************************************* * * Asn1SbiEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1SbiEnc ( asn1_sck_t * Asn1, u32 Sbi ) { u8 Chr; Chr = (u8) (Sbi & 0x7F); Sbi >>= 7; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; while (Sbi > 0) { Chr = (u8) (Sbi | 0x80); Sbi >>= 7; if (!Asn1OctEnc(Asn1, Chr)) return FALSE; } return TRUE; } /******************************************************************************* * * Asn1SbiDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1SbiDec ( asn1_sck_t * Asn1, u32 * Sbi ) { u8 Chr; *Sbi = 0; do { if (!Asn1OctDec(Asn1, &Chr)) return FALSE; *Sbi <<= 7; *Sbi |= Chr & 0x7F; } while ((Chr & 0x80) == 0x80); return TRUE; } /******************************************************************************* * * Asn1OjiEnc - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OjiEnc ( asn1_sck_t * Asn1, u8 ** Eoc, u32 * Oji, u32 OjiLen ) { u32 Sbi; *Eoc = Asn1->Pointer; if (OjiLen < 2) { asn1ErrStatus = ASN1_ERR_ENC_BADVALUE; return FALSE; } Sbi = Oji[1] + Oji[0] * 40; Oji += OjiLen; while (OjiLen-- > 2) { if (!Asn1SbiEnc(Asn1, *--Oji)) { return FALSE; } } if (!Asn1SbiEnc(Asn1, Sbi)) { return FALSE; } return TRUE; } /******************************************************************************* * * Asn1OjiDec - * * DESCRIPTION * * RETURNS * * NOMANUAL */ int Asn1OjiDec ( asn1_sck_t * Asn1, u8 * Eoc, u32 * Oji, u32 OjiSze, u32 * OjiLen ) { u32 Sbi; if (OjiSze < 2) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1SbiDec(Asn1, &Sbi)) return FALSE; if (Sbi < 40) { Oji[0] = 0; Oji[1] = Sbi; } else { if (Sbi < 80) { Oji[0] = 1; Oji[1] = Sbi - 40; } else { Oji[0] = 2; Oji[1] = Sbi - 80; } } *OjiLen = 2; Oji += 2; while (Asn1->Pointer < Eoc) { if (++(*OjiLen) > OjiSze) { asn1ErrStatus = ASN1_ERR_DEC_BADVALUE; return FALSE; } if (!Asn1SbiDec(Asn1, Oji++)) return FALSE; } return TRUE; }