]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c++-lib/c++/asn-bits.cpp 
   2   * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.    4   * The contents of this file constitute Original Code as defined in and are    5   * subject to the Apple Public Source License Version 1.2 (the 'License').    6   * You may not use this file except in compliance with the License. Please obtain    7   * a copy of the License at http://www.apple.com/publicsource and read it before   10   * This Original Code and all software distributed under the License are   11   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS   12   * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT   13   * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR   14   * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the   15   * specific language governing rights and limitations under the License.   19  // file: .../c++-lib/src/asn-bits.C - AsnBits (ASN.1 BIT STRING) Type   23  // Copyright (C) 1992 Michael Sample and the University of British Columbia   25  // This library is free software; you can redistribute it and/or   26  // modify it provided that this copyright/license information is retained   29  // If you modify this file, you must clearly indicate your changes.   31  // This source code is distributed in the hope that it will be   32  // useful, but WITHOUT ANY WARRANTY; without even the implied warranty   33  // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   35  // $Header: /cvs/root/Security/SecuritySNACCRuntime/c++-lib/c++/Attic/asn-bits.cpp,v 1.4 2002/03/21 05:38:44 dmitch Exp $   36  // $Log: asn-bits.cpp,v $   37  // Revision 1.4  2002/03/21 05:38:44  dmitch   38  // Radar 2868524: no more setjmp/longjmp in SNACC-generated code.   40  // Revision 1.3.44.1  2002/03/20 00:36:48  dmitch   41  // Radar 2868524: SNACC-generated code now uses throw/catch instead of setjmp/longjmp.   43  // Revision 1.3  2001/06/28 23:36:11  dmitch   44  // Removed SccsId statics. numToHexCharTblG table now const. Radar 2705410.   46  // Revision 1.2  2001/06/27 23:09:14  dmitch   47  // Pusuant to Radar 2664258, avoid all cerr-based output in NDEBUG configuration.   49  // Revision 1.1.1.1  2001/05/18 23:14:05  mb   50  // Move from private repository to open source repository   52  // Revision 1.3  2001/05/05 00:59:17  rmurphy   53  // Adding darwin license headers   55  // Revision 1.2  2000/12/07 22:15:49  dmitch   56  // Thread-safe mods: added a local StrStk strStkG to the routines which need it.   58  // Revision 1.1  2000/06/15 18:44:57  dmitch   59  // These snacc-generated source files are now checked in to allow cross-platform build.   61  // Revision 1.2  2000/06/08 20:05:34  dmitch   62  // Mods for X port. These files are actually machine generated and probably don't need to be in CVS....   64  // Revision 1.1.1.1  2000/03/09 01:00:05  rmurphy   65  // Base Fortissimo Tree   67  // Revision 1.3  1999/03/21 02:07:35  mb   68  // Added Copy to every AsnType.   70  // Revision 1.2  1999/02/26 00:23:39  mb   73  // Revision 1.1  1999/02/25 05:21:50  mb   74  // Added snacc c++ library   76  // Revision 1.9  1997/08/27 15:55:15  wan   77  // GetBit now returns 0 or 1, not 0 or <#bit>, even if bool type is emulated.   79  // Revision 1.8  1997/02/28 13:39:44  wan   80  // Modifications collected for new version 1.3: Bug fixes, tk4.2.   82  // Revision 1.7  1997/01/01 20:19:01  rj   83  // dereferencing pointer to member function is neither necessary nor allowed   85  // Revision 1.6  1995/08/17  15:37:49  rj   86  // set Tcl's errorCode variable   88  // Revision 1.5  1995/07/24  20:09:07  rj   89  // use memzero that is defined in .../snacc.h to use either memset or bzero.   90  // use memcmpeq that is defined in .../snacc.h to use either memcmp or bcmp.   92  // call constructor with additional pdu and create arguments.   94  // #if TCL ... #endif wrapped into #if META ... #endif   96  // changed `_' to `-' in file names.   98  // Revision 1.4  1994/10/08  04:18:21  rj   99  // code for meta structures added (provides information about the generated code itself).  101  // code for Tcl interface added (makes use of the above mentioned meta code).  103  // virtual inline functions (the destructor, the Clone() function, BEnc(), BDec() and Print()) moved from inc/*.h to src/*.C because g++ turns every one of them into a static non-inline function in every file where the .h file gets included.  105  // made Print() const (and some other, mainly comparison functions).  107  // several `unsigned long int' turned into `size_t'.  109  // Revision 1.3  1994/08/31  23:37:57  rj  110  // TRUE turned into true  112  // Revision 1.2  1994/08/28  10:01:11  rj  113  // comment leader fixed.  115  // Revision 1.1  1994/08/28  09:20:57  rj  116  // first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.  118  #include  "asn-config.h"  121  #include  "asn-type.h"  122  #include  "asn-bits.h"  127  /* OS X - thread safe - the only routine which uses this allocates  129  extern  StrStk strStkG
