]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c-lib/src/asn-bits.c
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.
20 * .../c-lib/src/asn-bits.c - BER encode, decode, print and free routines for 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/Darwin/Security/SecuritySNACCRuntime/c-lib/src/asn-bits.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $
36 * $Log: asn-bits.c,v $
37 * Revision 1.1.1.1 2001/05/18 23:14:08 mb
38 * Move from private repository to open source repository
40 * Revision 1.2 2001/05/05 00:59:25 rmurphy
41 * Adding darwin license headers
43 * Revision 1.1.1.1 1999/03/16 18:06:30 aram
44 * Originals from SMIME Free Library.
46 * Revision 1.4 1995/07/27 08:57:33 rj
47 * use memcmpeq that is defined in .../snacc.h to use either memcmp or bcmp.
49 * changed `_' to `-' in file names.
51 * Revision 1.3 1994/12/11 21:51:31 rj
52 * #include <string(s).h>
54 * Revision 1.2 1994/08/31 23:56:27 rj
55 * two unused variables removed.
57 * Revision 1.1 1994/08/28 09:45:50 rj
58 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
62 #include "asn-config.h"
64 #if STDC_HEADERS || HAVE_STRING_H
75 static unsigned short int unusedBitsG
;
77 char numToHexCharTblG
[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
82 * encodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING
85 BEncAsnBits
PARAMS ((b
, data
),
91 len
= BEncAsnBitsContent (b
, data
);
92 len
+= BEncDefLen (b
, len
);
93 len
+= BEncTag1 (b
, UNIV
, PRIM
, BITSTRING_TAG_CODE
);
99 * decodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING
102 BDecAsnBits
PARAMS ((b
, result
, bytesDecoded
, env
),
104 AsnBits
*result _AND_
105 AsnLen
*bytesDecoded _AND_
111 if (((tag
=BDecTag (b
, bytesDecoded
, env
)) !=
112 MAKE_TAG_ID (UNIV
, PRIM
, BITSTRING_TAG_CODE
)) &&
113 (tag
!= MAKE_TAG_ID (UNIV
, CONS
, BITSTRING_TAG_CODE
)))
115 Asn1Error ("BDecAsnBits: ERROR - wrong tag on BIT STRING.\n");
119 elmtLen
= BDecLen (b
, bytesDecoded
, env
);
120 BDecAsnBitsContent (b
, tag
, elmtLen
, result
, bytesDecoded
, env
);
127 * Encodes the BIT STRING value (including the unused bits
128 * byte) to the given buffer.
131 BEncAsnBitsContent
PARAMS ((b
, bits
),
135 unsigned long int unusedBits
;
136 unsigned long int byteLen
;
138 if (bits
->bitLen
== 0)
141 byteLen
= ((bits
->bitLen
-1) / 8) + 1;
143 BufPutSegRvs (b
, bits
->bits
, byteLen
);
144 unusedBits
= (bits
->bitLen
% 8);
146 unusedBits
= 8 - unusedBits
;
147 BufPutByteRvs (b
, unusedBits
);
150 } /* BEncAsnBitsContent */
154 * Used when decoding to combine constructed pieces into one
156 * Fills string stack with references to the pieces of a
157 * construced bit string. sets unusedBitsG appropriately.
158 * and strStkG.totalByteLenG to bytelen needed to hold the bitstring
161 FillBitStringStk
PARAMS ((b
, elmtLen0
, bytesDecoded
, env
),
163 AsnLen elmtLen0 _AND_
164 AsnLen
*bytesDecoded _AND_
167 unsigned long int refdLen
;
168 unsigned long int totalRefdLen
;
170 unsigned long int totalElmtsLen1
= 0;
171 unsigned long int tagId1
;
172 unsigned long int elmtLen1
;
173 unsigned long int lenToRef
;
175 for (; (totalElmtsLen1
< elmtLen0
) || (elmtLen0
== INDEFINITE_LEN
); )
177 tagId1
= BDecTag (b
, &totalElmtsLen1
, env
);
179 if ((tagId1
== EOC_TAG_ID
) && (elmtLen0
== INDEFINITE_LEN
))
181 BDEC_2ND_EOC_OCTET (b
, &totalElmtsLen1
, env
);
185 elmtLen1
= BDecLen (b
, &totalElmtsLen1
, env
);
186 if (tagId1
== MAKE_TAG_ID (UNIV
, PRIM
, BITSTRING_TAG_CODE
))
189 * primitive part of string, put references to piece (s) in
194 * get unused bits octet
196 if (unusedBitsG
!= 0)
199 * whoa - only allowed non-octet aligned bits on
200 * on last piece of bits string
202 Asn1Error ("FillBitStringStk: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits\n");
207 unusedBitsG
= BufGetByte (b
);
210 lenToRef
=elmtLen1
-1; /* remove one octet for the unused bits oct*/
214 strPtr
= BufGetSeg (b
, &refdLen
);
216 PUSH_STR (strPtr
, refdLen
, env
);
217 totalRefdLen
+= refdLen
;
218 if (totalRefdLen
== lenToRef
)
219 break; /* exit this while loop */
221 if (refdLen
== 0) /* end of data */
223 Asn1Error ("FillBitStringStk: ERROR - expecting more data\n");
226 refdLen
= lenToRef
- totalRefdLen
;
228 totalElmtsLen1
+= elmtLen1
;
232 else if (tagId1
== MAKE_TAG_ID (UNIV
, CONS
, BITSTRING_TAG_CODE
))
235 * constructed octets string embedding in this constructed
236 * octet string. decode it.
238 FillBitStringStk (b
, elmtLen1
, &totalElmtsLen1
, env
);
242 Asn1Error ("FillBitStringStk: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING\n");
247 (*bytesDecoded
) += totalElmtsLen1
;
249 } /* FillBitStringStk */
253 * Decodes a seq of universally tagged bits until either EOC is
254 * encountered or the given len decoded. Returns them in a
255 * single concatenated bit string
258 BDecConsAsnBits
PARAMS ((b
, len
, result
, bytesDecoded
, env
),
261 AsnBits
*result _AND_
262 AsnLen
*bytesDecoded _AND_
266 unsigned long int curr
;
271 * decode each piece of the octet string, puting
272 * an entry in the octet/bit string stack for each
274 FillBitStringStk (b
, len
, bytesDecoded
, env
);
276 /* alloc single str long enough for combined bitstring */
277 result
->bitLen
= strStkG
.totalByteLen
*8 - unusedBitsG
;
279 bufCurr
= result
->bits
= Asn1Alloc (strStkG
.totalByteLen
);
281 /* copy bit string pieces (buffer refs) into single block */
282 for (curr
= 0; curr
< strStkG
.nextFreeElmt
; curr
++)
284 memcpy (bufCurr
, strStkG
.stk
[curr
].str
, strStkG
.stk
[curr
].len
);
285 bufCurr
+= strStkG
.stk
[curr
].len
;
288 } /* BDecConsAsnBits */
291 * Decodes the content of a BIT STRING (including the unused bits octet)
292 * Always returns a single contiguous bit string
295 BDecAsnBitsContent
PARAMS ((b
, tagId
, len
, result
, bytesDecoded
, env
),
299 AsnBits
*result _AND_
300 AsnLen
*bytesDecoded _AND_
304 * tagId is encoded tag shifted into long int.
305 * if CONS bit is set then constructed bit string
307 if (TAG_IS_CONS (tagId
))
308 BDecConsAsnBits (b
, len
, result
, bytesDecoded
, env
);
309 else /* primitive octet string */
311 (*bytesDecoded
) += len
;
313 result
->bitLen
= (len
* 8) - (unsigned int)BufGetByte (b
);
314 result
->bits
= Asn1Alloc (len
);
315 BufCopy (result
->bits
, b
, len
);
316 if (BufReadError (b
))
318 Asn1Error ("BDecAsnBitsContent: ERROR - decoded past end of data\n");
322 } /* BDecAsnBitsContent */
327 * Frees the string part of a BIT STRING
330 FreeAsnBits
PARAMS ((v
),
338 * Prints the contents of the given BIT STRING to the
339 * given file. indent is ignored. Always uses ASN.1 Value Notaion
340 * Hex format. (Should be binary versions in some cases)
343 PrintAsnBits
PARAMS ((f
,v
, indent
),
346 unsigned short indent
)
349 unsigned long int octetLen
;
354 octetLen
= (v
->bitLen
-1)/8 +1;
357 for (i
= 0; i
< octetLen
; i
++)
358 fprintf (f
,"%c%c", TO_HEX (v
->bits
[i
] >> 4), TO_HEX (v
->bits
[i
]));
364 * Returns TRUE if the given BIT STRINGs are identical.
365 * Otherwise returns FALSE.
368 AsnBitsEquiv
PARAMS ((b1
, b2
),
375 if ((b1
->bitLen
== 0) && (b2
->bitLen
== 0))
378 octetsLessOne
= (b1
->bitLen
-1)/8;
379 octetBits
= 7 - (b1
->bitLen
% 8);
381 /* trailing bits may not be significant */
382 return b1
->bitLen
== b2
->bitLen
&& !memcmpeq (b1
->bits
, b2
->bits
, octetsLessOne
) && ((b1
->bits
[octetsLessOne
] & (0xFF << octetBits
)) == (b1
->bits
[octetsLessOne
] & (0xFF << octetBits
)));
388 * Set given bit to 1. Most significant bit is bit 0, least significant
389 * is bit (v1->bitLen -1)
392 SetAsnBit
PARAMS ((b1
, bit
),
394 unsigned long int bit
)
396 unsigned long int octet
;
397 unsigned long int octetsBit
;
399 if (bit
< b1
->bitLen
)
402 octetsBit
= 7 - (bit
% 8);/* bit zero is first/most sig bit in octet */
403 b1
->bits
[octet
] |= 1 << octetsBit
;
409 * Set given bit to 0. Most significant bit is bit 0, least significant
410 * is bit (v1->bitLen -1)
413 ClrAsnBit
PARAMS ((b1
, bit
),
415 unsigned long int bit
)
417 unsigned long int octet
;
418 unsigned long int octetsBit
;
420 if (bit
< b1
->bitLen
)
423 octetsBit
= 7 - (bit
% 8);/* bit zero is first/most sig bit in octet */
424 b1
->bits
[octet
] &= ~(1 << octetsBit
);
431 * Get given bit. Most significant bit is bit 0, least significant
432 * is bit (v1->bitLen -1). Returns TRUE if the bit is 1. Returns FALSE
433 * if the bit is 0. if the bit is out of range then returns 0.
436 GetAsnBit
PARAMS ((b1
, bit
),
438 unsigned long int bit
)
440 unsigned long int octet
;
441 unsigned long int octetsBit
;
443 if (bit
< b1
->bitLen
)
446 octetsBit
= 7 - (bit
% 8); /* bit zero is first/most sig bit in octet*/
447 return b1
->bits
[octet
] & (1 << octetsBit
);
450 } /* AsnBits::GetBit */