1%% ``Licensed under the Apache License, Version 2.0 (the "License"); 2%% you may not use this file except in compliance with the License. 3%% You may obtain a copy of the License at 4%% 5%% http://www.apache.org/licenses/LICENSE-2.0 6%% 7%% Unless required by applicable law or agreed to in writing, software 8%% distributed under the License is distributed on an "AS IS" BASIS, 9%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10%% See the License for the specific language governing permissions and 11%% limitations under the License. 12%% 13%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. 14%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings 15%% AB. All Rights Reserved.'' 16%% 17%% $Id: asn1rt_ber_bin.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $ 18-module(asn1rt_ber_bin). 19 20%% encoding / decoding of BER 21 22-export([decode/1]). 23-export([fixoptionals/2,split_list/2,cindex/3,restbytes2/3, 24 list_to_record/2, 25 encode_tag_val/1,decode_tag/1,peek_tag/1, 26 check_tags/3, encode_tags/3]). 27-export([encode_boolean/2,decode_boolean/3, 28 encode_integer/3,encode_integer/4, 29 decode_integer/4,decode_integer/5,encode_enumerated/2, 30 encode_enumerated/4,decode_enumerated/5, 31 encode_real/2,decode_real/4, 32 encode_bit_string/4,decode_bit_string/6, 33 decode_compact_bit_string/6, 34 encode_octet_string/3,decode_octet_string/5, 35 encode_null/2,decode_null/3, 36 encode_object_identifier/2,decode_object_identifier/3, 37 encode_restricted_string/4,decode_restricted_string/6, 38 encode_universal_string/3,decode_universal_string/5, 39 encode_BMP_string/3,decode_BMP_string/5, 40 encode_generalized_time/3,decode_generalized_time/5, 41 encode_utc_time/3,decode_utc_time/5, 42 encode_length/1,decode_length/1, 43 check_if_valid_tag/3, 44 decode_tag_and_length/1, decode_components/6, 45 decode_components/7, decode_set/6]). 46 47-export([encode_open_type/1,encode_open_type/2,decode_open_type/1,decode_open_type/2,decode_open_type/3]). 48-export([skipvalue/1, skipvalue/2]). 49 50-include("asn1_records.hrl"). 51 52% the encoding of class of tag bits 8 and 7 53-define(UNIVERSAL, 0). 54-define(APPLICATION, 16#40). 55-define(CONTEXT, 16#80). 56-define(PRIVATE, 16#C0). 57 58%%% primitive or constructed encoding % bit 6 59-define(PRIMITIVE, 0). 60-define(CONSTRUCTED, 2#00100000). 61 62%%% The tag-number for universal types 63-define(N_BOOLEAN, 1). 64-define(N_INTEGER, 2). 65-define(N_BIT_STRING, 3). 66-define(N_OCTET_STRING, 4). 67-define(N_NULL, 5). 68-define(N_OBJECT_IDENTIFIER, 6). 69-define(N_OBJECT_DESCRIPTOR, 7). 70-define(N_EXTERNAL, 8). 71-define(N_REAL, 9). 72-define(N_ENUMERATED, 10). 73-define(N_EMBEDDED_PDV, 11). 74-define(N_SEQUENCE, 16). 75-define(N_SET, 17). 76-define(N_NumericString, 18). 77-define(N_PrintableString, 19). 78-define(N_TeletexString, 20). 79-define(N_VideotexString, 21). 80-define(N_IA5String, 22). 81-define(N_UTCTime, 23). 82-define(N_GeneralizedTime, 24). 83-define(N_GraphicString, 25). 84-define(N_VisibleString, 26). 85-define(N_GeneralString, 27). 86-define(N_UniversalString, 28). 87-define(N_BMPString, 30). 88 89 90% the complete tag-word of built-in types 91-define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1). 92-define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2). 93-define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED 94-define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED 95-define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5). 96-define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6). 97-define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7). 98-define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8). 99-define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9). 100-define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10). 101-define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11). 102-define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16). 103-define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17). 104-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed 105-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed 106-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed 107-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed 108-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed 109-define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23). 110-define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24). 111-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed 112-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed 113-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed 114-define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed 115-define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed 116 117 118decode(Bin) -> 119 decode_primitive(Bin). 120 121decode_primitive(Bin) -> 122 {Tlv = {Tag,Len,V},<<>>} = decode_tlv(Bin), 123 case element(2,Tag) of 124 ?CONSTRUCTED -> 125 {Tag,Len,decode_constructed(V)}; 126 _ -> 127 Tlv 128 end. 129 130decode_constructed(<<>>) -> 131 []; 132decode_constructed(Bin) -> 133 {Tlv = {Tag,Len,V},Rest} = decode_tlv(Bin), 134 NewTlv = 135 case element(2,Tag) of 136 ?CONSTRUCTED -> 137 {Tag,Len,decode_constructed(V)}; 138 _ -> 139 Tlv 140 end, 141 [NewTlv|decode_constructed(Rest)]. 142 143decode_tlv(Bin) -> 144 {Tag,Bin1,_Rb1} = decode_tag(Bin), 145 {{Len,Bin2},_Rb2} = decode_length(Bin1), 146 <<V:Len/binary,Bin3/binary>> = Bin2, 147 {{Tag,Len,V},Bin3}. 148 149 150 151%%%%%%%%%%%%% 152% split_list(List,HeadLen) -> {HeadList,TailList} 153% 154% splits List into HeadList (Length=HeadLen) and TailList 155% if HeadLen == indefinite -> return {List,indefinite} 156split_list(List,indefinite) -> 157 {List, indefinite}; 158split_list(Bin, Len) when binary(Bin) -> 159 split_binary(Bin,Len); 160split_list(List,Len) -> 161 {lists:sublist(List,Len),lists:nthtail(Len,List)}. 162 163 164%%% new function which fixes a bug regarding indefinite length decoding 165restbytes2(indefinite,<<0,0,RemBytes/binary>>,_) -> 166 {RemBytes,2}; 167restbytes2(indefinite,RemBytes,ext) -> 168 skipvalue(indefinite,RemBytes); 169restbytes2(RemBytes,<<>>,_) -> 170 {RemBytes,0}; 171restbytes2(_RemBytes,Bytes,noext) -> 172 exit({error,{asn1, {unexpected,Bytes}}}); 173restbytes2(RemBytes,_Bytes,ext) -> 174 {RemBytes,0}. 175 176 177 178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 179%% skipvalue(Length, Bytes) -> {RemainingBytes, RemovedNumberOfBytes} 180%% 181%% skips the one complete (could be nested) TLV from Bytes 182%% handles both definite and indefinite length encodings 183%% 184 185skipvalue(L, Bytes) -> 186 skipvalue(L, Bytes, 0). 187 188skipvalue(indefinite, Bytes, Rb) -> 189 {_T,Bytes2,R2} = decode_tag(Bytes), 190 {{L,Bytes3},R3} = decode_length(Bytes2), 191 {Bytes4,Rb4} = case L of 192 indefinite -> 193 skipvalue(indefinite,Bytes3,R2+R3); 194 _ -> 195 <<_:L/binary, RestBytes/binary>> = Bytes3, 196 {RestBytes, R2+R3+L} 197 end, 198 case Bytes4 of 199 <<0,0,Bytes5/binary>> -> 200 {Bytes5,Rb+Rb4+2}; 201 _ -> skipvalue(indefinite,Bytes4,Rb+Rb4) 202 end; 203skipvalue(L, Bytes, Rb) -> 204% <<Skip:L/binary, RestBytes/binary>> = Bytes, 205 <<_:L/binary, RestBytes/binary>> = Bytes, 206 {RestBytes,Rb+L}. 207 208%%skipvalue(indefinite, Bytes, Rb) -> 209%% {T,Bytes2,R2} = decode_tag(Bytes), 210%% {L,Bytes3,R3} = decode_length(Bytes2), 211%% {Bytes4,Rb4} = case L of 212%% indefinite -> 213%% skipvalue(indefinite,Bytes3,R2+R3); 214%% _ -> 215%% lists:nthtail(L,Bytes3) %% konstigt !? 216%% end, 217%% case Bytes4 of 218%% [0,0|Bytes5] -> 219%% {Bytes5,Rb4+2}; 220%% _ -> skipvalue(indefinite,Bytes4,Rb4) 221%% end; 222%%skipvalue(L, Bytes, Rb) -> 223%% {lists:nthtail(L,Bytes),Rb+L}. 224 225skipvalue(Bytes) -> 226 {_T,Bytes2,R2} = decode_tag(Bytes), 227 {{L,Bytes3},R3} = decode_length(Bytes2), 228 skipvalue(L,Bytes3,R2+R3). 229 230 231cindex(Ix,Val,Cname) -> 232 case element(Ix,Val) of 233 {Cname,Val2} -> Val2; 234 X -> X 235 end. 236 237%%=============================================================================== 238%%=============================================================================== 239%%=============================================================================== 240%% Optionals, preset not filled optionals with asn1_NOVALUE 241%%=============================================================================== 242%%=============================================================================== 243%%=============================================================================== 244 245% converts a list to a record if necessary 246list_to_record(Name,List) when list(List) -> 247 list_to_tuple([Name|List]); 248list_to_record(_Name,Tuple) when tuple(Tuple) -> 249 Tuple. 250 251 252fixoptionals(OptList,Val) when list(Val) -> 253 fixoptionals(OptList,Val,1,[],[]). 254 255fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) -> 256 fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]); 257fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) -> 258 fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]); 259fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) -> 260 fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]); 261fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) -> 262 fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]); 263fixoptionals([],[],_,_Acc1,Acc2) -> 264 % return Val as a record 265 list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]). 266 267 268%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) -> 269%% 8bit Int | binary 270encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) -> 271 <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>; 272 273encode_tag_val({Class, Form, TagNo}) -> 274 {Octets,_Len} = mk_object_val(TagNo), 275 BinOct = list_to_binary(Octets), 276 <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>; 277 278%% asumes whole correct tag bitpattern, multiple of 8 279encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% is this function used??!! 280%% asumes correct bitpattern of 0-5 281encode_tag_val(Tag) -> encode_tag_val2(Tag,[]). 282 283encode_tag_val2(Tag, OctAck) when (Tag =< 255) -> 284 [Tag | OctAck]; 285encode_tag_val2(Tag, OctAck) -> 286 encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]). 287 288 289%%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) -> 290%%% 8bit Int | [list of octets] 291%encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) -> 292%%% <<Class:2,Form:1,TagNo:5>>; 293% [Class bor Form bor TagNo]; 294%encode_tag_val({Class, Form, TagNo}) -> 295% {Octets,L} = mk_object_val(TagNo), 296% [Class bor Form bor 31 | Octets]; 297 298 299%%============================================================================\%% Peek on the initial tag 300%% peek_tag(Bytes) -> TagBytes 301%% interprets the first byte and possible second, third and fourth byte as 302%% a tag and returns all the bytes comprising the tag, the constructed/primitive bit (6:th bit of first byte) is normalised to 0 303%% 304 305peek_tag(<<B7_6:2,_:1,31:5,Buffer/binary>>) -> 306 Bin = peek_tag(Buffer, <<>>), 307 <<B7_6:2,31:6,Bin/binary>>; 308%% single tag (tagno < 31) 309peek_tag(<<B7_6:2,_:1,B4_0:5,_Buffer/binary>>) -> 310 <<B7_6:2,B4_0:6>>. 311 312peek_tag(<<0:1,PartialTag:7,_Buffer/binary>>, TagAck) -> 313 <<TagAck/binary,PartialTag>>; 314peek_tag(<<PartialTag,Buffer/binary>>, TagAck) -> 315 peek_tag(Buffer,<<TagAck/binary,PartialTag>>); 316peek_tag(_,TagAck) -> 317 exit({error,{asn1, {invalid_tag,TagAck}}}). 318%%peek_tag([Tag|Buffer]) when (Tag band 31) == 31 -> 319%% [Tag band 2#11011111 | peek_tag(Buffer,[])]; 320%%%% single tag (tagno < 31) 321%%peek_tag([Tag|Buffer]) -> 322%% [Tag band 2#11011111]. 323 324%%peek_tag([PartialTag|Buffer], TagAck) when (PartialTag < 128 ) -> 325%% lists:reverse([PartialTag|TagAck]); 326%%peek_tag([PartialTag|Buffer], TagAck) -> 327%% peek_tag(Buffer,[PartialTag|TagAck]); 328%%peek_tag(Buffer,TagAck) -> 329%% exit({error,{asn1, {invalid_tag,lists:reverse(TagAck)}}}). 330 331 332%%=============================================================================== 333%% Decode a tag 334%% 335%% decode_tag(OctetListBuffer) -> {{Class, Form, TagNo}, RestOfBuffer, RemovedBytes} 336%%=============================================================================== 337 338%% multiple octet tag 339decode_tag(<<Class:2, Form:1, 31:5, Buffer/binary>>) -> 340 {TagNo, Buffer1, RemovedBytes} = decode_tag(Buffer, 0, 1), 341 {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer1, RemovedBytes}; 342 343%% single tag (< 31 tags) 344decode_tag(<<Class:2,Form:1,TagNo:5, Buffer/binary>>) -> 345 {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1}. 346 347%% last partial tag 348decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) -> 349 TagNo = (TagAck bsl 7) bor PartialTag, 350 %%<<TagNo>> = <<TagAck:1, PartialTag:7>>, 351 {TagNo, Buffer, RemovedBytes+1}; 352% more tags 353decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) -> 354 TagAck1 = (TagAck bsl 7) bor PartialTag, 355 %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>, 356 decode_tag(Buffer, TagAck1, RemovedBytes+1). 357 358%%------------------------------------------------------------------ 359%% check_tags_i is the same as check_tags except that it stops and 360%% returns the remaining tags not checked when it encounters an 361%% indefinite length field 362%% only called internally within this module 363 364check_tags_i([Tag], Buffer, OptOrMand) -> % optimized very usual case 365 {[],check_one_tag(Tag, Buffer, OptOrMand)}; 366check_tags_i(Tags, Buffer, OptOrMand) -> 367 check_tags_i(Tags, Buffer, 0, OptOrMand). 368 369check_tags_i([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand) 370 when Tag1#tag.type == 'IMPLICIT' -> 371 check_tags_i([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand); 372 373check_tags_i([Tag1|TagRest], Buffer, Rb, OptOrMand) -> 374 {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand), 375 case TagRest of 376 [] -> {TagRest, {Form_Length, Buffer2, Rb + Rb1}}; 377 _ -> 378 case Form_Length of 379 {?CONSTRUCTED,_} -> 380 {TagRest, {Form_Length, Buffer2, Rb + Rb1}}; 381 _ -> 382 check_tags_i(TagRest, Buffer2, Rb + Rb1, mandatory) 383 end 384 end; 385 386check_tags_i([], Buffer, Rb, _) -> 387 {[],{{0,0},Buffer,Rb}}. 388 389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 390%% This function is called from generated code 391 392check_tags([Tag], Buffer, OptOrMand) -> % optimized very usual case 393 check_one_tag(Tag, Buffer, OptOrMand); 394check_tags(Tags, Buffer, OptOrMand) -> 395 check_tags(Tags, Buffer, 0, OptOrMand). 396 397check_tags([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand) 398 when Tag1#tag.type == 'IMPLICIT' -> 399 check_tags([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand); 400 401check_tags([Tag1|TagRest], Buffer, Rb, OptOrMand) -> 402 {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand), 403 case TagRest of 404 [] -> {Form_Length, Buffer2, Rb + Rb1}; 405 _ -> check_tags(TagRest, Buffer2, Rb + Rb1, mandatory) 406 end; 407 408check_tags([], Buffer, Rb, _) -> 409 {{0,0},Buffer,Rb}. 410 411check_one_tag(Tag=#tag{class=ExpectedClass,number=ExpectedNumber}, Buffer, OptOrMand) -> 412 case catch decode_tag(Buffer) of 413 {'EXIT',_Reason} -> 414 tag_error(no_data,Tag,Buffer,OptOrMand); 415 {{ExpectedClass,Form,ExpectedNumber},Buffer2,Rb} -> 416 {{L,Buffer3},RemBytes2} = decode_length(Buffer2), 417 {{Form,L}, Buffer3, RemBytes2+Rb}; 418 {ErrorTag,_,_} -> 419 tag_error(ErrorTag, Tag, Buffer, OptOrMand) 420 end. 421 422tag_error(ErrorTag, Tag, Buffer, OptOrMand) -> 423 case OptOrMand of 424 mandatory -> 425 exit({error,{asn1, {invalid_tag, 426 {ErrorTag, Tag, Buffer}}}}); 427 _ -> 428 exit({error,{asn1, {no_optional_tag, 429 {ErrorTag, Tag, Buffer}}}}) 430 end. 431%%======================================================================= 432%% 433%% Encode all tags in the list Tags and return a possibly deep list of 434%% bytes with tag and length encoded 435%% 436%% prepend_tags(Tags, BytesSoFar, LenSoFar) -> {Bytes, Len} 437encode_tags(Tags, BytesSoFar, LenSoFar) -> 438 NewTags = encode_tags1(Tags, []), 439 %% NewTags contains the resulting tags in reverse order 440 encode_tags2(NewTags, BytesSoFar, LenSoFar). 441 442%encode_tags2([#tag{class=?UNIVERSAL,number=No}|Trest], BytesSoFar, LenSoFar) -> 443% {Bytes2,L2} = encode_length(LenSoFar), 444% encode_tags2(Trest,[[No|Bytes2],BytesSoFar], LenSoFar + 1 + L2); 445encode_tags2([Tag|Trest], BytesSoFar, LenSoFar) -> 446 {Bytes1,L1} = encode_one_tag(Tag), 447 {Bytes2,L2} = encode_length(LenSoFar), 448 encode_tags2(Trest, [Bytes1,Bytes2|BytesSoFar], 449 LenSoFar + L1 + L2); 450encode_tags2([], BytesSoFar, LenSoFar) -> 451 {BytesSoFar,LenSoFar}. 452 453encode_tags1([Tag1, Tag2| Trest], Acc) 454 when Tag1#tag.type == 'IMPLICIT' -> 455 encode_tags1([Tag1#tag{type=Tag2#tag.type,form=Tag2#tag.form}|Trest],Acc); 456encode_tags1([Tag1 | Trest], Acc) -> 457 encode_tags1(Trest, [Tag1|Acc]); 458encode_tags1([], Acc) -> 459 Acc. % the resulting tags are returned in reverse order 460 461encode_one_tag(Bin) when binary(Bin) -> 462 {Bin,size(Bin)}; 463encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) -> 464 NewForm = case Type of 465 'EXPLICIT' -> 466 ?CONSTRUCTED; 467 _ -> 468 Form 469 end, 470 Bytes = encode_tag_val({Class,NewForm,No}), 471 {Bytes,size(Bytes)}. 472 473%%=============================================================================== 474%% Change the tag (used when an implicit tagged type has a reference to something else) 475%% The constructed bit in the tag is taken from the tag to be replaced. 476%% 477%% change_tag(NewTag,[Tag,Buffer]) -> [NewTag,Buffer] 478%%=============================================================================== 479 480%change_tag({NewClass,NewTagNr}, Buffer) -> 481% {{OldClass, OldForm, OldTagNo}, Buffer1, RemovedBytes} = decode_tag(lists:flatten(Buffer)), 482% [encode_tag_val({NewClass, OldForm, NewTagNr}) | Buffer1]. 483 484 485 486 487 488 489 490%%=============================================================================== 491%% 492%% This comment is valid for all the encode/decode functions 493%% 494%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound} 495%% used for PER-coding but not for BER-coding. 496%% 497%% Val = Value. If Val is an atom then it is a symbolic integer value 498%% (i.e the atom must be one of the names in the NamedNumberList). 499%% The NamedNumberList is used to translate the atom to an integer value 500%% before encoding. 501%% 502%%=============================================================================== 503 504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 505%% encode_open_type(Value) -> CompleteList 506%% Value = list of bytes of an already encoded value (the list must be flat) 507%% | binary 508 509%% This version does not consider Explicit tagging of the open type. It 510%% is only left because of backward compatibility. 511encode_open_type(Val) when list(Val) -> 512 {Val,size(list_to_binary(Val))}; 513encode_open_type(Val) -> 514 {Val, size(Val)}. 515 516%% 517encode_open_type(Val, []) when list(Val) -> 518 {Val,size(list_to_binary(Val))}; 519encode_open_type(Val,[]) -> 520 {Val, size(Val)}; 521encode_open_type(Val, Tag) when list(Val) -> 522 encode_tags(Tag,Val,size(list_to_binary(Val))); 523encode_open_type(Val,Tag) -> 524 encode_tags(Tag,Val, size(Val)). 525 526 527 528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 529%% decode_open_type(Buffer) -> Value 530%% Bytes = [byte] with BER encoded data 531%% Value = [byte] with decoded data (which must be decoded again as some type) 532%% 533decode_open_type(Bytes) -> 534 {_Tag, Len, _RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes), 535 N = Len + RemovedBytes, 536 <<Val:N/binary, RemainingBytes/binary>> = Bytes, 537 {Val, RemainingBytes, Len + RemovedBytes}. 538 539decode_open_type(Bytes,ExplTag) -> 540 {Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes), 541 case {Tag,ExplTag} of 542 {{Class,Form,No},[#tag{class=Class,number=No,form=Form}]} -> 543 {_Tag2, Len2, _RemainingBuffer2, RemovedBytes2} = decode_tag_and_length(RemainingBuffer), 544 N = Len2 + RemovedBytes2, 545 <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes, 546 {Val, RemainingBytes, N + RemovedBytes}; 547 _ -> 548 N = Len + RemovedBytes, 549 <<Val:N/binary, RemainingBytes/binary>> = Bytes, 550 {Val, RemainingBytes, Len + RemovedBytes} 551 end. 552 553decode_open_type(ber_bin,Bytes,ExplTag) -> 554 decode_open_type(Bytes,ExplTag); 555decode_open_type(ber,Bytes,ExplTag) -> 556 {Val,RemBytes,Len}=decode_open_type(Bytes,ExplTag), 557 {binary_to_list(Val),RemBytes,Len}. 558 559%%=============================================================================== 560%%=============================================================================== 561%%=============================================================================== 562%% Boolean, ITU_T X.690 Chapter 8.2 563%%=============================================================================== 564%%=============================================================================== 565%%=============================================================================== 566 567%%=============================================================================== 568%% encode_boolean(Integer, tag | notag) -> [octet list] 569%%=============================================================================== 570 571encode_boolean({Name, Val}, DoTag) when atom(Name) -> 572 dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val)); 573encode_boolean(true,[]) -> 574 {[1,1,16#FF],3}; 575encode_boolean(false,[]) -> 576 {[1,1,0],3}; 577encode_boolean(Val, DoTag) -> 578 dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val)). 579 580%% encode_boolean(Boolean) -> [Len, Boolean] = [1, $FF | 0] 581encode_boolean(true) -> {[16#FF],1}; 582encode_boolean(false) -> {[0],1}; 583encode_boolean(X) -> exit({error,{asn1, {encode_boolean, X}}}). 584 585 586%%=============================================================================== 587%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} | 588%% {false, Remain, RemovedBytes} 589%%=============================================================================== 590 591decode_boolean(Buffer, Tags, OptOrMand) -> 592 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_BOOLEAN}), 593 decode_boolean_notag(Buffer, NewTags, OptOrMand). 594 595decode_boolean_notag(Buffer, Tags, OptOrMand) -> 596 {RestTags, {FormLen,Buffer0,Rb0}} = 597 check_tags_i(Tags, Buffer, OptOrMand), 598 case FormLen of 599 {?CONSTRUCTED,Len} -> 600 {Buffer00,RestBytes} = split_list(Buffer0,Len), 601 {Val,Buffer1,Rb1} = decode_boolean_notag(Buffer00, RestTags, OptOrMand), 602 {Buffer2, Rb2} = restbytes2(RestBytes,Buffer1,noext), 603 {Val, Buffer2, Rb0+Rb1+Rb2}; 604 {_,_} -> 605 decode_boolean2(Buffer0, Rb0) 606 end. 607 608decode_boolean2(<<0:8, Buffer/binary>>, RemovedBytes) -> 609 {false, Buffer, RemovedBytes + 1}; 610decode_boolean2(<<_:8, Buffer/binary>>, RemovedBytes) -> 611 {true, Buffer, RemovedBytes + 1}; 612decode_boolean2(Buffer, _) -> 613 exit({error,{asn1, {decode_boolean, Buffer}}}). 614 615 616 617 618%%=========================================================================== 619%% Integer, ITU_T X.690 Chapter 8.3 620 621%% encode_integer(Constraint, Value, Tag) -> [octet list] 622%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list] 623%% Value = INTEGER | {Name,INTEGER} 624%% Tag = tag | notag 625%%=========================================================================== 626 627encode_integer(C, Val, []) when integer(Val) -> 628 {EncVal,Len}=encode_integer(C, Val), 629 dotag_universal(?N_INTEGER,EncVal,Len); 630encode_integer(C, Val, Tag) when integer(Val) -> 631 dotag(Tag, ?N_INTEGER, encode_integer(C, Val)); 632encode_integer(C,{Name,Val},Tag) when atom(Name) -> 633 encode_integer(C,Val,Tag); 634encode_integer(_, Val, _) -> 635 exit({error,{asn1, {encode_integer, Val}}}). 636 637 638 639encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) -> 640 case lists:keysearch(Val, 1, NamedNumberList) of 641 {value,{_, NewVal}} -> 642 dotag(Tag, ?N_INTEGER, encode_integer(C, NewVal)); 643 _ -> 644 exit({error,{asn1, {encode_integer_namednumber, Val}}}) 645 end; 646encode_integer(C,{_,Val},NamedNumberList,Tag) -> 647 encode_integer(C,Val,NamedNumberList,Tag); 648encode_integer(C, Val, _NamedNumberList, Tag) -> 649 dotag(Tag, ?N_INTEGER, encode_integer(C, Val)). 650 651 652 653 654encode_integer(_C, Val) -> 655 Bytes = 656 if 657 Val >= 0 -> 658 encode_integer_pos(Val, []); 659 true -> 660 encode_integer_neg(Val, []) 661 end, 662 {Bytes,length(Bytes)}. 663 664encode_integer_pos(0, L=[B|_Acc]) when B < 128 -> 665 L; 666encode_integer_pos(N, Acc) -> 667 encode_integer_pos((N bsr 8), [N band 16#ff| Acc]). 668 669encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 -> 670 L; 671encode_integer_neg(N, Acc) -> 672 encode_integer_neg(N bsr 8, [N band 16#ff|Acc]). 673 674%%=============================================================================== 675%% decode integer 676%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 677%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 678%%=============================================================================== 679 680 681decode_integer(Buffer, Range, Tags, OptOrMand) -> 682 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}), 683 decode_integer_notag(Buffer, Range, [], NewTags, OptOrMand). 684 685decode_integer(Buffer, Range, NamedNumberList, Tags, OptOrMand) -> 686 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}), 687 decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand). 688 689decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand) -> 690 {RestTags, {FormLen, Buffer0, Rb0}} = 691 check_tags_i(NewTags, Buffer, OptOrMand), 692% Result = {Val, Buffer2, RemovedBytes} = 693 case FormLen of 694 {?CONSTRUCTED,Len} -> 695 {Buffer00, RestBytes} = split_list(Buffer0,Len), 696 {Val01, Buffer01, Rb01} = 697 decode_integer_notag(Buffer00, Range, NamedNumberList, 698 RestTags, OptOrMand), 699 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 700 {Val01, Buffer02, Rb0+Rb01+Rb02}; 701 {_, Len} -> 702 Result = 703 decode_integer2(Len,Buffer0,Rb0+Len), 704 Result2 = check_integer_constraint(Result,Range), 705 resolve_named_value(Result2,NamedNumberList) 706 end. 707 708resolve_named_value(Result={Val,Buffer,RemBytes},NamedNumberList) -> 709 case NamedNumberList of 710 [] -> Result; 711 _ -> 712 NewVal = case lists:keysearch(Val, 2, NamedNumberList) of 713 {value,{NamedVal, _}} -> 714 NamedVal; 715 _ -> 716 Val 717 end, 718 {NewVal, Buffer, RemBytes} 719 end. 720 721check_integer_constraint(Result={Val, _Buffer,_},Range) -> 722 case Range of 723 [] -> % No length constraint 724 Result; 725 {Lb,Ub} when Val >= Lb, Ub >= Val -> % variable length constraint 726 Result; 727 Val -> % fixed value constraint 728 Result; 729 {_,_} -> 730 exit({error,{asn1,{integer_range,Range,Val}}}); 731 SingleValue when integer(SingleValue) -> 732 exit({error,{asn1,{integer_range,Range,Val}}}); 733 _ -> % some strange constraint that we don't support yet 734 Result 735 end. 736 737%%============================================================================ 738%% Enumerated value, ITU_T X.690 Chapter 8.4 739 740%% encode enumerated value 741%%============================================================================ 742encode_enumerated(Val, []) when integer(Val)-> 743 {EncVal,Len} = encode_integer(false,Val), 744 dotag_universal(?N_ENUMERATED,EncVal,Len); 745encode_enumerated(Val, DoTag) when integer(Val)-> 746 dotag(DoTag, ?N_ENUMERATED, encode_integer(false,Val)); 747encode_enumerated({Name,Val}, DoTag) when atom(Name) -> 748 encode_enumerated(Val, DoTag). 749 750%% The encode_enumerated functions below this line can be removed when the 751%% new code generation is stable. (the functions might have to be kept here 752%% a while longer for compatibility reasons) 753 754encode_enumerated(C, Val, {NamedNumberList,ExtList}, DoTag) when atom(Val) -> 755 case catch encode_enumerated(C, Val, NamedNumberList, DoTag) of 756 {'EXIT',_} -> encode_enumerated(C, Val, ExtList, DoTag); 757 Result -> Result 758 end; 759 760encode_enumerated(C, Val, NamedNumberList, DoTag) when atom(Val) -> 761 case lists:keysearch(Val, 1, NamedNumberList) of 762 {value, {_, NewVal}} when DoTag == []-> 763 {EncVal,Len} = encode_integer(C,NewVal), 764 dotag_universal(?N_ENUMERATED,EncVal,Len); 765 {value, {_, NewVal}} -> 766 dotag(DoTag, ?N_ENUMERATED, encode_integer(C, NewVal)); 767 _ -> 768 exit({error,{asn1, {enumerated_not_in_range, Val}}}) 769 end; 770 771encode_enumerated(C, {asn1_enum, Val}, {_,_}, DoTag) when integer(Val) -> 772 dotag(DoTag, ?N_ENUMERATED, encode_integer(C,Val)); 773 774encode_enumerated(C, {Name,Val}, NamedNumberList, DoTag) when atom(Name) -> 775 encode_enumerated(C, Val, NamedNumberList, DoTag); 776 777encode_enumerated(_, Val, _, _) -> 778 exit({error,{asn1, {enumerated_not_namednumber, Val}}}). 779 780 781 782%%============================================================================ 783%% decode enumerated value 784%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> 785%% {Value, RemainingBuffer, RemovedBytes} 786%%=========================================================================== 787decode_enumerated(Buffer, Range, NamedNumberList, Tags, OptOrMand) -> 788 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_ENUMERATED}), 789 decode_enumerated_notag(Buffer, Range, NamedNumberList, 790 NewTags, OptOrMand). 791 792decode_enumerated_notag(Buffer, Range, NNList = {NamedNumberList,ExtList}, Tags, OptOrMand) -> 793 {RestTags, {FormLen, Buffer0, Rb0}} = 794 check_tags_i(Tags, Buffer, OptOrMand), 795 796 case FormLen of 797 {?CONSTRUCTED,Len} -> 798 {Buffer00,RestBytes} = split_list(Buffer0,Len), 799 {Val01, Buffer01, Rb01} = 800 decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand), 801 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 802 {Val01, Buffer02, Rb0+Rb01+Rb02}; 803 {_,Len} -> 804 {Val01, Buffer01, Rb01} = 805 decode_integer2(Len, Buffer0, Rb0+Len), 806 case decode_enumerated1(Val01, NamedNumberList) of 807 {asn1_enum,Val01} -> 808 {decode_enumerated1(Val01,ExtList), Buffer01, Rb01}; 809 Result01 -> 810 {Result01, Buffer01, Rb01} 811 end 812 end; 813 814decode_enumerated_notag(Buffer, Range, NNList, Tags, OptOrMand) -> 815 {RestTags, {FormLen, Buffer0, Rb0}} = 816 check_tags_i(Tags, Buffer, OptOrMand), 817 818 case FormLen of 819 {?CONSTRUCTED,Len} -> 820 {Buffer00,RestBytes} = split_list(Buffer0,Len), 821 {Val01, Buffer01, Rb01} = 822 decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand), 823 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 824 {Val01, Buffer02, Rb0+Rb01+Rb02}; 825 {_,Len} -> 826 {Val01, Buffer02, Rb02} = 827 decode_integer2(Len, Buffer0, Rb0+Len), 828 case decode_enumerated1(Val01, NNList) of 829 {asn1_enum,_} -> 830 exit({error,{asn1, {illegal_enumerated, Val01}}}); 831 Result01 -> 832 {Result01, Buffer02, Rb02} 833 end 834 end. 835 836decode_enumerated1(Val, NamedNumberList) -> 837 %% it must be a named integer 838 case lists:keysearch(Val, 2, NamedNumberList) of 839 {value,{NamedVal, _}} -> 840 NamedVal; 841 _ -> 842 {asn1_enum,Val} 843 end. 844 845 846%%============================================================================ 847%% 848%% Real value, ITU_T X.690 Chapter 8.5 849%%============================================================================ 850%% 851%% encode real value 852%%============================================================================ 853 854%% only base 2 internally so far!! 855encode_real(0, DoTag) -> 856 dotag(DoTag, ?N_REAL, {[],0}); 857encode_real('PLUS-INFINITY', DoTag) -> 858 dotag(DoTag, ?N_REAL, {[64],1}); 859encode_real('MINUS-INFINITY', DoTag) -> 860 dotag(DoTag, ?N_REAL, {[65],1}); 861encode_real(Val, DoTag) when tuple(Val)-> 862 dotag(DoTag, ?N_REAL, encode_real(Val)). 863 864%%%%%%%%%%%%%% 865%% not optimal efficient.. 866%% only base 2 of Mantissa encoding! 867%% only base 2 of ExpBase encoding! 868encode_real({Man, Base, Exp}) -> 869%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]), 870 871 OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, [])); 872 true -> list_to_binary(encode_integer_neg(Exp, [])) 873 end, 874%% ok = io:format("OctExp: ~w~n",[OctExp]), 875 SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval 876 true -> 1 877 end, 878%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]), 879 InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far! 880 true -> 881 exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}}) 882 end, 883 SFactor = 0, % bit 4,3: no scaling since only base 2 884 OctExpLen = size(OctExp), 885 if OctExpLen > 255 -> 886 exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}}); 887 true -> true %% make real assert later.. 888 end, 889 {LenCode, EOctets} = case OctExpLen of % bit 2,1 890 1 -> {0, OctExp}; 891 2 -> {1, OctExp}; 892 3 -> {2, OctExp}; 893 _ -> {3, <<OctExpLen, OctExp/binary>>} 894 end, 895 FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>, 896 OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man)); 897 true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign 898 end, 899 %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]), 900 Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>, 901 {Bin, size(Bin)}. 902 903 904%encode_real({Man, Base, Exp}) -> 905%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]), 906 907% OctExp = if Exp >= 0 -> encode_integer_pos(Exp, []); 908% true -> encode_integer_neg(Exp, []) 909% end, 910%% ok = io:format("OctExp: ~w~n",[OctExp]), 911% SignBitMask = if Man > 0 -> 2#00000000; % bit 7 is pos or neg, no Zeroval 912% true -> 2#01000000 913% end, 914%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]), 915% InternalBaseMask = if Base =:= 2 -> 2#00000000; % bit 6,5: only base 2 this far! 916% true -> 917% exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}}) 918% end, 919% ScalingFactorMask =2#00000000, % bit 4,3: no scaling since only base 2 920% OctExpLen = length(OctExp), 921% if OctExpLen > 255 -> 922% exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}}); 923% true -> true %% make real assert later.. 924% end, 925% {LenMask, EOctets} = case OctExpLen of % bit 2,1 926% 1 -> {0, OctExp}; 927% 2 -> {1, OctExp}; 928% 3 -> {2, OctExp}; 929% _ -> {3, [OctExpLen, OctExp]} 930% end, 931% FirstOctet = (SignBitMask bor InternalBaseMask bor 932% ScalingFactorMask bor LenMask bor 933% 2#10000000), % bit set for binary mantissa encoding! 934% OctMantissa = if Man > 0 -> minimum_octets(Man); 935% true -> minimum_octets(-(Man)) % signbit keeps track of sign 936% end, 937%% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]), 938% {[FirstOctet, EOctets, OctMantissa], 939% length(OctMantissa) + 940% (if OctExpLen > 3 -> 941% OctExpLen + 2; 942% true -> 943% OctExpLen + 1 944% end) 945% }. 946 947 948%%============================================================================ 949%% decode real value 950%% 951%% decode_real([OctetBufferList], tuple|value, tag|notag) -> 952%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0, 953%% RestBuff} 954%% 955%% only for base 2 decoding sofar!! 956%%============================================================================ 957 958decode_real(Buffer, Form, Tags, OptOrMand) -> 959 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_REAL}), 960 decode_real_notag(Buffer, Form, NewTags, OptOrMand). 961 962decode_real_notag(Buffer, Form, Tags, OptOrMand) -> 963 {RestTags, {FormLen, Buffer0, Rb0}} = 964 check_tags_i(Tags, Buffer, OptOrMand), 965 966 case FormLen of 967 {?CONSTRUCTED,Len} -> 968 {Buffer00,RestBytes} = split_list(Buffer0,Len), 969 {Val01, Buffer01, Rb01} = 970 decode_real_notag(Buffer00, Form, RestTags, OptOrMand), 971 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 972 {Val01, Buffer02, Rb0+Rb01+Rb02}; 973 {_,Len} -> 974 decode_real2(Buffer0, Form, Len, Rb0) 975 end. 976 977decode_real2(Buffer0, Form, Len, RemBytes1) -> 978 <<First, Buffer2/binary>> = Buffer0, 979 if 980 First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2}; 981 First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2}; 982 First =:= 2#00000000 -> {0, Buffer2}; 983 true -> 984 %% have some check here to verify only supported bases (2) 985 <<_B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>, 986 Sign = B6, 987 Base = 988 case B5_4 of 989 0 -> 2; % base 2, only one so far 990 _ -> exit({error,{asn1, {non_supported_base, First}}}) 991 end, 992% ScalingFactor = 993 case B3_2 of 994 0 -> 0; % no scaling so far 995 _ -> exit({error,{asn1, {non_supported_scaling, First}}}) 996 end, 997 % ok = io:format("Buffer2: ~w~n",[Buffer2]), 998 {FirstLen, {Exp, Buffer3}, RemBytes2} = 999 case B1_0 of 1000 0 -> {2, decode_integer2(1, Buffer2, RemBytes1), RemBytes1+1}; 1001 1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2}; 1002 2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3}; 1003 3 -> 1004 <<ExpLen1,RestBuffer/binary>> = Buffer2, 1005 { ExpLen1 + 2, 1006 decode_integer2(ExpLen1, RestBuffer, RemBytes1), 1007 RemBytes1+ExpLen1} 1008 end, 1009 % io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n", 1010 % [FirstLen, Exp, Buffer3]), 1011 Length = Len - FirstLen, 1012 <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3, 1013 {{Mantissa, Buffer4}, RemBytes3} = 1014 if Sign =:= 0 -> 1015 % io:format("sign plus~n"), 1016 {{LongInt, RestBuff}, 1 + Length}; 1017 true -> 1018 % io:format("sign minus~n"), 1019 {{-LongInt, RestBuff}, 1 + Length} 1020 end, 1021 % io:format("Form: ~w~n",[Form]), 1022 case Form of 1023 tuple -> 1024 {Val,Buf,_RemB} = Exp, 1025 {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3}; 1026 _value -> 1027 comming 1028 end 1029 end. 1030 1031 1032%%============================================================================ 1033%% Bitstring value, ITU_T X.690 Chapter 8.6 1034%% 1035%% encode bitstring value 1036%% 1037%% bitstring NamedBitList 1038%% Val can be of: 1039%% - [identifiers] where only named identifiers are set to one, 1040%% the Constraint must then have some information of the 1041%% bitlength. 1042%% - [list of ones and zeroes] all bits 1043%% - integer value representing the bitlist 1044%% C is constrint Len, only valid when identifiers 1045%%============================================================================ 1046 1047encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,DoTag) when integer(Unused), binary(BinBits) -> 1048 encode_bin_bit_string(C,Bin,NamedBitList,DoTag); 1049encode_bit_string(C, [FirstVal | RestVal], NamedBitList, DoTag) when atom(FirstVal) -> 1050 encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag); 1051 1052encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, DoTag) -> 1053 encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, DoTag); 1054 1055encode_bit_string(C, [FirstVal| RestVal], NamedBitList, DoTag) when integer(FirstVal) -> 1056 encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, DoTag); 1057 1058encode_bit_string(_, 0, _, []) -> 1059 {[?N_BIT_STRING,1,0],3}; 1060 1061encode_bit_string(_, 0, _, DoTag) -> 1062 dotag(DoTag, ?N_BIT_STRING, {<<0>>,1}); 1063 1064encode_bit_string(_, [], _, []) -> 1065 {[?N_BIT_STRING,1,0],3}; 1066 1067encode_bit_string(_, [], _, DoTag) -> 1068 dotag(DoTag, ?N_BIT_STRING, {<<0>>,1}); 1069 1070encode_bit_string(C, IntegerVal, NamedBitList, DoTag) when integer(IntegerVal) -> 1071 BitListVal = int_to_bitlist(IntegerVal), 1072 encode_bit_string_bits(C, BitListVal, NamedBitList, DoTag); 1073 1074encode_bit_string(C, {Name,BitList}, NamedBitList, DoTag) when atom(Name) -> 1075 encode_bit_string(C, BitList, NamedBitList, DoTag). 1076 1077 1078 1079int_to_bitlist(0) -> 1080 []; 1081int_to_bitlist(Int) when integer(Int), Int >= 0 -> 1082 [Int band 1 | int_to_bitlist(Int bsr 1)]. 1083 1084 1085%%================================================================= 1086%% Encode BIT STRING of the form {Unused,BinBits}. 1087%% Unused is the number of unused bits in the last byte in BinBits 1088%% and BinBits is a binary representing the BIT STRING. 1089%%================================================================= 1090encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,DoTag)-> 1091 case get_constraint(C,'SizeConstraint') of 1092 no -> 1093 remove_unused_then_dotag(DoTag,?N_BIT_STRING,Unused,BinBits); 1094 {_Min,Max} -> 1095 BBLen = (size(BinBits)*8)-Unused, 1096 if 1097 BBLen > Max -> 1098 exit({error,{asn1, 1099 {bitstring_length, 1100 {{was,BBLen},{maximum,Max}}}}}); 1101 true -> 1102 remove_unused_then_dotag(DoTag,?N_BIT_STRING, 1103 Unused,BinBits) 1104 end; 1105 Size -> 1106 case ((size(BinBits)*8)-Unused) of 1107 BBSize when BBSize =< Size -> 1108 remove_unused_then_dotag(DoTag,?N_BIT_STRING, 1109 Unused,BinBits); 1110 BBSize -> 1111 exit({error,{asn1, 1112 {bitstring_length, 1113 {{was,BBSize},{should_be,Size}}}}}) 1114 end 1115 end. 1116 1117remove_unused_then_dotag(DoTag,StringType,Unused,BinBits) -> 1118 case Unused of 1119 0 when (size(BinBits) == 0),DoTag==[] -> 1120 %% time optimization of next case 1121 {[StringType,1,0],3}; 1122 0 when (size(BinBits) == 0) -> 1123 dotag(DoTag,StringType,{<<0>>,1}); 1124 0 when DoTag==[]-> % time optimization of next case 1125 dotag_universal(StringType,[Unused|BinBits],size(BinBits)+1); 1126% {LenEnc,Len} = encode_legth(size(BinBits)+1), 1127% {[StringType,LenEnc,[Unused|BinBits]],size(BinBits)+1+Len+1}; 1128 0 -> 1129 dotag(DoTag,StringType,<<Unused,BinBits/binary>>); 1130 Num when DoTag == [] -> % time optimization of next case 1131 N = (size(BinBits)-1), 1132 <<BBits:N/binary,LastByte>> = BinBits, 1133 dotag_universal(StringType, 1134 [Unused,BBits,(LastByte bsr Num) bsl Num], 1135 size(BinBits)+1); 1136% {LenEnc,Len} = encode_legth(size(BinBits)+1), 1137% {[StringType,LenEnc,[Unused,BBits,(LastByte bsr Num) bsl Num], 1138% 1+Len+size(BinBits)+1}; 1139 Num -> 1140 N = (size(BinBits)-1), 1141 <<BBits:N/binary,LastByte>> = BinBits, 1142 dotag(DoTag,StringType,{[Unused,binary_to_list(BBits) ++ 1143 [(LastByte bsr Num) bsl Num]], 1144 1+size(BinBits)}) 1145 end. 1146 1147 1148%%================================================================= 1149%% Encode named bits 1150%%================================================================= 1151 1152encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag) -> 1153 {Len,Unused,OctetList} = 1154 case get_constraint(C,'SizeConstraint') of 1155 no -> 1156 ToSetPos = get_all_bitposes([FirstVal | RestVal], 1157 NamedBitList, []), 1158 BitList = make_and_set_list(lists:max(ToSetPos)+1, 1159 ToSetPos, 0), 1160 encode_bitstring(BitList); 1161 {_Min,Max} -> 1162 ToSetPos = get_all_bitposes([FirstVal | RestVal], 1163 NamedBitList, []), 1164 BitList = make_and_set_list(Max, ToSetPos, 0), 1165 encode_bitstring(BitList); 1166 Size -> 1167 ToSetPos = get_all_bitposes([FirstVal | RestVal], 1168 NamedBitList, []), 1169 BitList = make_and_set_list(Size, ToSetPos, 0), 1170 encode_bitstring(BitList) 1171 end, 1172 case DoTag of 1173 [] -> 1174 dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1); 1175% {EncLen,LenLen} = encode_length(Len+1), 1176% {[?N_BIT_STRING,EncLen,Unused,OctetList],1+LenLen+Len+1}; 1177 _ -> 1178 dotag(DoTag, ?N_BIT_STRING, {[Unused|OctetList],Len+1}) 1179 end. 1180 1181 1182%%---------------------------------------- 1183%% get_all_bitposes([list of named bits to set], named_bit_db, []) -> 1184%% [sorted_list_of_bitpositions_to_set] 1185%%---------------------------------------- 1186 1187get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) -> 1188 get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]); 1189get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) -> 1190 case lists:keysearch(Val, 1, NamedBitList) of 1191 {value, {_ValName, ValPos}} -> 1192 get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]); 1193 _ -> 1194 exit({error,{asn1, {bitstring_namedbit, Val}}}) 1195 end; 1196get_all_bitposes([], _NamedBitList, Ack) -> 1197 lists:sort(Ack). 1198 1199 1200%%---------------------------------------- 1201%% make_and_set_list(Len of list to return, [list of positions to set to 1])-> 1202%% returns list of Len length, with all in SetPos set. 1203%% in positioning in list the first element is 0, the second 1 etc.., but 1204%% Len will make a list of length Len, not Len + 1. 1205%% BitList = make_and_set_list(C, ToSetPos, 0), 1206%%---------------------------------------- 1207 1208make_and_set_list(0, [], _) -> []; 1209make_and_set_list(0, _, _) -> 1210 exit({error,{asn1,bitstring_sizeconstraint}}); 1211make_and_set_list(Len, [XPos|SetPos], XPos) -> 1212 [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)]; 1213make_and_set_list(Len, [Pos|SetPos], XPos) -> 1214 [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)]; 1215make_and_set_list(Len, [], XPos) -> 1216 [0 | make_and_set_list(Len - 1, [], XPos + 1)]. 1217 1218 1219 1220 1221 1222 1223%%================================================================= 1224%% Encode bit string for lists of ones and zeroes 1225%%================================================================= 1226encode_bit_string_bits(C, BitListVal, _NamedBitList, DoTag) when list(BitListVal) -> 1227 {Len,Unused,OctetList} = 1228 case get_constraint(C,'SizeConstraint') of 1229 no -> 1230 encode_bitstring(BitListVal); 1231 Constr={Min,Max} when integer(Min),integer(Max) -> 1232 encode_constr_bit_str_bits(Constr,BitListVal,DoTag); 1233 {Constr={_,_},[]} -> 1234 %% constraint with extension mark 1235 encode_constr_bit_str_bits(Constr,BitListVal,DoTag); 1236 Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}} 1237 %% constraint with extension mark 1238 encode_constr_bit_str_bits(Constr,BitListVal,DoTag); 1239 Size -> 1240 case length(BitListVal) of 1241 BitSize when BitSize == Size -> 1242 encode_bitstring(BitListVal); 1243 BitSize when BitSize < Size -> 1244 PaddedList = 1245 pad_bit_list(Size-BitSize,BitListVal), 1246 encode_bitstring(PaddedList); 1247 BitSize -> 1248 exit({error, 1249 {asn1, 1250 {bitstring_length, 1251 {{was,BitSize}, 1252 {should_be,Size}}}}}) 1253 end 1254 end, 1255 %%add unused byte to the Len 1256 case DoTag of 1257 [] -> 1258 dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1); 1259% {EncLen,LenLen}=encode_length(Len+1), 1260% {[?N_BIT_STRING,EncLen,Unused|OctetList],1+LenLen+Len+1}; 1261 _ -> 1262 dotag(DoTag, ?N_BIT_STRING, 1263 {[Unused | OctetList],Len+1}) 1264 end. 1265 1266 1267encode_constr_bit_str_bits({_Min,Max},BitListVal,_DoTag) -> 1268 BitLen = length(BitListVal), 1269 if 1270 BitLen > Max -> 1271 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1272 {maximum,Max}}}}}); 1273 true -> 1274 encode_bitstring(BitListVal) 1275 end; 1276encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,_DoTag) -> 1277 BitLen = length(BitListVal), 1278 case BitLen of 1279 Len when Len > Max2 -> 1280 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1281 {maximum,Max2}}}}}); 1282 Len when Len > Max1, Len < Min2 -> 1283 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1284 {not_allowed_interval, 1285 Max1,Min2}}}}}); 1286 _ -> 1287 encode_bitstring(BitListVal) 1288 end. 1289 1290%% returns a list of length Size + length(BitListVal), with BitListVal 1291%% as the most significant elements followed by padded zero elements 1292pad_bit_list(Size,BitListVal) -> 1293 Tail = lists:duplicate(Size,0), 1294 lists:append(BitListVal,Tail). 1295 1296%%================================================================= 1297%% Do the actual encoding 1298%% ([bitlist]) -> {ListLen, UnusedBits, OctetList} 1299%%================================================================= 1300 1301encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) -> 1302 Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor 1303 (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1, 1304 encode_bitstring(Rest, [Val], 1); 1305encode_bitstring(Val) -> 1306 {Unused, Octet} = unused_bitlist(Val, 7, 0), 1307 {1, Unused, [Octet]}. 1308 1309encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) -> 1310 Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor 1311 (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1, 1312 encode_bitstring(Rest, [Ack | [Val]], Len + 1); 1313%%even multiple of 8 bits.. 1314encode_bitstring([], Ack, Len) -> 1315 {Len, 0, Ack}; 1316%% unused bits in last octet 1317encode_bitstring(Rest, Ack, Len) -> 1318% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]), 1319 {Unused, Val} = unused_bitlist(Rest, 7, 0), 1320 {Len + 1, Unused, [Ack | [Val]]}. 1321 1322%%%%%%%%%%%%%%%%%% 1323%% unused_bitlist([list of ones and zeros <= 7], 7, []) -> 1324%% {Unused bits, Last octet with bits moved to right} 1325unused_bitlist([], Trail, Ack) -> 1326 {Trail + 1, Ack}; 1327unused_bitlist([Bit | Rest], Trail, Ack) -> 1328%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]), 1329 unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack). 1330 1331 1332%%============================================================================ 1333%% decode bitstring value 1334%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 1335%%============================================================================ 1336 1337decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) -> 1338% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}), 1339 decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn, 1340 NamedNumberList, OptOrMand,bin). 1341 1342decode_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) -> 1343% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}), 1344 decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn, 1345 NamedNumberList, OptOrMand,old). 1346 1347 1348decode_bit_string2(1,<<0 ,Buffer/binary>>,_NamedNumberList,RemovedBytes,BinOrOld) -> 1349 case BinOrOld of 1350 bin -> 1351 {{0,<<>>},Buffer,RemovedBytes}; 1352 _ -> 1353 {[], Buffer, RemovedBytes} 1354 end; 1355decode_bit_string2(Len,<<Unused,Buffer/binary>>,NamedNumberList, 1356 RemovedBytes,BinOrOld) -> 1357 L = Len - 1, 1358 <<Bits:L/binary,BufferTail/binary>> = Buffer, 1359 case NamedNumberList of 1360 [] -> 1361 case BinOrOld of 1362 bin -> 1363 {{Unused,Bits},BufferTail,RemovedBytes}; 1364 _ -> 1365 BitString = decode_bitstring2(L, Unused, Buffer), 1366 {BitString,BufferTail, RemovedBytes} 1367 end; 1368 _ -> 1369 BitString = decode_bitstring2(L, Unused, Buffer), 1370 {decode_bitstring_NNL(BitString,NamedNumberList), 1371 BufferTail, 1372 RemovedBytes} 1373 end. 1374 1375%%---------------------------------------- 1376%% Decode the in buffer to bits 1377%%---------------------------------------- 1378decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) -> 1379 lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused); 1380decode_bitstring2(Len, Unused, 1381 <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) -> 1382 [B7, B6, B5, B4, B3, B2, B1, B0 | 1383 decode_bitstring2(Len - 1, Unused, Buffer)]. 1384 1385%%decode_bitstring2(1, Unused, Buffer) -> 1386%% make_bits_of_int(hd(Buffer), 128, 8-Unused); 1387%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) -> 1388%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8), 1389%% [B7, B6, B5, B4, B3, B2, B1, B0 | 1390%% decode_bitstring2(Len - 1, Unused, Buffer)]. 1391 1392 1393%%make_bits_of_int(_, _, 0) -> 1394%% []; 1395%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 -> 1396%% X = case MaskVal band BitVal of 1397%% 0 -> 0 ; 1398%% _ -> 1 1399%% end, 1400%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)]. 1401 1402 1403 1404%%---------------------------------------- 1405%% Decode the bitlist to names 1406%%---------------------------------------- 1407 1408 1409decode_bitstring_NNL(BitList,NamedNumberList) -> 1410 decode_bitstring_NNL(BitList,NamedNumberList,0,[]). 1411 1412 1413decode_bitstring_NNL([],_,_No,Result) -> 1414 lists:reverse(Result); 1415 1416decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) -> 1417 if 1418 B == 0 -> 1419 decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result); 1420 true -> 1421 decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result]) 1422 end; 1423decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) -> 1424 decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]); 1425decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) -> 1426 decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result). 1427 1428 1429%%============================================================================ 1430%% Octet string, ITU_T X.690 Chapter 8.7 1431%% 1432%% encode octet string 1433%% The OctetList must be a flat list of integers in the range 0..255 1434%% the function does not check this because it takes to much time 1435%%============================================================================ 1436encode_octet_string(_C, OctetList, []) when binary(OctetList) -> 1437 dotag_universal(?N_OCTET_STRING,OctetList,size(OctetList)); 1438encode_octet_string(_C, OctetList, DoTag) when binary(OctetList) -> 1439 dotag(DoTag, ?N_OCTET_STRING, {OctetList,size(OctetList)}); 1440encode_octet_string(_C, OctetList, DoTag) when list(OctetList) -> 1441 case length(OctetList) of 1442 Len when DoTag == [] -> 1443 dotag_universal(?N_OCTET_STRING,OctetList,Len); 1444 Len -> 1445 dotag(DoTag, ?N_OCTET_STRING, {OctetList,Len}) 1446 end; 1447% encode_octet_string(C, OctetList, DoTag) when list(OctetList) -> 1448% dotag(DoTag, ?N_OCTET_STRING, {OctetList,length(OctetList)}); 1449encode_octet_string(C, {Name,OctetList}, DoTag) when atom(Name) -> 1450 encode_octet_string(C, OctetList, DoTag). 1451 1452 1453%%============================================================================ 1454%% decode octet string 1455%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1456%% 1457%% Octet string is decoded as a restricted string 1458%%============================================================================ 1459decode_octet_string(Buffer, Range, Tags, TotalLen, OptOrMand) -> 1460% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}), 1461 decode_restricted_string(Buffer, Range, ?N_OCTET_STRING, 1462 Tags, TotalLen, [], OptOrMand,old). 1463 1464%%============================================================================ 1465%% Null value, ITU_T X.690 Chapter 8.8 1466%% 1467%% encode NULL value 1468%%============================================================================ 1469 1470encode_null(_, []) -> 1471 {[?N_NULL,0],2}; 1472encode_null(_, DoTag) -> 1473 dotag(DoTag, ?N_NULL, {[],0}). 1474 1475%%============================================================================ 1476%% decode NULL value 1477%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes} 1478%%============================================================================ 1479decode_null(Buffer, Tags, OptOrMand) -> 1480 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_NULL}), 1481 decode_null_notag(Buffer, NewTags, OptOrMand). 1482 1483decode_null_notag(Buffer, Tags, OptOrMand) -> 1484 {RestTags, {FormLen, Buffer0, Rb0}} = 1485 check_tags_i(Tags, Buffer, OptOrMand), 1486 1487 case FormLen of 1488 {?CONSTRUCTED,Len} -> 1489 {_Buffer00,RestBytes} = split_list(Buffer0,Len), 1490 {Val01, Buffer01, Rb01} = decode_null_notag(Buffer0, RestTags, 1491 OptOrMand), 1492 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 1493 {Val01, Buffer02, Rb0+Rb01+Rb02}; 1494 {_,0} -> 1495 {'NULL', Buffer0, Rb0}; 1496 {_,Len} -> 1497 exit({error,{asn1,{invalid_length,'NULL',Len}}}) 1498 end. 1499 1500 1501%%============================================================================ 1502%% Object identifier, ITU_T X.690 Chapter 8.19 1503%% 1504%% encode Object Identifier value 1505%%============================================================================ 1506 1507encode_object_identifier({Name,Val}, DoTag) when atom(Name) -> 1508 encode_object_identifier(Val, DoTag); 1509encode_object_identifier(Val, []) -> 1510 {EncVal,Len} = e_object_identifier(Val), 1511 dotag_universal(?N_OBJECT_IDENTIFIER,EncVal,Len); 1512encode_object_identifier(Val, DoTag) -> 1513 dotag(DoTag, ?N_OBJECT_IDENTIFIER, e_object_identifier(Val)). 1514 1515e_object_identifier({'OBJECT IDENTIFIER', V}) -> 1516 e_object_identifier(V); 1517e_object_identifier({Cname, V}) when atom(Cname), tuple(V) -> 1518 e_object_identifier(tuple_to_list(V)); 1519e_object_identifier({Cname, V}) when atom(Cname), list(V) -> 1520 e_object_identifier(V); 1521e_object_identifier(V) when tuple(V) -> 1522 e_object_identifier(tuple_to_list(V)); 1523 1524%%%%%%%%%%%%%%% 1525%% e_object_identifier([List of Obect Identifiers]) -> 1526%% {[Encoded Octetlist of ObjIds], IntLength} 1527%% 1528e_object_identifier([E1, E2 | Tail]) -> 1529 Head = 40*E1 + E2, % wow! 1530 {H,Lh} = mk_object_val(Head), 1531 {R,Lr} = enc_obj_id_tail(Tail, [], 0), 1532 {[H|R], Lh+Lr}. 1533 1534enc_obj_id_tail([], Ack, Len) -> 1535 {lists:reverse(Ack), Len}; 1536enc_obj_id_tail([H|T], Ack, Len) -> 1537 {B, L} = mk_object_val(H), 1538 enc_obj_id_tail(T, [B|Ack], Len+L). 1539 1540%% e_object_identifier([List of Obect Identifiers]) -> 1541%% {[Encoded Octetlist of ObjIds], IntLength} 1542%% 1543%%e_object_identifier([E1, E2 | Tail]) -> 1544%% Head = 40*E1 + E2, % wow! 1545%% F = fun(Val, AckLen) -> 1546%% {L, Ack} = mk_object_val(Val), 1547%% {L, Ack + AckLen} 1548%% end, 1549%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]). 1550 1551%%%%%%%%%%% 1552%% mk_object_val(Value) -> {OctetList, Len} 1553%% returns a Val as a list of octets, the 8 bit is allways set to one except 1554%% for the last octet, where its 0 1555%% 1556 1557 1558mk_object_val(Val) when Val =< 127 -> 1559 {[255 band Val], 1}; 1560mk_object_val(Val) -> 1561 mk_object_val(Val bsr 7, [Val band 127], 1). 1562mk_object_val(0, Ack, Len) -> 1563 {Ack, Len}; 1564mk_object_val(Val, Ack, Len) -> 1565 mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1). 1566 1567 1568 1569%%============================================================================ 1570%% decode Object Identifier value 1571%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes} 1572%%============================================================================ 1573 1574decode_object_identifier(Buffer, Tags, OptOrMand) -> 1575 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL, 1576 number=?N_OBJECT_IDENTIFIER}), 1577 decode_object_identifier_notag(Buffer, NewTags, OptOrMand). 1578 1579decode_object_identifier_notag(Buffer, Tags, OptOrMand) -> 1580 {RestTags, {FormLen, Buffer0, Rb0}} = 1581 check_tags_i(Tags, Buffer, OptOrMand), 1582 1583 case FormLen of 1584 {?CONSTRUCTED,Len} -> 1585 {Buffer00,RestBytes} = split_list(Buffer0,Len), 1586 {Val01, Buffer01, Rb01} = 1587 decode_object_identifier_notag(Buffer00, 1588 RestTags, OptOrMand), 1589 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 1590 {Val01, Buffer02, Rb0+Rb01+Rb02}; 1591 {_,Len} -> 1592 {[AddedObjVal|ObjVals],Buffer01} = 1593 dec_subidentifiers(Buffer0,0,[],Len), 1594 {Val1, Val2} = if 1595 AddedObjVal < 40 -> 1596 {0, AddedObjVal}; 1597 AddedObjVal < 80 -> 1598 {1, AddedObjVal - 40}; 1599 true -> 1600 {2, AddedObjVal - 80} 1601 end, 1602 {list_to_tuple([Val1, Val2 | ObjVals]), Buffer01, 1603 Rb0+Len} 1604 end. 1605 1606dec_subidentifiers(Buffer,_Av,Al,0) -> 1607 {lists:reverse(Al),Buffer}; 1608dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al,Len) -> 1609 dec_subidentifiers(T,(Av bsl 7) + H,Al,Len-1); 1610dec_subidentifiers(<<H,T/binary>>,Av,Al,Len) -> 1611 dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1). 1612 1613 1614%%dec_subidentifiers(Buffer,Av,Al,0) -> 1615%% {lists:reverse(Al),Buffer}; 1616%%dec_subidentifiers([H|T],Av,Al,Len) when H >=16#80 -> 1617%% dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al,Len-1); 1618%%dec_subidentifiers([H|T],Av,Al,Len) -> 1619%% dec_subidentifiers(T,0,[(Av bsl 7) + H |Al],Len-1). 1620 1621 1622%%============================================================================ 1623%% Restricted character string types, ITU_T X.690 Chapter 8.20 1624%% 1625%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings 1626%%============================================================================ 1627encode_restricted_string(_C, OctetList, StringType, []) 1628 when binary(OctetList) -> 1629 dotag_universal(StringType,OctetList,size(OctetList)); 1630encode_restricted_string(_C, OctetList, StringType, DoTag) 1631 when binary(OctetList) -> 1632 dotag(DoTag, StringType, {OctetList, size(OctetList)}); 1633encode_restricted_string(_C, OctetList, StringType, []) 1634 when list(OctetList) -> 1635 dotag_universal(StringType,OctetList,length(OctetList)); 1636encode_restricted_string(_C, OctetList, StringType, DoTag) 1637 when list(OctetList) -> 1638 dotag(DoTag, StringType, {OctetList, length(OctetList)}); 1639encode_restricted_string(C,{Name,OctetL},StringType,DoTag) when atom(Name)-> 1640 encode_restricted_string(C, OctetL, StringType, DoTag). 1641 1642%%============================================================================ 1643%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings 1644%% (Buffer, Range, StringType, HasTag, TotalLen) -> 1645%% {String, Remain, RemovedBytes} 1646%%============================================================================ 1647 1648decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, OptOrMand) -> 1649 {Val,Buffer2,Rb} = 1650 decode_restricted_string_tag(Buffer, Range, StringType, Tags, 1651 LenIn, [], OptOrMand,old), 1652 {check_and_convert_restricted_string(Val,StringType,Range,[],old), 1653 Buffer2,Rb}. 1654 1655 1656decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, NNList, OptOrMand, BinOrOld ) -> 1657 {Val,Buffer2,Rb} = 1658 decode_restricted_string_tag(Buffer, Range, StringType, Tags, 1659 LenIn, NNList, OptOrMand, BinOrOld), 1660 {check_and_convert_restricted_string(Val,StringType,Range,NNList,BinOrOld), 1661 Buffer2,Rb}. 1662 1663decode_restricted_string_tag(Buffer, Range, StringType, TagsIn, LenIn, NNList, OptOrMand, BinOrOld ) -> 1664 NewTags = new_tags(TagsIn, #tag{class=?UNIVERSAL,number=StringType}), 1665 decode_restricted_string_notag(Buffer, Range, StringType, NewTags, 1666 LenIn, NNList, OptOrMand, BinOrOld). 1667 1668 1669 1670 1671check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) -> 1672 {StrLen,NewVal} = case StringType of 1673 ?N_BIT_STRING when NamedNumberList /= [] -> 1674 {no_check,Val}; 1675 ?N_BIT_STRING when list(Val) -> 1676 {length(Val),Val}; 1677 ?N_BIT_STRING when tuple(Val) -> 1678 {(size(element(2,Val))*8) - element(1,Val),Val}; 1679 _ when binary(Val) -> 1680 {size(Val),binary_to_list(Val)}; 1681 _ when list(Val) -> 1682 {length(Val), Val} 1683 end, 1684 case Range of 1685 _ when StrLen == no_check -> 1686 NewVal; 1687 [] -> % No length constraint 1688 NewVal; 1689 {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint 1690 NewVal; 1691 {{Lb,_Ub},[]} when StrLen >= Lb -> 1692 NewVal; 1693 {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1; 1694 StrLen =< Ub2, StrLen >= Lb2 -> 1695 NewVal; 1696 StrLen -> % fixed length constraint 1697 NewVal; 1698 {_,_} -> 1699 exit({error,{asn1,{length,Range,Val}}}); 1700 _Len when integer(_Len) -> 1701 exit({error,{asn1,{length,Range,Val}}}); 1702 _ -> % some strange constraint that we don't support yet 1703 NewVal 1704 end. 1705 1706 1707%%============================================================================= 1708%% Common routines for several string types including bit string 1709%% handles indefinite length 1710%%============================================================================= 1711 1712 1713decode_restricted_string_notag(Buffer, _Range, StringType, TagsIn, 1714 _, NamedNumberList, OptOrMand,BinOrOld) -> 1715 %%----------------------------------------------------------- 1716 %% Get inner (the implicit tag or no tag) and 1717 %% outer (the explicit tag) lengths. 1718 %%----------------------------------------------------------- 1719 {RestTags, {FormLength={_,_Len01}, Buffer0, Rb0}} = 1720 check_tags_i(TagsIn, Buffer, OptOrMand), 1721 1722 case FormLength of 1723 {?CONSTRUCTED,Len} -> 1724 {Buffer00, RestBytes} = split_list(Buffer0,Len), 1725 {Val01, Buffer01, Rb01} = 1726 decode_restricted_parts(Buffer00, RestBytes, [], StringType, 1727 RestTags, 1728 Len, NamedNumberList, 1729 OptOrMand, 1730 BinOrOld, 0, []), 1731 {Val01, Buffer01, Rb0+Rb01}; 1732 {_, Len} -> 1733 {Val01, Buffer01, Rb01} = 1734 decode_restricted(Buffer0, Len, StringType, 1735 NamedNumberList, BinOrOld), 1736 {Val01, Buffer01, Rb0+Rb01} 1737 end. 1738 1739 1740decode_restricted_parts(Buffer, RestBytes, [], StringType, RestTags, Len, NNList, 1741 OptOrMand, BinOrOld, AccRb, AccVal) -> 1742 DecodeFun = case RestTags of 1743 [] -> fun decode_restricted_string_tag/8; 1744 _ -> fun decode_restricted_string_notag/8 1745 end, 1746 {Val, Buffer1, Rb} = 1747 DecodeFun(Buffer, [], StringType, RestTags, 1748 no_length, NNList, 1749 OptOrMand, BinOrOld), 1750 {Buffer2,More} = 1751 case Buffer1 of 1752 <<0,0,Buffer10/binary>> when Len == indefinite -> 1753 {Buffer10,false}; 1754 <<>> -> 1755 {RestBytes,false}; 1756 _ -> 1757 {Buffer1,true} 1758 end, 1759 {NewVal, NewRb} = 1760 case StringType of 1761 ?N_BIT_STRING when BinOrOld == bin -> 1762 {concat_bit_binaries(AccVal, Val), AccRb+Rb}; 1763 _ when binary(Val),binary(AccVal) -> 1764 {<<AccVal/binary,Val/binary>>,AccRb+Rb}; 1765 _ when binary(Val), AccVal==[] -> 1766 {Val,AccRb+Rb}; 1767 _ -> 1768 {AccVal++Val, AccRb+Rb} 1769 end, 1770 case More of 1771 false -> 1772 {NewVal, Buffer2, NewRb}; 1773 true -> 1774 decode_restricted_parts(Buffer2, RestBytes, [], StringType, RestTags, Len, NNList, 1775 OptOrMand, BinOrOld, NewRb, NewVal) 1776 end. 1777 1778 1779 1780decode_restricted(Buffer, InnerLen, StringType, NamedNumberList,BinOrOld) -> 1781 1782 case StringType of 1783 ?N_BIT_STRING -> 1784 decode_bit_string2(InnerLen,Buffer,NamedNumberList,InnerLen,BinOrOld); 1785 1786 ?N_UniversalString -> 1787 <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary 1788 UniString = mk_universal_string(binary_to_list(PreBuff)), 1789 {UniString,RestBuff,InnerLen}; 1790 ?N_BMPString -> 1791 <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary 1792 BMP = mk_BMP_string(binary_to_list(PreBuff)), 1793 {BMP,RestBuff,InnerLen}; 1794 _ -> 1795 <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary 1796 {PreBuff, RestBuff, InnerLen} 1797 end. 1798 1799 1800 1801%%============================================================================ 1802%% encode Universal string 1803%%============================================================================ 1804 1805encode_universal_string(C, {Name, Universal}, DoTag) when atom(Name) -> 1806 encode_universal_string(C, Universal, DoTag); 1807encode_universal_string(_C, Universal, []) -> 1808 OctetList = mk_uni_list(Universal), 1809 dotag_universal(?N_UniversalString,OctetList,length(OctetList)); 1810encode_universal_string(_C, Universal, DoTag) -> 1811 OctetList = mk_uni_list(Universal), 1812 dotag(DoTag, ?N_UniversalString, {OctetList,length(OctetList)}). 1813 1814mk_uni_list(In) -> 1815 mk_uni_list(In,[]). 1816 1817mk_uni_list([],List) -> 1818 lists:reverse(List); 1819mk_uni_list([{A,B,C,D}|T],List) -> 1820 mk_uni_list(T,[D,C,B,A|List]); 1821mk_uni_list([H|T],List) -> 1822 mk_uni_list(T,[H,0,0,0|List]). 1823 1824%%=========================================================================== 1825%% decode Universal strings 1826%% (Buffer, Range, StringType, HasTag, LenIn) -> 1827%% {String, Remain, RemovedBytes} 1828%%=========================================================================== 1829 1830decode_universal_string(Buffer, Range, Tags, LenIn, OptOrMand) -> 1831% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_UniversalString}), 1832 decode_restricted_string(Buffer, Range, ?N_UniversalString, 1833 Tags, LenIn, [], OptOrMand,old). 1834 1835 1836mk_universal_string(In) -> 1837 mk_universal_string(In,[]). 1838 1839mk_universal_string([],Acc) -> 1840 lists:reverse(Acc); 1841mk_universal_string([0,0,0,D|T],Acc) -> 1842 mk_universal_string(T,[D|Acc]); 1843mk_universal_string([A,B,C,D|T],Acc) -> 1844 mk_universal_string(T,[{A,B,C,D}|Acc]). 1845 1846 1847%%============================================================================ 1848%% encode BMP string 1849%%============================================================================ 1850 1851encode_BMP_string(C, {Name,BMPString}, DoTag) when atom(Name)-> 1852 encode_BMP_string(C, BMPString, DoTag); 1853encode_BMP_string(_C, BMPString, []) -> 1854 OctetList = mk_BMP_list(BMPString), 1855 dotag_universal(?N_BMPString,OctetList,length(OctetList)); 1856encode_BMP_string(_C, BMPString, DoTag) -> 1857 OctetList = mk_BMP_list(BMPString), 1858 dotag(DoTag, ?N_BMPString, {OctetList,length(OctetList)}). 1859 1860mk_BMP_list(In) -> 1861 mk_BMP_list(In,[]). 1862 1863mk_BMP_list([],List) -> 1864 lists:reverse(List); 1865mk_BMP_list([{0,0,C,D}|T],List) -> 1866 mk_BMP_list(T,[D,C|List]); 1867mk_BMP_list([H|T],List) -> 1868 mk_BMP_list(T,[H,0|List]). 1869 1870%%============================================================================ 1871%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList} 1872%% (Buffer, Range, StringType, HasTag, TotalLen) -> 1873%% {String, Remain, RemovedBytes} 1874%%============================================================================ 1875decode_BMP_string(Buffer, Range, Tags, LenIn, OptOrMand) -> 1876% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_BMPString}), 1877 decode_restricted_string(Buffer, Range, ?N_BMPString, 1878 Tags, LenIn, [], OptOrMand,old). 1879 1880mk_BMP_string(In) -> 1881 mk_BMP_string(In,[]). 1882 1883mk_BMP_string([],US) -> 1884 lists:reverse(US); 1885mk_BMP_string([0,B|T],US) -> 1886 mk_BMP_string(T,[B|US]); 1887mk_BMP_string([C,D|T],US) -> 1888 mk_BMP_string(T,[{0,0,C,D}|US]). 1889 1890 1891%%============================================================================ 1892%% Generalized time, ITU_T X.680 Chapter 39 1893%% 1894%% encode Generalized time 1895%%============================================================================ 1896 1897encode_generalized_time(C, {Name,OctetList}, DoTag) when atom(Name) -> 1898 encode_generalized_time(C, OctetList, DoTag); 1899encode_generalized_time(_C, OctetList, []) -> 1900 dotag_universal(?N_GeneralizedTime,OctetList,length(OctetList)); 1901encode_generalized_time(_C, OctetList, DoTag) -> 1902 dotag(DoTag, ?N_GeneralizedTime, {OctetList,length(OctetList)}). 1903 1904%%============================================================================ 1905%% decode Generalized time 1906%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1907%%============================================================================ 1908 1909decode_generalized_time(Buffer, Range, Tags, TotalLen, OptOrMand) -> 1910 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL, 1911 number=?N_GeneralizedTime}), 1912 decode_generalized_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand). 1913 1914decode_generalized_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) -> 1915 {RestTags, {FormLen, Buffer0, Rb0}} = 1916 check_tags_i(Tags, Buffer, OptOrMand), 1917 1918 case FormLen of 1919 {?CONSTRUCTED,Len} -> 1920 {Buffer00,RestBytes} = split_list(Buffer0,Len), 1921 {Val01, Buffer01, Rb01} = 1922 decode_generalized_time_notag(Buffer00, Range, 1923 RestTags, TotalLen, 1924 OptOrMand), 1925 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 1926 {Val01, Buffer02, Rb0+Rb01+Rb02}; 1927 {_,Len} -> 1928 <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0, 1929 {binary_to_list(PreBuff), RestBuff, Rb0+Len} 1930 end. 1931 1932%%============================================================================ 1933%% Universal time, ITU_T X.680 Chapter 40 1934%% 1935%% encode UTC time 1936%%============================================================================ 1937 1938encode_utc_time(C, {Name,OctetList}, DoTag) when atom(Name) -> 1939 encode_utc_time(C, OctetList, DoTag); 1940encode_utc_time(_C, OctetList, []) -> 1941 dotag_universal(?N_UTCTime, OctetList,length(OctetList)); 1942encode_utc_time(_C, OctetList, DoTag) -> 1943 dotag(DoTag, ?N_UTCTime, {OctetList,length(OctetList)}). 1944 1945%%============================================================================ 1946%% decode UTC time 1947%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1948%%============================================================================ 1949 1950decode_utc_time(Buffer, Range, Tags, TotalLen, OptOrMand) -> 1951 NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_UTCTime}), 1952 decode_utc_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand). 1953 1954decode_utc_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) -> 1955 {RestTags, {FormLen, Buffer0, Rb0}} = 1956 check_tags_i(Tags, Buffer, OptOrMand), 1957 1958 case FormLen of 1959 {?CONSTRUCTED,Len} -> 1960 {Buffer00,RestBytes} = split_list(Buffer0,Len), 1961 {Val01, Buffer01, Rb01} = 1962 decode_utc_time_notag(Buffer00, Range, 1963 RestTags, TotalLen, 1964 OptOrMand), 1965 {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext), 1966 {Val01, Buffer02, Rb0+Rb01+Rb02}; 1967 {_,Len} -> 1968 <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0, 1969 {binary_to_list(PreBuff), RestBuff, Rb0+Len} 1970 end. 1971 1972 1973%%============================================================================ 1974%% Length handling 1975%% 1976%% Encode length 1977%% 1978%% encode_length(Int | indefinite) -> 1979%% [<127]| [128 + Int (<127),OctetList] | [16#80] 1980%%============================================================================ 1981 1982encode_length(indefinite) -> 1983 {[16#80],1}; % 128 1984encode_length(L) when L =< 16#7F -> 1985 {[L],1}; 1986encode_length(L) -> 1987 Oct = minimum_octets(L), 1988 Len = length(Oct), 1989 if 1990 Len =< 126 -> 1991 {[ (16#80+Len) | Oct ],Len+1}; 1992 true -> 1993 exit({error,{asn1, to_long_length_oct, Len}}) 1994 end. 1995 1996 1997%% Val must be >= 0 1998minimum_octets(Val) -> 1999 minimum_octets(Val,[]). 2000 2001minimum_octets(0,Acc) -> 2002 Acc; 2003minimum_octets(Val, Acc) -> 2004 minimum_octets((Val bsr 8),[Val band 16#FF | Acc]). 2005 2006 2007%%=========================================================================== 2008%% Decode length 2009%% 2010%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} | 2011%% {{Length, RestOctetsL}, NoRemovedBytes} 2012%%=========================================================================== 2013 2014decode_length(<<1:1,0:7,T/binary>>) -> 2015 {{indefinite, T}, 1}; 2016decode_length(<<0:1,Length:7,T/binary>>) -> 2017 {{Length,T},1}; 2018decode_length(<<1:1,LL:7,T/binary>>) -> 2019 <<Length:LL/unit:8,Rest/binary>> = T, 2020 {{Length,Rest}, LL+1}. 2021 2022%decode_length([128 | T]) -> 2023% {{indefinite, T},1}; 2024%decode_length([H | T]) when H =< 127 -> 2025% {{H, T},1}; 2026%decode_length([H | T]) -> 2027% dec_long_length(H band 16#7F, T, 0, 1). 2028 2029 2030%%dec_long_length(0, Buffer, Acc, Len) -> 2031%% {{Acc, Buffer},Len}; 2032%%dec_long_length(Bytes, [H | T], Acc, Len) -> 2033%% dec_long_length(Bytes - 1, T, (Acc bsl 8) + H, Len+1). 2034 2035%%=========================================================================== 2036%% Decode tag and length 2037%% 2038%% decode_tag_and_length(Buffer) -> {Tag, Len, RemainingBuffer, RemovedBytes} 2039%% 2040%%=========================================================================== 2041 2042decode_tag_and_length(Buffer) -> 2043 {Tag, Buffer2, RemBytesTag} = decode_tag(Buffer), 2044 {{Len, Buffer3}, RemBytesLen} = decode_length(Buffer2), 2045 {Tag, Len, Buffer3, RemBytesTag+RemBytesLen}. 2046 2047 2048%%============================================================================ 2049%% Check if valid tag 2050%% 2051%% check_if_valid_tag(Tag, List_of_valid_tags, OptOrMand) -> name of the tag 2052%%=============================================================================== 2053 2054check_if_valid_tag(<<0,0,_/binary>>,_,_) -> 2055 asn1_EOC; 2056check_if_valid_tag(<<>>, _, OptOrMand) -> 2057 check_if_valid_tag2(false,[],[],OptOrMand); 2058check_if_valid_tag(Bytes, ListOfTags, OptOrMand) when binary(Bytes) -> 2059 {Tag, _, _} = decode_tag(Bytes), 2060 check_if_valid_tag(Tag, ListOfTags, OptOrMand); 2061 2062%% This alternative should be removed in the near future 2063%% Bytes as input should be the only necessary call 2064check_if_valid_tag(Tag, ListOfTags, OptOrMand) -> 2065 {Class, _Form, TagNo} = Tag, 2066 C = code_class(Class), 2067 T = case C of 2068 'UNIVERSAL' -> 2069 code_type(TagNo); 2070 _ -> 2071 TagNo 2072 end, 2073 check_if_valid_tag2({C,T}, ListOfTags, Tag, OptOrMand). 2074 2075check_if_valid_tag2(_Class_TagNo, [], Tag, mandatory) -> 2076 exit({error,{asn1,{invalid_tag,Tag}}}); 2077check_if_valid_tag2(_Class_TagNo, [], Tag, _) -> 2078 exit({error,{asn1,{no_optional_tag,Tag}}}); 2079 2080check_if_valid_tag2(Class_TagNo, [{TagName,TagList}|T], Tag, OptOrMand) -> 2081 case check_if_valid_tag_loop(Class_TagNo, TagList) of 2082 true -> 2083 TagName; 2084 false -> 2085 check_if_valid_tag2(Class_TagNo, T, Tag, OptOrMand) 2086 end. 2087 2088check_if_valid_tag_loop(_Class_TagNo,[]) -> 2089 false; 2090check_if_valid_tag_loop(Class_TagNo,[H|T]) -> 2091 %% It is not possible to distinguish between SEQUENCE OF and SEQUENCE, and 2092 %% between SET OF and SET because both are coded as 16 and 17, respectively. 2093 H_without_OF = case H of 2094 {C, 'SEQUENCE OF'} -> 2095 {C, 'SEQUENCE'}; 2096 {C, 'SET OF'} -> 2097 {C, 'SET'}; 2098 Else -> 2099 Else 2100 end, 2101 2102 case H_without_OF of 2103 Class_TagNo -> 2104 true; 2105 {_,_} -> 2106 check_if_valid_tag_loop(Class_TagNo,T); 2107 _ -> 2108 check_if_valid_tag_loop(Class_TagNo,H), 2109 check_if_valid_tag_loop(Class_TagNo,T) 2110 end. 2111 2112 2113 2114code_class(0) -> 'UNIVERSAL'; 2115code_class(16#40) -> 'APPLICATION'; 2116code_class(16#80) -> 'CONTEXT'; 2117code_class(16#C0) -> 'PRIVATE'. 2118 2119 2120code_type(1) -> 'BOOLEAN'; 2121code_type(2) -> 'INTEGER'; 2122code_type(3) -> 'BIT STRING'; 2123code_type(4) -> 'OCTET STRING'; 2124code_type(5) -> 'NULL'; 2125code_type(6) -> 'OBJECT IDENTIFIER'; 2126code_type(7) -> 'OBJECT DESCRIPTOR'; 2127code_type(8) -> 'EXTERNAL'; 2128code_type(9) -> 'REAL'; 2129code_type(10) -> 'ENUMERATED'; 2130code_type(11) -> 'EMBEDDED_PDV'; 2131code_type(16) -> 'SEQUENCE'; 2132code_type(16) -> 'SEQUENCE OF'; 2133code_type(17) -> 'SET'; 2134code_type(17) -> 'SET OF'; 2135code_type(18) -> 'NumericString'; 2136code_type(19) -> 'PrintableString'; 2137code_type(20) -> 'TeletexString'; 2138code_type(21) -> 'VideotexString'; 2139code_type(22) -> 'IA5String'; 2140code_type(23) -> 'UTCTime'; 2141code_type(24) -> 'GeneralizedTime'; 2142code_type(25) -> 'GraphicString'; 2143code_type(26) -> 'VisibleString'; 2144code_type(27) -> 'GeneralString'; 2145code_type(28) -> 'UniversalString'; 2146code_type(30) -> 'BMPString'; 2147code_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}). 2148 2149%%------------------------------------------------------------------------- 2150%% decoding of the components of a SET 2151%%------------------------------------------------------------------------- 2152 2153decode_set(Rb, indefinite, <<0,0,Bytes/binary>>, _OptOrMand, _Fun3, Acc) -> 2154 {lists:reverse(Acc),Bytes,Rb+2}; 2155 2156decode_set(Rb, indefinite, Bytes, OptOrMand, Fun3, Acc) -> 2157 {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand), 2158 decode_set(Rb+Rb1, indefinite, Remain, OptOrMand, Fun3, [Term|Acc]); 2159 2160decode_set(Rb, Num, Bytes, _OptOrMand, _Fun3, Acc) when Num == 0 -> 2161 {lists:reverse(Acc), Bytes, Rb}; 2162 2163decode_set(_, Num, _, _, _, _) when Num < 0 -> 2164 exit({error,{asn1,{length_error,'SET'}}}); 2165 2166decode_set(Rb, Num, Bytes, OptOrMand, Fun3, Acc) -> 2167 {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand), 2168 decode_set(Rb+Rb1, Num-Rb1, Remain, OptOrMand, Fun3, [Term|Acc]). 2169 2170 2171%%------------------------------------------------------------------------- 2172%% decoding of SEQUENCE OF and SET OF 2173%%------------------------------------------------------------------------- 2174 2175decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun3, _TagIn, Acc) -> 2176 {lists:reverse(Acc),Bytes,Rb+2}; 2177 2178decode_components(Rb, indefinite, Bytes, Fun3, TagIn, Acc) -> 2179 {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn), 2180 decode_components(Rb+Rb1, indefinite, Remain, Fun3, TagIn, [Term|Acc]); 2181 2182decode_components(Rb, Num, Bytes, _Fun3, _TagIn, Acc) when Num == 0 -> 2183 {lists:reverse(Acc), Bytes, Rb}; 2184 2185decode_components(_, Num, _, _, _, _) when Num < 0 -> 2186 exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}}); 2187 2188decode_components(Rb, Num, Bytes, Fun3, TagIn, Acc) -> 2189 {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn), 2190 decode_components(Rb+Rb1, Num-Rb1, Remain, Fun3, TagIn, [Term|Acc]). 2191 2192%%decode_components(Rb, indefinite, [0,0|Bytes], _Fun3, _TagIn, Acc) -> 2193%% {lists:reverse(Acc),Bytes,Rb+2}; 2194 2195decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun4, _TagIn, _Fun, Acc) -> 2196 {lists:reverse(Acc),Bytes,Rb+2}; 2197 2198decode_components(Rb, indefinite, Bytes, _Fun4, TagIn, _Fun, Acc) -> 2199 {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun), 2200 decode_components(Rb+Rb1, indefinite, Remain, _Fun4, TagIn, _Fun, [Term|Acc]); 2201 2202decode_components(Rb, Num, Bytes, _Fun4, _TagIn, _Fun, Acc) when Num == 0 -> 2203 {lists:reverse(Acc), Bytes, Rb}; 2204 2205decode_components(_, Num, _, _, _, _, _) when Num < 0 -> 2206 exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}}); 2207 2208decode_components(Rb, Num, Bytes, _Fun4, TagIn, _Fun, Acc) -> 2209 {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun), 2210 decode_components(Rb+Rb1, Num-Rb1, Remain, _Fun4, TagIn, _Fun, [Term|Acc]). 2211 2212 2213 2214%%------------------------------------------------------------------------- 2215%% INTERNAL HELPER FUNCTIONS (not exported) 2216%%------------------------------------------------------------------------- 2217 2218 2219%%========================================================================== 2220%% Encode tag 2221%% 2222%% dotag(tag | notag, TagValpattern | TagValTuple, [Length, Value]) -> [Tag] 2223%% TagValPattern is a correct bitpattern for a tag 2224%% TagValTuple is a tuple of three bitpatterns, Class, Form and TagNo where 2225%% Class = UNIVERSAL | APPLICATION | CONTEXT | PRIVATE 2226%% Form = Primitive | Constructed 2227%% TagNo = Number of tag 2228%%========================================================================== 2229 2230 2231dotag([], Tag, {Bytes,Len}) -> 2232 dotag_universal(Tag,Bytes,Len); 2233dotag(Tags, Tag, {Bytes,Len}) -> 2234 encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}], 2235 Bytes, Len); 2236 2237dotag(Tags, Tag, Bytes) -> 2238 encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}], 2239 Bytes, size(Bytes)). 2240 2241dotag_universal(UniversalTag,Bytes,Len) when Len =< 16#7F-> 2242 {[UniversalTag,Len,Bytes],2+Len}; 2243dotag_universal(UniversalTag,Bytes,Len) -> 2244 {EncLen,LenLen}=encode_length(Len), 2245 {[UniversalTag,EncLen,Bytes],1+LenLen+Len}. 2246 2247%% decoding postitive integer values. 2248decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>,RemovedBytes) -> 2249 <<Int:Len/unit:8,Buffer2/binary>> = Bin, 2250 {Int,Buffer2,RemovedBytes}; 2251%% decoding negative integer values. 2252decode_integer2(Len,<<1:1,B2:7,Bs/binary>>,RemovedBytes) -> 2253 <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>, 2254 Int = N - (1 bsl (8 * Len - 1)), 2255 {Int,Buffer2,RemovedBytes}. 2256 2257%%decode_integer2(Len,Buffer,Acc,RemovedBytes) when (hd(Buffer) band 16#FF) =< 16#7F -> 2258%% {decode_integer_pos(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes}; 2259%%decode_integer2(Len,Buffer,Acc,RemovedBytes) -> 2260%% {decode_integer_neg(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes}. 2261 2262%%decode_integer_pos([Byte|Tail], Shift) -> 2263%% (Byte bsl Shift) bor decode_integer_pos(Tail, Shift-8); 2264%%decode_integer_pos([], _) -> 0. 2265 2266 2267%%decode_integer_neg([Byte|Tail], Shift) -> 2268%% (-128 + (Byte band 127) bsl Shift) bor decode_integer_pos(Tail, Shift-8). 2269 2270 2271concat_bit_binaries([],Bin={_,_}) -> 2272 Bin; 2273concat_bit_binaries({0,B1},{U2,B2}) -> 2274 {U2,<<B1/binary,B2/binary>>}; 2275concat_bit_binaries({U1,B1},{U2,B2}) -> 2276 S1 = (size(B1) * 8) - U1, 2277 S2 = (size(B2) * 8) - U2, 2278 PadBits = 8 - ((S1+S2) rem 8), 2279 {PadBits, <<B1:S1/binary-unit:1,B2:S2/binary-unit:1,0:PadBits>>}; 2280concat_bit_binaries(L1,L2) when list(L1),list(L2) -> 2281 %% this case occur when decoding with NNL 2282 L1 ++ L2. 2283 2284 2285get_constraint(C,Key) -> 2286 case lists:keysearch(Key,1,C) of 2287 false -> 2288 no; 2289 {value,{_,V}} -> 2290 V 2291 end. 2292 2293%%skip(Buffer, 0) -> 2294%% Buffer; 2295%%skip([H | T], Len) -> 2296%% skip(T, Len-1). 2297 2298new_tags([],LastTag) -> 2299 [LastTag]; 2300new_tags(Tags=[#tag{type='IMPLICIT'}],_LastTag) -> 2301 Tags; 2302new_tags([T1 = #tag{type='IMPLICIT'},#tag{type=T2Type}|Rest],LastTag) -> 2303 new_tags([T1#tag{type=T2Type}|Rest],LastTag); 2304new_tags(Tags,LastTag) -> 2305 case lists:last(Tags) of 2306 #tag{type='IMPLICIT'} -> 2307 Tags; 2308 _ -> 2309 Tags ++ [LastTag] 2310 end. 2311