;  130  unsigned short int   strStkUnusedBitsG
;  131  #endif   /* __APPLE__ */  134  char  numToHexCharTblG
[ 16 ] = {  '0' ,  '1' ,  '2' ,  '3' ,  '4' ,  '5' ,  '6' ,  '7' ,  '8' ,  '9' ,  'a' ,  'b' ,  'c' ,  'd' ,  'e' ,  'f' };  141  AsnType 
* AsnBits :: Clone ()  const  146  AsnType 
* AsnBits :: Copy ()  const  148    return new  AsnBits  (* this );  151  // Initializes the bits string with a bit string numBits in length.  152  // All bits are zeroed.  153  void  AsnBits :: Set  ( size_t  numBits
)  156    size_t  octetLen 
= ( bitLen
+ 7 )/ 8 ;  159    bits 
=  Asn1Alloc  ( octetLen
);  161    bits 
= ( char  *)  mem_mgr_ptr
-> Get  ( octetLen
);        // Guido Grassel, 11.8.93  162  #endif  /* _IBM_ENC_ */  163    memzero  ( bits
,  octetLen
);  // init to zeros  166  // initializes a BIT STRING with the given string and bit length  167  // Copies the bits from bitsOcts.  168  void  AsnBits :: Set  ( const char  * bitOcts
,  size_t  numBits
)  173          size_t  octetLen 
= ( bitLen
+ 7 )/ 8 ;  175          bits 
=  new  char [ octetLen
];  177          bits 
= ( char  *)  mem_mgr_ptr
-> Get  ( octetLen
);        // Guido Grassel, 11.8.93  178  #endif  /* _IBM_ENC_ */  179          memcpy  ( bits
,  bitOcts
,  octetLen
);  183  // initializes a BIT STRING by copying another BIT STRING's bits  184  void  AsnBits :: Set  ( const  AsnBits 
& b
)  189      size_t  octetLen 
= ( bitLen
+ 7 )/ 8 ;  191      bits 
=  new  char [ octetLen
];  193      bits 
= ( char  *)  mem_mgr_ptr
-> Get  ( octetLen
);        // Guido Grassel, 11.8.93  194  #endif  /* _IBM_ENC_ */  195      memcpy  ( bits
,  b
. bits
,  octetLen
);  199  // Initializes the bits string with a bit string numBits in length.  200  // All bits are zeroed.  201  void  AsnBits :: ReSet  ( size_t  numBits
)  207    mem_mgr_ptr
-> Put  (( void  *)  bits
);        // Guido Grassel, 11.8.93  209  #endif  /* _IBM_ENC_ */  212  // frees old bits value and then re-initializes the  213  // BIT STRING with the given string and bit length  214  // Copies the bitOcts into bits.  215  void  AsnBits :: ReSet  ( const char  * bitOcts
,  size_t  numBits
)  221      Set  ( bitOcts
,  numBits
);  223      mem_mgr_ptr
-> Put  (( void  *)  bits
);        // Guido Grassel, 11.8.93  224      Set  ( bitOcts
,  numBits
);  225  #endif  /* _IBM_ENC_ */  229  // frees old bits value and then re-initializes the  230  // BIT STRING by copying another BIT STRING's bits  231  void  AsnBits :: ReSet  ( const  AsnBits 
& b
)  233    if  (& b 
!=  this )   // avoid b = b; probs  239      mem_mgr_ptr
-> Put  (( void  *)  bits
);        // Guido Grassel, 11.8.93  241  #endif  /* _IBM_ENC_ */  246  // Returns true if the given BIT STRING is the same as this one  247  bool  AsnBits :: BitsEquiv  ( const  AsnBits 
& ab
)  const  249    size_t  octetsLessOne 
= ( bitLen
- 1 )/ 8 ;  250    size_t  octetBits 
=  7  - ( bitLen 
%  8 );  252    if  (! bitLen 
&& ! ab
. bitLen
)  255    // trailing bits may not be significant  256    return  bitLen 
==  ab
. bitLen
 257      && ! memcmpeq  ( bits
,  ab
. bits
,  octetsLessOne
)  258      && ( bits
[ octetsLessOne
] & ( 0xFF  <<  octetBits
)) == ( ab
. bits
[ octetsLessOne
] & ( 0xFF  <<  octetBits
));  259  }   /* AsnBits::BitsEquiv */  262  // set given bit to 1. Most signif. bit is bit 0, least signif bit is bitLen-1  263  void  AsnBits :: SetBit  ( size_t  bit
)  267      size_t  octet 
=  bit
/ 8 ;  268      size_t  octetsBit 
=  7  - ( bit 
%  8 );    // bit zero is first/most sig bit in octet  269      bits
[ octet
] |=  1  <<  octetsBit
;  273      Asn1Errror 
<<  "AsnBits::SetBit: ERROR - bit larger than bit string"  <<  endl
;  275  }  /* AsnBits::SetBit */  277  // Clr bit. Most signif. bit is bit 0, least signif bit is bitLen-1  278  void  AsnBits :: ClrBit  ( size_t  bit
)  282      size_t  octet 
=  bit
/ 8 ;  283      size_t  octetsBit 
=  7  - ( bit 
%  8 );    // bit zero is first/most sig bit in octet  284      bits
[ octet
] &= ~( 1  <<  octetsBit
);  288      Asn1Errror 
<<  "AsnBits::ClrBit: ERROR - bit larger than bit string"  <<  endl
;  290  }  /* AsnBits::ClrBit */  292  // returns given bit. Most signif. bit is bit 0, least signif bit is bitLen-1.  293  // Returns false if the givnen bit index is out of range.  294  bool  AsnBits :: GetBit  ( size_t  bit
)  const  298      size_t  octet 
=  bit
/ 8 ;  299      size_t  octetsBit 
=  7  - ( bit 
%  8 );    // bit zero is first/most sig bit in octet  300      return  !!( bits
[ octet
] & ( 1  <<  octetsBit
));  304      Asn1Errror 
<<  "AsnBits::GetBit: ERROR - bit larger than bit string"  <<  endl
;  308  }   /* AsnBits::GetBit */  311  // Encoded the content (included unused bits octet) of the BIT STRING  312  // to the given buffer.  313  AsnLen 
AsnBits :: BEncContent  ( BUF_TYPE b
)  315      size_t  byteLen 
= ( bitLen
+ 7 )/ 8 ;  316      b
. PutSegRvs  ( bits
,  byteLen
);  318      size_t  unusedBits 
= ( bitLen 
%  8 );  320          unusedBits 
=  8  -  unusedBits
;  321      b
. PutByteRvs  ( unusedBits
);  325  }  /* AsnBits::BEncContent */  328  // Decodes a BER BIT STRING from the given buffer and stores  329  // the value in this object.  330  void  AsnBits :: BDecContent  ( BUF_TYPE b
,  AsnTag tagId
,  AsnLen elmtLen
,  AsnLen 
& bytesDecoded
,  ENV_TYPE env
)  335       * tagId is encoded tag shifted into long int.  336       * if CONS bit is set then constructed bit string  338      if  ( tagId 
&  0x20000000 )  339          BDecConsBits  ( b
,  elmtLen
,  bytesDecoded
,  env
);  341      else  /* primitive octet string */  343          bytesDecoded 
+=  elmtLen
;  345          bitLen 
= ( elmtLen 
*  8 ) - ( unsigned int ) b
. GetByte ();  347          bits 
=   Asn1Alloc  ( elmtLen
);  349          bits 
= ( char  *)  mem_mgr_ptr
-> Get  ( elmtLen
);        // Guido Grassel, 11.8.93  350  #endif  /* _IBM_ENC_ */  351          b
. CopyOut  ( bits
,  elmtLen
);  354              Asn1Error 
<<  "BDecBitString: ERROR - decoded past end of data"  <<  endl
;  355                          #if SNACC_EXCEPTION_ENABLE  356                          SnaccExcep :: throwMe (- 1 );  363  }  /* AsnBits::BDecContent */  365  AsnLen 
AsnBits :: BEnc  ( BUF_TYPE b
)  369      l 
+=  BEncDefLen  ( b
,  l
);  370      l 
+=  BEncTag1  ( b
,  UNIV
,  PRIM
,  BITSTRING_TAG_CODE
);  374  void  AsnBits :: BDec  ( BUF_TYPE b
,  AsnLen 
& bytesDecoded
,  ENV_TYPE env
)  379      tag 
=  BDecTag  ( b
,  bytesDecoded
,  env
);  380      if  (( tag 
!=  MAKE_TAG_ID  ( UNIV
,  PRIM
,  BITSTRING_TAG_CODE
))  381        && ( tag 
!=  MAKE_TAG_ID  ( UNIV
,  CONS
,  BITSTRING_TAG_CODE
)))  383          Asn1Error 
<<  "AsnBits::BDec: ERROR tag on BIT STRING is wrong."  <<  endl
;  384          #if SNACC_EXCEPTION_ENABLE  385          SnaccExcep :: throwMe (- 50 );  390      elmtLen 
=  BDecLen  ( b
,  bytesDecoded
,  env
);  391      BDecContent  ( b
,  tag
,  elmtLen
,  bytesDecoded
,  env
);  395   * Used to concatentate constructed bit strings when decoding.  397   * fills string stack with references to the pieces of a  398   * construced bit string. sets strStkUnusedBitsG appropriately.  399   * and strStkTotalByteLenG to bytelen needed to hold the bitstring  402  void  AsnBits :: FillBitStringStk  ( BUF_TYPE b
,  AsnLen elmtLen0
,   403          AsnLen 
& bytesDecoded
,  ENV_TYPE env
,  405          unsigned short int   & strStkUnusedBitsG
)  407  void  AsnBits :: FillBitStringStk  ( BUF_TYPE b
,  AsnLen elmtLen0
,   408          AsnLen 
& bytesDecoded
,  ENV_TYPE env
)  414      AsnLen totalElmtsLen1 
=  0 ;  415      unsigned long int  tagId1
;  418  //    size_t unusedBits;  420      for  (; ( totalElmtsLen1 
<  elmtLen0
) || ( elmtLen0 
==  INDEFINITE_LEN
); )  422          tagId1 
=  BDecTag  ( b
,  totalElmtsLen1
,  env
);  424          if  (( tagId1 
==  EOC_TAG_ID
) && ( elmtLen0 
==  INDEFINITE_LEN
))  426              BDEC_2ND_EOC_OCTET  ( b
,  totalElmtsLen1
,  env
);  430          elmtLen1 
=  BDecLen  ( b
,  totalElmtsLen1
,  env
);  431          if  ( tagId1 
==  MAKE_TAG_ID  ( UNIV
,  PRIM
,  BITSTRING_TAG_CODE
))  434               * primitive part of string, put references to piece (s) in  439               * get unused bits octet  441              if  ( strStkUnusedBitsG 
!=  0 )  444                   *  whoa - only allowed non-octed aligned bits on  445                   *  on last piece of bits string  447                  Asn1Error 
<<  "BDecConsBitString: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits"  <<  endl
;  448                                  #if SNACC_EXCEPTION_ENABLE  449                                  SnaccExcep :: throwMe (- 2 );  456                  strStkUnusedBitsG 
=  b
. GetByte ();  459              lenToRef 
= elmtLen1
- 1 ;  /* remove one octet for the unused bits oct*/  463                  strPtr 
=  b
. GetSeg  (& refdLen
);  465                  strStkG
. Push  ( strPtr
,  refdLen
);  466                  totalRefdLen 
+=  refdLen
;  467                  if  ( totalRefdLen 
==  lenToRef
)  468                      break ;  /* exit this while loop */  470                  if  ( refdLen 
==  0 )  /* end of data */  472                      Asn1Error 
<<  "BDecConsOctetString: ERROR - expecting more data"  <<  endl
;  473                                          #if SNACC_EXCEPTION_ENABLE  474                                          SnaccExcep :: throwMe (- 3 );  479                  refdLen 
=  lenToRef 
-  totalRefdLen
;  481              totalElmtsLen1 
+=  elmtLen1
;  485          else if  ( tagId1 
==  MAKE_TAG_ID  ( UNIV
,  CONS
,  BITSTRING_TAG_CODE
))  488               * constructed octets string embedding in this constructed  489               * octet string. decode it.  491              FillBitStringStk  ( b
,  elmtLen1
,  totalElmtsLen1
,  env
 493                                  ,  strStkG
,  strStkUnusedBitsG
 499              Asn1Error 
<<  "BDecConsBitString: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING"  <<  endl
;  500                          #if SNACC_EXCEPTION_ENABLE  501                          SnaccExcep :: throwMe (- 4 );  508      bytesDecoded 
+=  totalElmtsLen1
;  509  }   /* FillBitStringStk */  513   * decodes a seq of universally tagged bits until either EOC is  514   * encountered or the given len decoded.  Return them in a  515   * single concatenated bit string  517  void  AsnBits :: BDecConsBits  ( BUF_TYPE b
,  AsnLen elmtLen
,  AsnLen 
& bytesDecoded
,  ENV_TYPE env
)  520          StrStk 
strStkG ( 128 ,  64 );  521          unsigned short int   strStkUnusedBitsG
;  524      strStkUnusedBitsG 
=  0 ;  527       * decode each piece of the octet string, puting  528       * an entry in the octet/bit string stack for each  530      FillBitStringStk  ( b
,  elmtLen
,  bytesDecoded
,  env
,  strStkG
,   533      /* alloc single str long enough for combined bitstring */  534      bitLen 
=  strStkG
. totalByteLen
* 8  -  strStkUnusedBitsG
;  537      bits 
=  Asn1Alloc  ( strStkG
. totalByteLen
);  539      bits 
= ( char  *)  mem_mgr_ptr
-> Get  ( strStkG
. totalByteLen
);        // Guido Grassel, 11.8.93  540  #endif  /* _IBM_ENC_ */  542      strStkG
. CopyOut  ( bits
);  546  // prints the BIT STRING to the given ostream.  547  void  AsnBits :: Print  ( ostream 
& os
)  const  550      size_t  octetLen 
= ( bitLen
+ 7 )/ 8 ;  553      for  ( unsigned  i 
=  0 ;  i 
<  octetLen
;  i
++)  554          os 
<<  TO_HEX  ( bits
[ i
] >>  4 ) << ( TO_HEX  ( bits
[ i
]));  555      os 
<<  "'H  -- BIT STRING bitlen = "  <<  bitLen 
<<  " --" ;  561  const  AsnBitsTypeDesc 
AsnBits :: _desc  ( NULL
,  NULL
,  false ,  AsnTypeDesc :: BIT_STRING
,  NULL
,  NULL
);  563  const  AsnTypeDesc 
* AsnBits :: _getdesc ()  const  570  int  AsnBits :: TclGetVal  ( Tcl_Interp 
* interp
)  const  572    Tcl_ResetResult ( interp
);  573    for  ( int  i
= 0 ;  i
< bitLen
;  i
++)  574      Tcl_AppendResult ( interp
, GetBit  ( i
) ?  "1"  :  "0" , NULL
);  578  int  AsnBits :: TclSetVal  ( Tcl_Interp 
* interp
,  const char  * valstr
)  583    for  ( i
= 0 ,  p
= valstr
; * p
;  i
++,  p
++)  590          const char  c
[ 2 ] = { * p
,  '\0'  };  591          Tcl_AppendResult  ( interp
,  "illegal character '" ,  c
,  "' for bit in type " ,  _getdesc ()-> getmodule ()-> name
,  "." ,  _getdesc ()-> getname (),  NULL
);  592          Tcl_SetErrorCode  ( interp
,  "SNACC" ,  "ILLBIT" ,  NULL
);  598    for  ( i
= 0 ,  p
= valstr
;  i
< bitLen
;  i
++,  p
++)  599      * p 
==  '0'  ?  ClrBit ( i
) :  SetBit ( i
);