]>
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
);