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_v2.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $ 18-module(asn1rt_ber_bin_v2). 19 20%% encoding / decoding of BER 21 22-export([decode/1, decode/2, match_tags/2, encode/1]). 23-export([fixoptionals/2, cindex/3, 24 list_to_record/2, 25 encode_tag_val/1, 26 encode_tags/3]). 27-export([encode_boolean/2,decode_boolean/2, 28 encode_integer/3,encode_integer/4, 29 decode_integer/3, decode_integer/4, 30 encode_enumerated/2, 31 encode_enumerated/4,decode_enumerated/4, 32 encode_real/2,decode_real/3, 33 encode_bit_string/4,decode_bit_string/4, 34 decode_compact_bit_string/4, 35 encode_octet_string/3,decode_octet_string/3, 36 encode_null/2,decode_null/2, 37 encode_object_identifier/2,decode_object_identifier/2, 38 encode_restricted_string/4,decode_restricted_string/4, 39 encode_universal_string/3,decode_universal_string/3, 40 encode_BMP_string/3,decode_BMP_string/3, 41 encode_generalized_time/3,decode_generalized_time/3, 42 encode_utc_time/3,decode_utc_time/3, 43 encode_length/1,decode_length/1, 44 decode_tag_and_length/1]). 45 46-export([encode_open_type/1,encode_open_type/2, 47 decode_open_type/2,decode_open_type_as_binary/2]). 48 49-export([decode_primitive_incomplete/2]). 50 51-include("asn1_records.hrl"). 52 53% the encoding of class of tag bits 8 and 7 54-define(UNIVERSAL, 0). 55-define(APPLICATION, 16#40). 56-define(CONTEXT, 16#80). 57-define(PRIVATE, 16#C0). 58 59%%% primitive or constructed encoding % bit 6 60-define(PRIMITIVE, 0). 61-define(CONSTRUCTED, 2#00100000). 62 63%%% The tag-number for universal types 64-define(N_BOOLEAN, 1). 65-define(N_INTEGER, 2). 66-define(N_BIT_STRING, 3). 67-define(N_OCTET_STRING, 4). 68-define(N_NULL, 5). 69-define(N_OBJECT_IDENTIFIER, 6). 70-define(N_OBJECT_DESCRIPTOR, 7). 71-define(N_EXTERNAL, 8). 72-define(N_REAL, 9). 73-define(N_ENUMERATED, 10). 74-define(N_EMBEDDED_PDV, 11). 75-define(N_SEQUENCE, 16). 76-define(N_SET, 17). 77-define(N_NumericString, 18). 78-define(N_PrintableString, 19). 79-define(N_TeletexString, 20). 80-define(N_VideotexString, 21). 81-define(N_IA5String, 22). 82-define(N_UTCTime, 23). 83-define(N_GeneralizedTime, 24). 84-define(N_GraphicString, 25). 85-define(N_VisibleString, 26). 86-define(N_GeneralString, 27). 87-define(N_UniversalString, 28). 88-define(N_BMPString, 30). 89 90 91% the complete tag-word of built-in types 92-define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1). 93-define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2). 94-define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED 95-define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED 96-define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5). 97-define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6). 98-define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7). 99-define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8). 100-define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9). 101-define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10). 102-define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11). 103-define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16). 104-define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17). 105-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed 106-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed 107-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed 108-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed 109-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed 110-define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23). 111-define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24). 112-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed 113-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed 114-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed 115-define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed 116-define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed 117 118% encode(Tlv={_Tag={?PRIMITIVE,_},_VList}) -> 119% encode_primitive(Tlv); 120% encode(Tlv) -> 121% encode_constructed(Tlv). 122 123encode([Tlv]) -> 124 encode(Tlv); 125encode({TlvTag,TlvVal}) when list(TlvVal) -> 126 %% constructed form of value 127 encode_tlv(TlvTag,TlvVal,?CONSTRUCTED); 128encode({TlvTag,TlvVal}) -> 129 encode_tlv(TlvTag,TlvVal,?PRIMITIVE); 130encode(Bin) when binary(Bin) -> 131 Bin. 132 133encode_tlv(TlvTag,TlvVal,Form) -> 134 Tag = encode_tlv_tag(TlvTag,Form), 135 {Val,VLen} = encode_tlv_val(TlvVal), 136 {Len,_LLen} = encode_length(VLen), 137 BinLen = list_to_binary(Len), 138 <<Tag/binary,BinLen/binary,Val/binary>>. 139 140encode_tlv_tag(ClassTagNo,Form) -> 141 Class = ClassTagNo bsr 16, 142 case encode_tag_val({Class bsl 6,Form,(ClassTagNo - (Class bsl 16))}) of 143 T when list(T) -> 144 list_to_binary(T); 145 T -> 146 T 147 end. 148 149encode_tlv_val(TlvL) when list(TlvL) -> 150 encode_tlv_list(TlvL,[]); 151encode_tlv_val(Bin) -> 152 {Bin,size(Bin)}. 153 154encode_tlv_list([Tlv|Tlvs],Acc) -> 155 EncTlv = encode(Tlv), 156 encode_tlv_list(Tlvs,[EncTlv|Acc]); 157encode_tlv_list([],Acc) -> 158 Bin=list_to_binary(lists:reverse(Acc)), 159 {Bin,size(Bin)}. 160 161% encode_primitive({{_,ClassTagNo},V}) -> 162% Len = size(V), % not sufficient as length encode 163% Class = ClassTagNo bsr 16, 164% {TagLen,Tag} = 165% case encode_tag_val({Class,?PRIMITIVE,ClassTagNo - Class}) of 166% T when list(T) -> 167% {length(T),list_to_binary(T)}; 168% T -> 169% {1,T} 170% end, 171 172 173decode(B,driver) -> 174 case catch port_control(drv_complete,2,B) of 175 Bin when binary(Bin) -> 176 binary_to_term(Bin); 177 List when list(List) -> handle_error(List,B); 178 {'EXIT',{badarg,Reason}} -> 179 asn1rt_driver_handler:load_driver(), 180 receive 181 driver_ready -> 182 case catch port_control(drv_complete,2,B) of 183 Bin2 when binary(Bin2) -> binary_to_term(Bin2); 184 List when list(List) -> handle_error(List,B); 185 Error -> exit(Error) 186 end; 187 {error,Error} -> % error when loading driver 188 %% the driver could not be loaded 189 exit(Error); 190 Error={port_error,Reason} -> 191 exit(Error) 192 end; 193 {'EXIT',Reason} -> 194 exit(Reason) 195 end. 196 197handle_error([],_)-> 198 exit({error,{"memory allocation problem"}}); 199handle_error([$1|_],L) -> % error in driver 200 exit({error,{asn1_error,L}}); 201handle_error([$2|_],L) -> % error in driver due to wrong tag 202 exit({error,{asn1_error,{"bad tag",L}}}); 203handle_error([$3|_],L) -> % error in driver due to length error 204 exit({error,{asn1_error,{"bad length field",L}}}); 205handle_error([$4|_],L) -> % error in driver due to indefinite length error 206 exit({error,{asn1_error,{"indefinite length without end bytes",L}}}); 207handle_error(ErrL,L) -> 208 exit({error,{unknown_error,ErrL,L}}). 209 210 211decode(Bin) when binary(Bin) -> 212 decode_primitive(Bin); 213decode(Tlv) -> % assume it is a tlv 214 {Tlv,<<>>}. 215 216 217decode_primitive(Bin) -> 218 {{Form,TagNo,Len,V},Rest} = decode_tlv(Bin), 219 case Form of 220 1 when Len == indefinite -> % constructed 221 {Vlist,Rest2} = decode_constructed_indefinite(V,[]), 222 {{TagNo,Vlist},Rest2}; 223 1 -> % constructed 224 {{TagNo,decode_constructed(V)},Rest}; 225 0 -> % primitive 226 {{TagNo,V},Rest} 227 end. 228 229decode_constructed(<<>>) -> 230 []; 231decode_constructed(Bin) -> 232 {Tlv,Rest} = decode_primitive(Bin), 233 [Tlv|decode_constructed(Rest)]. 234 235decode_constructed_indefinite(<<0,0,Rest/binary>>,Acc) -> 236 {lists:reverse(Acc),Rest}; 237decode_constructed_indefinite(Bin,Acc) -> 238 {Tlv,Rest} = decode_primitive(Bin), 239 decode_constructed_indefinite(Rest, [Tlv|Acc]). 240 241decode_tlv(Bin) -> 242 {Form,TagNo,Len,Bin2} = decode_tag_and_length(Bin), 243 case Len of 244 indefinite -> 245 {{Form,TagNo,Len,Bin2},[]}; 246 _ -> 247 <<V:Len/binary,Bin3/binary>> = Bin2, 248 {{Form,TagNo,Len,V},Bin3} 249 end. 250 251%% decode_primitive_incomplete/2 decodes an encoded message incomplete 252%% by help of the pattern attribute (first argument). 253decode_primitive_incomplete([[default,TagNo]],Bin) -> %default 254 case decode_tlv(Bin) of 255 {{Form,TagNo,Len,V},Rest} -> 256 decode_incomplete2(Form,TagNo,Len,V,[],Rest); 257 _ -> 258 %{asn1_DEFAULT,Bin} 259 asn1_NOVALUE 260 end; 261decode_primitive_incomplete([[default,TagNo,Directives]],Bin) -> %default, constructed type, Directives points into this type 262 case decode_tlv(Bin) of 263 {{Form,TagNo,Len,V},Rest} -> 264 decode_incomplete2(Form,TagNo,Len,V,Directives,Rest); 265 _ -> 266 %{asn1_DEFAULT,Bin} 267 asn1_NOVALUE 268 end; 269decode_primitive_incomplete([[opt,TagNo]],Bin) -> %optional 270 case decode_tlv(Bin) of 271 {{Form,TagNo,Len,V},Rest} -> 272 decode_incomplete2(Form,TagNo,Len,V,[],Rest); 273 _ -> 274 %{{TagNo,asn1_NOVALUE},Bin} 275 asn1_NOVALUE 276 end; 277decode_primitive_incomplete([[opt,TagNo,Directives]],Bin) -> %optional 278 case decode_tlv(Bin) of 279 {{Form,TagNo,Len,V},Rest} -> 280 decode_incomplete2(Form,TagNo,Len,V,Directives,Rest); 281 _ -> 282 %{{TagNo,asn1_NOVALUE},Bin} 283 asn1_NOVALUE 284 end; 285%% A choice alternative that shall be undecoded 286decode_primitive_incomplete([[alt_undec,TagNo]|RestAlts],Bin) -> 287% decode_incomplete_bin(Bin); 288 case decode_tlv(Bin) of 289 {{_Form,TagNo,_Len,_V},_R} -> 290 decode_incomplete_bin(Bin); 291 _ -> 292 decode_primitive_incomplete(RestAlts,Bin) 293 end; 294decode_primitive_incomplete([[alt,TagNo]|RestAlts],Bin) -> 295 case decode_tlv(Bin) of 296 {{_Form,TagNo,_Len,V},Rest} -> 297 {{TagNo,V},Rest}; 298 _ -> 299 decode_primitive_incomplete(RestAlts,Bin) 300 end; 301decode_primitive_incomplete([[alt,TagNo,Directives]|RestAlts],Bin) -> 302 case decode_tlv(Bin) of 303 {{Form,TagNo,Len,V},Rest} -> 304 decode_incomplete2(Form,TagNo,Len,V,Directives,Rest); 305 _ -> 306 decode_primitive_incomplete(RestAlts,Bin) 307 end; 308decode_primitive_incomplete([[alt_parts,TagNo]|RestAlts],Bin) -> 309 case decode_tlv(Bin) of 310 {{_Form,TagNo,_Len,V},Rest} -> 311 {{TagNo,decode_parts_incomplete(V)},Rest}; 312 _ -> 313 decode_primitive_incomplete(RestAlts,Bin) 314 end; 315decode_primitive_incomplete([[undec,_TagNo]|_RestTag],Bin) -> %incomlete decode 316 decode_incomplete_bin(Bin); %% use this if changing handling of 317decode_primitive_incomplete([[parts,TagNo]|_RestTag],Bin) -> 318 case decode_tlv(Bin) of 319 {{_Form,TagNo,_Len,V},Rest} -> 320 {{TagNo,decode_parts_incomplete(V)},Rest}; 321 Err -> 322 {error,{asn1,"tag failure",TagNo,Err}} 323 end; 324decode_primitive_incomplete([mandatory|RestTag],Bin) -> 325 case decode_tlv(Bin) of 326 {{Form,TagNo,Len,V},Rest} -> 327 decode_incomplete2(Form,TagNo,Len,V,RestTag,Rest); 328 _ -> 329 {error,{asn1,"partial incomplete decode failure"}} 330 end; 331%% A choice that is a toptype or a mandatory component of a 332%% SEQUENCE or SET. 333decode_primitive_incomplete([[mandatory,Directives]],Bin) -> 334 case decode_tlv(Bin) of 335 {{Form,TagNo,Len,V},Rest} -> 336 decode_incomplete2(Form,TagNo,Len,V,Directives,Rest); 337 _ -> 338 {error,{asn1,"partial incomplete decode failure"}} 339 end; 340decode_primitive_incomplete([],Bin) -> 341 decode_primitive(Bin). 342 343%% decode_parts_incomplete/1 receives a number of values encoded in 344%% sequence and returns the parts as unencoded binaries 345decode_parts_incomplete(<<>>) -> 346 []; 347decode_parts_incomplete(Bin) -> 348 {ok,Rest} = skip_tag(Bin), 349 {ok,Rest2} = skip_length_and_value(Rest), 350 LenPart = size(Bin) - size(Rest2), 351 <<Part:LenPart/binary,RestBin/binary>> = Bin, 352 [Part|decode_parts_incomplete(RestBin)]. 353 354 355%% decode_incomplete2 checks if V is a value of a constructed or 356%% primitive type, and continues the decode propeerly. 357decode_incomplete2(1,TagNo,indefinite,V,TagMatch,_) -> 358 %% constructed indefinite length 359 {Vlist,Rest2} = decode_constr_indef_incomplete(TagMatch,V,[]), 360 {{TagNo,Vlist},Rest2}; 361decode_incomplete2(1,TagNo,_Len,V,TagMatch,Rest) -> 362 {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest}; 363decode_incomplete2(0,TagNo,_Len,V,_TagMatch,Rest) -> 364 {{TagNo,V},Rest}. 365 366decode_constructed_incomplete(_TagMatch,<<>>) -> 367 []; 368decode_constructed_incomplete([mandatory|RestTag],Bin) -> 369 {Tlv,Rest} = decode_primitive(Bin), 370 [Tlv|decode_constructed_incomplete(RestTag,Rest)]; 371decode_constructed_incomplete(Directives=[[Alt,_]|_],Bin) 372 when Alt == alt_undec; Alt == alt -> 373 case decode_tlv(Bin) of 374 {{_Form,TagNo,_Len,V},Rest} -> 375 case incomplete_choice_alt(TagNo,Directives) of 376 alt_undec -> 377 LenA = size(Bin)-size(Rest), 378 <<A:LenA/binary,Rest/binary>> = Bin, 379 A; 380% {UndecBin,_}=decode_incomplete_bin(Bin), 381% UndecBin; 382% [{TagNo,V}]; 383 alt -> 384 {Tlv,_} = decode_primitive(V), 385 [{TagNo,Tlv}]; 386 alt_parts -> 387 %{{TagNo,decode_parts_incomplete(V)},Rest}; % maybe wrong 388 [{TagNo,decode_parts_incomplete(V)}]; 389 Err -> 390 {error,{asn1,"partial incomplete decode failure",Err}} 391 end; 392 _ -> 393 {error,{asn1,"partial incomplete decode failure"}} 394 end; 395decode_constructed_incomplete([TagNo|RestTag],Bin) -> 396%% {Tlv,Rest} = decode_primitive_incomplete([TagNo],Bin), 397 case decode_primitive_incomplete([TagNo],Bin) of 398 {Tlv,Rest} -> 399 [Tlv|decode_constructed_incomplete(RestTag,Rest)]; 400 asn1_NOVALUE -> 401 decode_constructed_incomplete(RestTag,Bin) 402 end; 403decode_constructed_incomplete([],Bin) -> 404 {Tlv,_Rest}=decode_primitive(Bin), 405 [Tlv]. 406 407decode_constr_indef_incomplete(_TagMatch,<<0,0,Rest/binary>>,Acc) -> 408 {lists:reverse(Acc),Rest}; 409decode_constr_indef_incomplete([Tag|RestTags],Bin,Acc) -> 410% {Tlv,Rest} = decode_primitive_incomplete([Tag],Bin), 411 case decode_primitive_incomplete([Tag],Bin) of 412 {Tlv,Rest} -> 413 decode_constr_indef_incomplete(RestTags,Rest,[Tlv|Acc]); 414 asn1_NOVALUE -> 415 decode_constr_indef_incomplete(RestTags,Bin,Acc) 416 end. 417 418 419decode_incomplete_bin(Bin) -> 420 {ok,Rest} = skip_tag(Bin), 421 {ok,Rest2} = skip_length_and_value(Rest), 422 IncLen = size(Bin) - size(Rest2), 423 <<IncBin:IncLen/binary,Ret/binary>> = Bin, 424 {IncBin,Ret}. 425 426incomplete_choice_alt(TagNo,[[Alt,TagNo]|_Directives]) -> 427 Alt; 428incomplete_choice_alt(TagNo,[_H|Directives]) -> 429 incomplete_choice_alt(TagNo,Directives); 430incomplete_choice_alt(_,[]) -> 431 error. 432 433 434%% skip_tag and skip_length_and_value are rutines used both by 435%% decode_partial_incomplete and decode_partial (decode/2). 436 437skip_tag(<<_:3,31:5,Rest/binary>>)-> 438 skip_long_tag(Rest); 439skip_tag(<<_:3,_Tag:5,Rest/binary>>) -> 440 {ok,Rest}. 441 442skip_long_tag(<<1:1,_:7,Rest/binary>>) -> 443 skip_long_tag(Rest); 444skip_long_tag(<<0:1,_:7,Rest/binary>>) -> 445 {ok,Rest}. 446 447skip_length_and_value(Binary) -> 448 case decode_length(Binary) of 449 {indefinite,RestBinary} -> 450 skip_indefinite_value(RestBinary); 451 {Length,RestBinary} -> 452 <<_:Length/unit:8,Rest/binary>> = RestBinary, 453 {ok,Rest} 454 end. 455 456skip_indefinite_value(<<0,0,Rest/binary>>) -> 457 {ok,Rest}; 458skip_indefinite_value(Binary) -> 459 {ok,RestBinary}=skip_tag(Binary), 460 {ok,RestBinary2} = skip_length_and_value(RestBinary), 461 skip_indefinite_value(RestBinary2). 462 463 464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 465%% match_tags takes a Tlv (Tag, Length, Value) structure and matches 466%% it with the tags in TagList. If the tags does not match the function 467%% crashes otherwise it returns the remaining Tlv after that the tags have 468%% been removed. 469%% 470%% match_tags(Tlv, TagList) 471%% 472 473 474match_tags({T,V}, [T|Tt]) -> 475 match_tags(V,Tt); 476match_tags([{T,V}],[T|Tt]) -> 477 match_tags(V, Tt); 478match_tags(Vlist = [{T,_V}|_], [T]) -> 479 Vlist; 480match_tags(Tlv, []) -> 481 Tlv; 482match_tags({Tag,_V},[T|_Tt]) -> 483 {error,{asn1,{wrong_tag,{Tag,T}}}}. 484 485 486cindex(Ix,Val,Cname) -> 487 case element(Ix,Val) of 488 {Cname,Val2} -> Val2; 489 X -> X 490 end. 491 492%%=============================================================================== 493%%=============================================================================== 494%%=============================================================================== 495%% Optionals, preset not filled optionals with asn1_NOVALUE 496%%=============================================================================== 497%%=============================================================================== 498%%=============================================================================== 499 500% converts a list to a record if necessary 501list_to_record(Name,List) when list(List) -> 502 list_to_tuple([Name|List]); 503list_to_record(_Name,Tuple) when tuple(Tuple) -> 504 Tuple. 505 506 507fixoptionals(OptList,Val) when list(Val) -> 508 fixoptionals(OptList,Val,1,[],[]). 509 510fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) -> 511 fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]); 512fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) -> 513 fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]); 514fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) -> 515 fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]); 516fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) -> 517 fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]); 518fixoptionals([],[],_,_Acc1,Acc2) -> 519 % return Val as a record 520 list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]). 521 522 523%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) -> 524%% 8bit Int | binary 525encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) -> 526 <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>; 527 528encode_tag_val({Class, Form, TagNo}) -> 529 {Octets,_Len} = mk_object_val(TagNo), 530 BinOct = list_to_binary(Octets), 531 <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>; 532 533%% asumes whole correct tag bitpattern, multiple of 8 534encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% is this function used??!! 535%% asumes correct bitpattern of 0-5 536encode_tag_val(Tag) -> encode_tag_val2(Tag,[]). 537 538encode_tag_val2(Tag, OctAck) when (Tag =< 255) -> 539 [Tag | OctAck]; 540encode_tag_val2(Tag, OctAck) -> 541 encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]). 542 543 544%%=============================================================================== 545%% Decode a tag 546%% 547%% decode_tag(OctetListBuffer) -> {{Form, (Class bsl 16)+ TagNo}, RestOfBuffer, RemovedBytes} 548%%=============================================================================== 549 550decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 0:1, Length:7, RestBuffer/binary>>) when TagNo < 31 -> 551 {Form, (Class bsl 16) + TagNo, Length, RestBuffer}; 552decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, 0:7, T/binary>>) when TagNo < 31 -> 553 {Form, (Class bsl 16) + TagNo, indefinite, T}; 554decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, LL:7, T/binary>>) when TagNo < 31 -> 555 <<Length:LL/unit:8,RestBuffer/binary>> = T, 556 {Form, (Class bsl 16) + TagNo, Length, RestBuffer}; 557decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 0:1, Length:7, RestBuffer/binary>>) -> 558 {Form, (Class bsl 16) + TagNo, Length, RestBuffer}; 559decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, 0:7, T/binary>>) -> 560 {Form, (Class bsl 16) + TagNo, indefinite, T}; 561decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, LL:7, T/binary>>) -> 562 <<Length:LL/unit:8,RestBuffer/binary>> = T, 563 {Form, (Class bsl 16) + TagNo, Length, RestBuffer}; 564decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) -> 565 {TagNo, Buffer1} = decode_tag(Buffer, 0), 566 {Length, RestBuffer} = decode_length(Buffer1), 567 {Form, (Class bsl 16) + TagNo, Length, RestBuffer}. 568 569 570 571%% last partial tag 572decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck) -> 573 TagNo = (TagAck bsl 7) bor PartialTag, 574 %%<<TagNo>> = <<TagAck:1, PartialTag:7>>, 575 {TagNo, Buffer}; 576% more tags 577decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck) -> 578 TagAck1 = (TagAck bsl 7) bor PartialTag, 579 %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>, 580 decode_tag(Buffer, TagAck1). 581 582 583%%======================================================================= 584%% 585%% Encode all tags in the list Tags and return a possibly deep list of 586%% bytes with tag and length encoded 587%% The taglist must be in reverse order (fixed by the asn1 compiler) 588%% e.g [T1,T2] will result in 589%% {[EncodedT2,EncodedT1|BytesSoFar],LenSoFar+LenT2+LenT1} 590%% 591 592encode_tags([Tag|Trest], BytesSoFar, LenSoFar) -> 593% remove {Bytes1,L1} = encode_one_tag(Tag), 594 {Bytes2,L2} = encode_length(LenSoFar), 595 encode_tags(Trest, [Tag,Bytes2|BytesSoFar], 596 LenSoFar + size(Tag) + L2); 597encode_tags([], BytesSoFar, LenSoFar) -> 598 {BytesSoFar,LenSoFar}. 599 600encode_tags(TagIn, {BytesSoFar,LenSoFar}) -> 601 encode_tags(TagIn, BytesSoFar, LenSoFar). 602 603% encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) -> 604% NewForm = case Type of 605% 'EXPLICIT' -> 606% ?CONSTRUCTED; 607% _ -> 608% Form 609% end, 610% Bytes = encode_tag_val({Class,NewForm,No}), 611% {Bytes,size(Bytes)}. 612 613 614%%=============================================================================== 615%% 616%% This comment is valid for all the encode/decode functions 617%% 618%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound} 619%% used for PER-coding but not for BER-coding. 620%% 621%% Val = Value. If Val is an atom then it is a symbolic integer value 622%% (i.e the atom must be one of the names in the NamedNumberList). 623%% The NamedNumberList is used to translate the atom to an integer value 624%% before encoding. 625%% 626%%=============================================================================== 627 628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 629%% encode_open_type(Value) -> io_list (i.e nested list with integers, binaries) 630%% Value = list of bytes of an already encoded value (the list must be flat) 631%% | binary 632 633%% 634encode_open_type(Val) when list(Val) -> 635% {Val,length(Val)}; 636 encode_open_type(list_to_binary(Val)); 637encode_open_type(Val) -> 638 {Val, size(Val)}. 639 640%% 641encode_open_type(Val, T) when list(Val) -> 642 encode_open_type(list_to_binary(Val),T); 643encode_open_type(Val,[]) -> 644 {Val, size(Val)}; 645encode_open_type(Val,Tag) -> 646 encode_tags(Tag,Val, size(Val)). 647 648 649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 650%% decode_open_type(Tlv, TagIn) -> Value 651%% Tlv = {Tag,V} | V where V -> binary() 652%% TagIn = [TagVal] where TagVal -> int() 653%% Value = binary with decoded data (which must be decoded again as some type) 654%% 655decode_open_type(Tlv, TagIn) -> 656 case match_tags(Tlv,TagIn) of 657 Bin when binary(Bin) -> 658 {InnerTlv,_} = decode(Bin), 659 InnerTlv; 660 TlvBytes -> TlvBytes 661 end. 662 663 664decode_open_type_as_binary(Tlv,TagIn)-> 665 case match_tags(Tlv,TagIn) of 666 V when binary(V) -> 667 V; 668 [Tlv2] -> encode(Tlv2); 669 Tlv2 -> encode(Tlv2) 670 end. 671 672%%=============================================================================== 673%%=============================================================================== 674%%=============================================================================== 675%% Boolean, ITU_T X.690 Chapter 8.2 676%%=============================================================================== 677%%=============================================================================== 678%%=============================================================================== 679 680%%=============================================================================== 681%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len} 682%%=============================================================================== 683 684encode_boolean({Name, Val}, TagIn) when atom(Name) -> 685 encode_boolean(Val, TagIn); 686encode_boolean(true, TagIn) -> 687 encode_tags(TagIn, [16#FF],1); 688encode_boolean(false, TagIn) -> 689 encode_tags(TagIn, [0],1); 690encode_boolean(X,_) -> 691 exit({error,{asn1, {encode_boolean, X}}}). 692 693 694%%=============================================================================== 695%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} | 696%% {false, Remain, RemovedBytes} 697%%=============================================================================== 698decode_boolean(Tlv,TagIn) -> 699 Val = match_tags(Tlv, TagIn), 700 case Val of 701 <<0:8>> -> 702 false; 703 <<_:8>> -> 704 true; 705 _ -> 706 exit({error,{asn1, {decode_boolean, Val}}}) 707 end. 708 709 710%%=========================================================================== 711%% Integer, ITU_T X.690 Chapter 8.3 712 713%% encode_integer(Constraint, Value, Tag) -> [octet list] 714%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list] 715%% Value = INTEGER | {Name,INTEGER} 716%% Tag = tag | notag 717%%=========================================================================== 718 719encode_integer(C, Val, Tag) when integer(Val) -> 720 encode_tags(Tag, encode_integer(C, Val)); 721encode_integer(C,{Name,Val},Tag) when atom(Name) -> 722 encode_integer(C,Val,Tag); 723encode_integer(_C, Val, _Tag) -> 724 exit({error,{asn1, {encode_integer, Val}}}). 725 726 727 728encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) -> 729 case lists:keysearch(Val, 1, NamedNumberList) of 730 {value,{_, NewVal}} -> 731 encode_tags(Tag, encode_integer(C, NewVal)); 732 _ -> 733 exit({error,{asn1, {encode_integer_namednumber, Val}}}) 734 end; 735encode_integer(C,{_Name,Val},NamedNumberList,Tag) -> 736 encode_integer(C,Val,NamedNumberList,Tag); 737encode_integer(C, Val, _NamedNumberList, Tag) -> 738 encode_tags(Tag, encode_integer(C, Val)). 739 740 741encode_integer(_, Val) -> 742 Bytes = 743 if 744 Val >= 0 -> 745 encode_integer_pos(Val, []); 746 true -> 747 encode_integer_neg(Val, []) 748 end, 749 {Bytes,length(Bytes)}. 750 751encode_integer_pos(0, L=[B|_Acc]) when B < 128 -> 752 L; 753encode_integer_pos(N, Acc) -> 754 encode_integer_pos((N bsr 8), [N band 16#ff| Acc]). 755 756encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 -> 757 L; 758encode_integer_neg(N, Acc) -> 759 encode_integer_neg(N bsr 8, [N band 16#ff|Acc]). 760 761%%=============================================================================== 762%% decode integer 763%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 764%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 765%%=============================================================================== 766 767decode_integer(Tlv,Range,NamedNumberList,TagIn) -> 768 V = match_tags(Tlv,TagIn), 769 Int = decode_integer(V), 770 range_check_integer(Int,Range), 771 number2name(Int,NamedNumberList). 772 773decode_integer(Tlv,Range,TagIn) -> 774 V = match_tags(Tlv, TagIn), 775 Int = decode_integer(V), 776 range_check_integer(Int,Range), 777 Int. 778 779%% decoding postitive integer values. 780decode_integer(Bin = <<0:1,_:7,_/binary>>) -> 781 Len = size(Bin), 782% <<Int:Len/unit:8,Buffer2/binary>> = Bin, 783 <<Int:Len/unit:8>> = Bin, 784 Int; 785%% decoding negative integer values. 786decode_integer(Bin = <<1:1,B2:7,Bs/binary>>) -> 787 Len = size(Bin), 788% <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>, 789 <<N:Len/unit:8>> = <<B2,Bs/binary>>, 790 Int = N - (1 bsl (8 * Len - 1)), 791 Int. 792 793range_check_integer(Int,Range) -> 794 case Range of 795 [] -> % No length constraint 796 Int; 797 {Lb,Ub} when Int >= Lb, Ub >= Int -> % variable length constraint 798 Int; 799 Int -> % fixed value constraint 800 Int; 801 {_,_} -> 802 exit({error,{asn1,{integer_range,Range,Int}}}); 803 SingleValue when integer(SingleValue) -> 804 exit({error,{asn1,{integer_range,Range,Int}}}); 805 _ -> % some strange constraint that we don't support yet 806 Int 807 end. 808 809number2name(Int,[]) -> 810 Int; 811number2name(Int,NamedNumberList) -> 812 case lists:keysearch(Int, 2, NamedNumberList) of 813 {value,{NamedVal, _}} -> 814 NamedVal; 815 _ -> 816 Int 817 end. 818 819 820%%============================================================================ 821%% Enumerated value, ITU_T X.690 Chapter 8.4 822 823%% encode enumerated value 824%%============================================================================ 825encode_enumerated(Val, TagIn) when integer(Val)-> 826 encode_tags(TagIn, encode_integer(false,Val)); 827encode_enumerated({Name,Val}, TagIn) when atom(Name) -> 828 encode_enumerated(Val, TagIn). 829 830%% The encode_enumerated functions below this line can be removed when the 831%% new code generation is stable. (the functions might have to be kept here 832%% a while longer for compatibility reasons) 833 834encode_enumerated(C, Val, {NamedNumberList,ExtList}, TagIn) when atom(Val) -> 835 case catch encode_enumerated(C, Val, NamedNumberList, TagIn) of 836 {'EXIT',_} -> encode_enumerated(C, Val, ExtList, TagIn); 837 Result -> Result 838 end; 839 840encode_enumerated(C, Val, NamedNumberList, TagIn) when atom(Val) -> 841 case lists:keysearch(Val, 1, NamedNumberList) of 842 {value, {_, NewVal}} -> 843 encode_tags(TagIn, encode_integer(C, NewVal)); 844 _ -> 845 exit({error,{asn1, {enumerated_not_in_range, Val}}}) 846 end; 847 848encode_enumerated(C, {asn1_enum, Val}, {_,_}, TagIn) when integer(Val) -> 849 encode_tags(TagIn, encode_integer(C,Val)); 850 851encode_enumerated(C, {Name,Val}, NamedNumberList, TagIn) when atom(Name) -> 852 encode_enumerated(C, Val, NamedNumberList, TagIn); 853 854encode_enumerated(_C, Val, _NamedNumberList, _TagIn) -> 855 exit({error,{asn1, {enumerated_not_namednumber, Val}}}). 856 857 858 859%%============================================================================ 860%% decode enumerated value 861%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value 862%%=========================================================================== 863decode_enumerated(Tlv, Range, NamedNumberList, Tags) -> 864 Buffer = match_tags(Tlv,Tags), 865 decode_enumerated_notag(Buffer, Range, NamedNumberList, Tags). 866 867decode_enumerated_notag(Buffer, _Range, {NamedNumberList,ExtList}, _Tags) -> 868 869 IVal = decode_integer2(size(Buffer), Buffer), 870 case decode_enumerated1(IVal, NamedNumberList) of 871 {asn1_enum,IVal} -> 872 decode_enumerated1(IVal,ExtList); 873 EVal -> 874 EVal 875 end; 876decode_enumerated_notag(Buffer, _Range, NNList, _Tags) -> 877 IVal = decode_integer2(size(Buffer), Buffer), 878 case decode_enumerated1(IVal, NNList) of 879 {asn1_enum,_} -> 880 exit({error,{asn1, {illegal_enumerated, IVal}}}); 881 EVal -> 882 EVal 883 end. 884 885decode_enumerated1(Val, NamedNumberList) -> 886 %% it must be a named integer 887 case lists:keysearch(Val, 2, NamedNumberList) of 888 {value,{NamedVal, _}} -> 889 NamedVal; 890 _ -> 891 {asn1_enum,Val} 892 end. 893 894 895%%============================================================================ 896%% 897%% Real value, ITU_T X.690 Chapter 8.5 898%%============================================================================ 899%% 900%% encode real value 901%%============================================================================ 902 903%% only base 2 internally so far!! 904encode_real(0, TagIn) -> 905 encode_tags(TagIn, {[],0}); 906encode_real('PLUS-INFINITY', TagIn) -> 907 encode_tags(TagIn, {[64],1}); 908encode_real('MINUS-INFINITY', TagIn) -> 909 encode_tags(TagIn, {[65],1}); 910encode_real(Val, TagIn) when tuple(Val)-> 911 encode_tags(TagIn, encode_real(Val)). 912 913%%%%%%%%%%%%%% 914%% not optimal efficient.. 915%% only base 2 of Mantissa encoding! 916%% only base 2 of ExpBase encoding! 917encode_real({Man, Base, Exp}) -> 918%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]), 919 920 OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, [])); 921 true -> list_to_binary(encode_integer_neg(Exp, [])) 922 end, 923%% ok = io:format("OctExp: ~w~n",[OctExp]), 924 SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval 925 true -> 1 926 end, 927%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]), 928 InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far! 929 true -> 930 exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}}) 931 end, 932 SFactor = 0, % bit 4,3: no scaling since only base 2 933 OctExpLen = size(OctExp), 934 if OctExpLen > 255 -> 935 exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}}); 936 true -> true %% make real assert later.. 937 end, 938 {LenCode, EOctets} = case OctExpLen of % bit 2,1 939 1 -> {0, OctExp}; 940 2 -> {1, OctExp}; 941 3 -> {2, OctExp}; 942 _ -> {3, <<OctExpLen, OctExp/binary>>} 943 end, 944 FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>, 945 OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man)); 946 true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign 947 end, 948 %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]), 949 Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>, 950 {Bin, size(Bin)}. 951 952 953%%============================================================================ 954%% decode real value 955%% 956%% decode_real([OctetBufferList], tuple|value, tag|notag) -> 957%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0, 958%% RestBuff} 959%% 960%% only for base 2 decoding sofar!! 961%%============================================================================ 962 963decode_real(Tlv, Form, Tags) -> 964 Buffer = match_tags(Tlv,Tags), 965 decode_real_notag(Buffer, Form). 966 967decode_real_notag(_Buffer, _Form) -> 968 exit({error,{asn1, {unimplemented,real}}}). 969%% decode_real2(Buffer, Form, size(Buffer)). 970 971% decode_real2(Buffer, Form, Len) -> 972% <<First, Buffer2/binary>> = Buffer, 973% if 974% First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2}; 975% First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2}; 976% First =:= 2#00000000 -> {0, Buffer2}; 977% true -> 978% %% have some check here to verify only supported bases (2) 979% <<B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>, 980% Sign = B6, 981% Base = 982% case B5_4 of 983% 0 -> 2; % base 2, only one so far 984% _ -> exit({error,{asn1, {non_supported_base, First}}}) 985% end, 986% ScalingFactor = 987% case B3_2 of 988% 0 -> 0; % no scaling so far 989% _ -> exit({error,{asn1, {non_supported_scaling, First}}}) 990% end, 991 992% {FirstLen,Exp,Buffer3} = 993% case B1_0 of 994% 0 -> 995% <<_:1/unit:8,Buffer21/binary>> = Buffer2, 996% {2, decode_integer2(1, Buffer2),Buffer21}; 997% 1 -> 998% <<_:2/unit:8,Buffer21/binary>> = Buffer2, 999% {3, decode_integer2(2, Buffer2)}; 1000% 2 -> 1001% <<_:3/unit:8,Buffer21/binary>> = Buffer2, 1002% {4, decode_integer2(3, Buffer2)}; 1003% 3 -> 1004% <<ExpLen1,RestBuffer/binary>> = Buffer2, 1005% <<_:ExpLen1/unit:8,RestBuffer2/binary>> = RestBuffer, 1006% { ExpLen1 + 2, 1007% decode_integer2(ExpLen1, RestBuffer, RemBytes1), 1008% RestBuffer2} 1009% end, 1010% Length = Len - FirstLen, 1011% <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3, 1012% {Mantissa, Buffer4} = 1013% if Sign =:= 0 -> 1014 1015% {LongInt, RestBuff};% sign plus, 1016% true -> 1017 1018% {-LongInt, RestBuff}% sign minus 1019% end, 1020% case Form of 1021% tuple -> 1022% {Val,Buf,RemB} = Exp, 1023% {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3}; 1024% _value -> 1025% comming 1026% end 1027% end. 1028 1029 1030%%============================================================================ 1031%% Bitstring value, ITU_T X.690 Chapter 8.6 1032%% 1033%% encode bitstring value 1034%% 1035%% bitstring NamedBitList 1036%% Val can be of: 1037%% - [identifiers] where only named identifiers are set to one, 1038%% the Constraint must then have some information of the 1039%% bitlength. 1040%% - [list of ones and zeroes] all bits 1041%% - integer value representing the bitlist 1042%% C is constrint Len, only valid when identifiers 1043%%============================================================================ 1044 1045encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,TagIn) when integer(Unused), binary(BinBits) -> 1046 encode_bin_bit_string(C,Bin,NamedBitList,TagIn); 1047encode_bit_string(C, [FirstVal | RestVal], NamedBitList, TagIn) when atom(FirstVal) -> 1048 encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn); 1049 1050encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, TagIn) -> 1051 encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, TagIn); 1052 1053encode_bit_string(C, [FirstVal| RestVal], NamedBitList, TagIn) when integer(FirstVal) -> 1054 encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, TagIn); 1055 1056encode_bit_string(_C, 0, _NamedBitList, TagIn) -> 1057 encode_tags(TagIn, <<0>>,1); 1058 1059encode_bit_string(_C, [], _NamedBitList, TagIn) -> 1060 encode_tags(TagIn, <<0>>,1); 1061 1062encode_bit_string(C, IntegerVal, NamedBitList, TagIn) when integer(IntegerVal) -> 1063 BitListVal = int_to_bitlist(IntegerVal), 1064 encode_bit_string_bits(C, BitListVal, NamedBitList, TagIn); 1065 1066encode_bit_string(C, {Name,BitList}, NamedBitList, TagIn) when atom(Name) -> 1067 encode_bit_string(C, BitList, NamedBitList, TagIn). 1068 1069 1070 1071int_to_bitlist(0) -> 1072 []; 1073int_to_bitlist(Int) when integer(Int), Int >= 0 -> 1074 [Int band 1 | int_to_bitlist(Int bsr 1)]. 1075 1076 1077%%================================================================= 1078%% Encode BIT STRING of the form {Unused,BinBits}. 1079%% Unused is the number of unused bits in the last byte in BinBits 1080%% and BinBits is a binary representing the BIT STRING. 1081%%================================================================= 1082encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,TagIn)-> 1083 case get_constraint(C,'SizeConstraint') of 1084 no -> 1085 remove_unused_then_dotag(TagIn, Unused, BinBits); 1086 {_Min,Max} -> 1087 BBLen = (size(BinBits)*8)-Unused, 1088 if 1089 BBLen > Max -> 1090 exit({error,{asn1, 1091 {bitstring_length, 1092 {{was,BBLen},{maximum,Max}}}}}); 1093 true -> 1094 remove_unused_then_dotag(TagIn, Unused, BinBits) 1095 end; 1096 Size -> 1097 case ((size(BinBits)*8)-Unused) of 1098 BBSize when BBSize =< Size -> 1099 remove_unused_then_dotag(TagIn, Unused, BinBits); 1100 BBSize -> 1101 exit({error,{asn1, 1102 {bitstring_length, 1103 {{was,BBSize},{should_be,Size}}}}}) 1104 end 1105 end. 1106 1107remove_unused_then_dotag(TagIn,Unused,BinBits) -> 1108 case Unused of 1109 0 when (size(BinBits) == 0) -> 1110 encode_tags(TagIn,<<0>>,1); 1111 0 -> 1112 Bin = <<Unused,BinBits/binary>>, 1113 encode_tags(TagIn,Bin,size(Bin)); 1114 Num -> 1115 N = (size(BinBits)-1), 1116 <<BBits:N/binary,LastByte>> = BinBits, 1117 encode_tags(TagIn, 1118 [Unused,binary_to_list(BBits) ++[(LastByte bsr Num) bsl Num]], 1119 1+size(BinBits)) 1120 end. 1121 1122 1123%%================================================================= 1124%% Encode named bits 1125%%================================================================= 1126 1127encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) -> 1128 ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []), 1129 Size = 1130 case get_constraint(C,'SizeConstraint') of 1131 no -> 1132 lists:max(ToSetPos)+1; 1133 {_Min,Max} -> 1134 Max; 1135 TSize -> 1136 TSize 1137 end, 1138 BitList = make_and_set_list(Size, ToSetPos, 0), 1139 {Len, Unused, OctetList} = encode_bitstring(BitList), 1140 encode_tags(TagIn, [Unused|OctetList],Len+1). 1141 1142 1143%%---------------------------------------- 1144%% get_all_bitposes([list of named bits to set], named_bit_db, []) -> 1145%% [sorted_list_of_bitpositions_to_set] 1146%%---------------------------------------- 1147 1148get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) -> 1149 get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]); 1150get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) -> 1151 case lists:keysearch(Val, 1, NamedBitList) of 1152 {value, {_ValName, ValPos}} -> 1153 get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]); 1154 _ -> 1155 exit({error,{asn1, {bitstring_namedbit, Val}}}) 1156 end; 1157get_all_bitposes([], _NamedBitList, Ack) -> 1158 lists:sort(Ack). 1159 1160 1161%%---------------------------------------- 1162%% make_and_set_list(Len of list to return, [list of positions to set to 1])-> 1163%% returns list of Len length, with all in SetPos set. 1164%% in positioning in list the first element is 0, the second 1 etc.., but 1165%% Len will make a list of length Len, not Len + 1. 1166%% BitList = make_and_set_list(C, ToSetPos, 0), 1167%%---------------------------------------- 1168 1169make_and_set_list(0, [], _) -> []; 1170make_and_set_list(0, _, _) -> 1171 exit({error,{asn1,bitstring_sizeconstraint}}); 1172make_and_set_list(Len, [XPos|SetPos], XPos) -> 1173 [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)]; 1174make_and_set_list(Len, [Pos|SetPos], XPos) -> 1175 [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)]; 1176make_and_set_list(Len, [], XPos) -> 1177 [0 | make_and_set_list(Len - 1, [], XPos + 1)]. 1178 1179 1180 1181 1182 1183 1184%%================================================================= 1185%% Encode bit string for lists of ones and zeroes 1186%%================================================================= 1187encode_bit_string_bits(C, BitListVal, _NamedBitList, TagIn) when list(BitListVal) -> 1188 case get_constraint(C,'SizeConstraint') of 1189 no -> 1190 {Len, Unused, OctetList} = encode_bitstring(BitListVal), 1191 %%add unused byte to the Len 1192 encode_tags(TagIn, [Unused | OctetList], Len+1); 1193 Constr={Min,Max} when integer(Min),integer(Max) -> 1194 encode_constr_bit_str_bits(Constr,BitListVal,TagIn); 1195 {Constr={_,_},[]} ->%Constr={Min,Max} 1196 %% constraint with extension mark 1197 encode_constr_bit_str_bits(Constr,BitListVal,TagIn); 1198 Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}} 1199 %% constraint with extension mark 1200 encode_constr_bit_str_bits(Constr,BitListVal,TagIn); 1201 Size -> 1202 case length(BitListVal) of 1203 BitSize when BitSize == Size -> 1204 {Len, Unused, OctetList} = encode_bitstring(BitListVal), 1205 %%add unused byte to the Len 1206 encode_tags(TagIn, [Unused | OctetList], Len+1); 1207 BitSize when BitSize < Size -> 1208 PaddedList = pad_bit_list(Size-BitSize,BitListVal), 1209 {Len, Unused, OctetList} = encode_bitstring(PaddedList), 1210 %%add unused byte to the Len 1211 encode_tags(TagIn, [Unused | OctetList], Len+1); 1212 BitSize -> 1213 exit({error,{asn1, 1214 {bitstring_length, {{was,BitSize},{should_be,Size}}}}}) 1215 end 1216 1217 end. 1218 1219encode_constr_bit_str_bits({_Min,Max},BitListVal,TagIn) -> 1220 BitLen = length(BitListVal), 1221 if 1222 BitLen > Max -> 1223 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1224 {maximum,Max}}}}}); 1225 true -> 1226 {Len, Unused, OctetList} = encode_bitstring(BitListVal), 1227 %%add unused byte to the Len 1228 encode_tags(TagIn, [Unused, OctetList], Len+1) 1229 end; 1230encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,TagIn) -> 1231 BitLen = length(BitListVal), 1232 case BitLen of 1233 Len when Len > Max2 -> 1234 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1235 {maximum,Max2}}}}}); 1236 Len when Len > Max1, Len < Min2 -> 1237 exit({error,{asn1,{bitstring_length,{{was,BitLen}, 1238 {not_allowed_interval, 1239 Max1,Min2}}}}}); 1240 _ -> 1241 {Len, Unused, OctetList} = encode_bitstring(BitListVal), 1242 %%add unused byte to the Len 1243 encode_tags(TagIn, [Unused, OctetList], Len+1) 1244 end. 1245 1246%% returns a list of length Size + length(BitListVal), with BitListVal 1247%% as the most significant elements followed by padded zero elements 1248pad_bit_list(Size,BitListVal) -> 1249 Tail = lists:duplicate(Size,0), 1250 lists:append(BitListVal,Tail). 1251 1252%%================================================================= 1253%% Do the actual encoding 1254%% ([bitlist]) -> {ListLen, UnusedBits, OctetList} 1255%%================================================================= 1256 1257encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) -> 1258 Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor 1259 (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1, 1260 encode_bitstring(Rest, [Val], 1); 1261encode_bitstring(Val) -> 1262 {Unused, Octet} = unused_bitlist(Val, 7, 0), 1263 {1, Unused, [Octet]}. 1264 1265encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) -> 1266 Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor 1267 (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1, 1268 encode_bitstring(Rest, [Ack | [Val]], Len + 1); 1269%%even multiple of 8 bits.. 1270encode_bitstring([], Ack, Len) -> 1271 {Len, 0, Ack}; 1272%% unused bits in last octet 1273encode_bitstring(Rest, Ack, Len) -> 1274% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]), 1275 {Unused, Val} = unused_bitlist(Rest, 7, 0), 1276 {Len + 1, Unused, [Ack | [Val]]}. 1277 1278%%%%%%%%%%%%%%%%%% 1279%% unused_bitlist([list of ones and zeros <= 7], 7, []) -> 1280%% {Unused bits, Last octet with bits moved to right} 1281unused_bitlist([], Trail, Ack) -> 1282 {Trail + 1, Ack}; 1283unused_bitlist([Bit | Rest], Trail, Ack) -> 1284%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]), 1285 unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack). 1286 1287 1288%%============================================================================ 1289%% decode bitstring value 1290%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes} 1291%%============================================================================ 1292 1293decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags) -> 1294% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}), 1295 decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, 1296 NamedNumberList,bin). 1297 1298decode_bit_string(Buffer, Range, NamedNumberList, Tags) -> 1299% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}), 1300 decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, 1301 NamedNumberList,old). 1302 1303 1304decode_bit_string2(<<0>>,_NamedNumberList,BinOrOld) -> 1305 case BinOrOld of 1306 bin -> 1307 {0,<<>>}; 1308 _ -> 1309 [] 1310 end; 1311decode_bit_string2(<<Unused,Bits/binary>>,NamedNumberList,BinOrOld) -> 1312 case NamedNumberList of 1313 [] -> 1314 case BinOrOld of 1315 bin -> 1316 {Unused,Bits}; 1317 _ -> 1318 decode_bitstring2(size(Bits), Unused, Bits) 1319 end; 1320 _ -> 1321 BitString = decode_bitstring2(size(Bits), Unused, Bits), 1322 decode_bitstring_NNL(BitString,NamedNumberList) 1323 end. 1324 1325%%---------------------------------------- 1326%% Decode the in buffer to bits 1327%%---------------------------------------- 1328decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) -> 1329 lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused); 1330decode_bitstring2(Len, Unused, 1331 <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) -> 1332 [B7, B6, B5, B4, B3, B2, B1, B0 | 1333 decode_bitstring2(Len - 1, Unused, Buffer)]. 1334 1335%%decode_bitstring2(1, Unused, Buffer) -> 1336%% make_bits_of_int(hd(Buffer), 128, 8-Unused); 1337%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) -> 1338%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8), 1339%% [B7, B6, B5, B4, B3, B2, B1, B0 | 1340%% decode_bitstring2(Len - 1, Unused, Buffer)]. 1341 1342 1343%%make_bits_of_int(_, _, 0) -> 1344%% []; 1345%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 -> 1346%% X = case MaskVal band BitVal of 1347%% 0 -> 0 ; 1348%% _ -> 1 1349%% end, 1350%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)]. 1351 1352 1353 1354%%---------------------------------------- 1355%% Decode the bitlist to names 1356%%---------------------------------------- 1357 1358 1359decode_bitstring_NNL(BitList,NamedNumberList) -> 1360 decode_bitstring_NNL(BitList,NamedNumberList,0,[]). 1361 1362 1363decode_bitstring_NNL([],_,_No,Result) -> 1364 lists:reverse(Result); 1365 1366decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) -> 1367 if 1368 B == 0 -> 1369 decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result); 1370 true -> 1371 decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result]) 1372 end; 1373decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) -> 1374 decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]); 1375decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) -> 1376 decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result). 1377 1378 1379%%============================================================================ 1380%% Octet string, ITU_T X.690 Chapter 8.7 1381%% 1382%% encode octet string 1383%% The OctetList must be a flat list of integers in the range 0..255 1384%% the function does not check this because it takes to much time 1385%%============================================================================ 1386encode_octet_string(_C, OctetList, TagIn) when binary(OctetList) -> 1387 encode_tags(TagIn, OctetList, size(OctetList)); 1388encode_octet_string(_C, OctetList, TagIn) when list(OctetList) -> 1389 encode_tags(TagIn, OctetList, length(OctetList)); 1390encode_octet_string(C, {Name,OctetList}, TagIn) when atom(Name) -> 1391 encode_octet_string(C, OctetList, TagIn). 1392 1393 1394%%============================================================================ 1395%% decode octet string 1396%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1397%% 1398%% Octet string is decoded as a restricted string 1399%%============================================================================ 1400decode_octet_string(Buffer, Range, Tags) -> 1401% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}), 1402 decode_restricted_string(Buffer, Range, ?N_OCTET_STRING, 1403 Tags, [], old). 1404 1405%%============================================================================ 1406%% Null value, ITU_T X.690 Chapter 8.8 1407%% 1408%% encode NULL value 1409%%============================================================================ 1410 1411encode_null({Name, _Val}, TagIn) when atom(Name) -> 1412 encode_tags(TagIn, [], 0); 1413encode_null(_Val, TagIn) -> 1414 encode_tags(TagIn, [], 0). 1415 1416%%============================================================================ 1417%% decode NULL value 1418%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes} 1419%%============================================================================ 1420 1421decode_null(Tlv, Tags) -> 1422 Val = match_tags(Tlv, Tags), 1423 case Val of 1424 <<>> -> 1425 'NULL'; 1426 _ -> 1427 exit({error,{asn1,{decode_null,Val}}}) 1428 end. 1429 1430%%============================================================================ 1431%% Object identifier, ITU_T X.690 Chapter 8.19 1432%% 1433%% encode Object Identifier value 1434%%============================================================================ 1435 1436encode_object_identifier({Name,Val}, TagIn) when atom(Name) -> 1437 encode_object_identifier(Val, TagIn); 1438encode_object_identifier(Val, TagIn) -> 1439 encode_tags(TagIn, e_object_identifier(Val)). 1440 1441e_object_identifier({'OBJECT IDENTIFIER', V}) -> 1442 e_object_identifier(V); 1443e_object_identifier({Cname, V}) when atom(Cname), tuple(V) -> 1444 e_object_identifier(tuple_to_list(V)); 1445e_object_identifier({Cname, V}) when atom(Cname), list(V) -> 1446 e_object_identifier(V); 1447e_object_identifier(V) when tuple(V) -> 1448 e_object_identifier(tuple_to_list(V)); 1449 1450%%%%%%%%%%%%%%% 1451%% e_object_identifier([List of Obect Identifiers]) -> 1452%% {[Encoded Octetlist of ObjIds], IntLength} 1453%% 1454e_object_identifier([E1, E2 | Tail]) -> 1455 Head = 40*E1 + E2, % wow! 1456 {H,Lh} = mk_object_val(Head), 1457 {R,Lr} = enc_obj_id_tail(Tail, [], 0), 1458 {[H|R], Lh+Lr}. 1459 1460enc_obj_id_tail([], Ack, Len) -> 1461 {lists:reverse(Ack), Len}; 1462enc_obj_id_tail([H|T], Ack, Len) -> 1463 {B, L} = mk_object_val(H), 1464 enc_obj_id_tail(T, [B|Ack], Len+L). 1465 1466%% e_object_identifier([List of Obect Identifiers]) -> 1467%% {[Encoded Octetlist of ObjIds], IntLength} 1468%% 1469%%e_object_identifier([E1, E2 | Tail]) -> 1470%% Head = 40*E1 + E2, % wow! 1471%% F = fun(Val, AckLen) -> 1472%% {L, Ack} = mk_object_val(Val), 1473%% {L, Ack + AckLen} 1474%% end, 1475%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]). 1476 1477%%%%%%%%%%% 1478%% mk_object_val(Value) -> {OctetList, Len} 1479%% returns a Val as a list of octets, the 8 bit is allways set to one except 1480%% for the last octet, where its 0 1481%% 1482 1483 1484mk_object_val(Val) when Val =< 127 -> 1485 {[255 band Val], 1}; 1486mk_object_val(Val) -> 1487 mk_object_val(Val bsr 7, [Val band 127], 1). 1488mk_object_val(0, Ack, Len) -> 1489 {Ack, Len}; 1490mk_object_val(Val, Ack, Len) -> 1491 mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1). 1492 1493 1494 1495%%============================================================================ 1496%% decode Object Identifier value 1497%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes} 1498%%============================================================================ 1499 1500decode_object_identifier(Tlv, Tags) -> 1501 Val = match_tags(Tlv, Tags), 1502 [AddedObjVal|ObjVals] = dec_subidentifiers(Val,0,[]), 1503 {Val1, Val2} = if 1504 AddedObjVal < 40 -> 1505 {0, AddedObjVal}; 1506 AddedObjVal < 80 -> 1507 {1, AddedObjVal - 40}; 1508 true -> 1509 {2, AddedObjVal - 80} 1510 end, 1511 list_to_tuple([Val1, Val2 | ObjVals]). 1512 1513dec_subidentifiers(<<>>,_Av,Al) -> 1514 lists:reverse(Al); 1515dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) -> 1516 dec_subidentifiers(T,(Av bsl 7) + H,Al); 1517dec_subidentifiers(<<H,T/binary>>,Av,Al) -> 1518 dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]). 1519 1520 1521%%============================================================================ 1522%% Restricted character string types, ITU_T X.690 Chapter 8.20 1523%% 1524%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings 1525%%============================================================================ 1526%% The StringType arg is kept for future use but might be removed 1527encode_restricted_string(_C, OctetList, _StringType, TagIn) 1528 when binary(OctetList) -> 1529 encode_tags(TagIn, OctetList, size(OctetList)); 1530encode_restricted_string(_C, OctetList, _StringType, TagIn) 1531 when list(OctetList) -> 1532 encode_tags(TagIn, OctetList, length(OctetList)); 1533encode_restricted_string(C,{Name,OctetL}, StringType, TagIn) when atom(Name)-> 1534 encode_restricted_string(C, OctetL, StringType, TagIn). 1535 1536%%============================================================================ 1537%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings 1538%% (Buffer, Range, StringType, HasTag, TotalLen) -> 1539%% {String, Remain, RemovedBytes} 1540%%============================================================================ 1541 1542decode_restricted_string(Buffer, Range, StringType, Tags) -> 1543 decode_restricted_string(Buffer, Range, StringType, Tags, [], old). 1544 1545 1546decode_restricted_string(Tlv, Range, StringType, TagsIn, 1547 NamedNumberList, BinOrOld) -> 1548 Val = match_tags(Tlv, TagsIn), 1549 Val2 = 1550 case Val of 1551 PartList = [_H|_T] -> % constructed val 1552 Bin = collect_parts(PartList), 1553 decode_restricted(Bin, StringType, 1554 NamedNumberList, BinOrOld); 1555 Bin -> 1556 decode_restricted(Bin, StringType, 1557 NamedNumberList, BinOrOld) 1558 end, 1559 check_and_convert_restricted_string(Val2,StringType,Range,NamedNumberList,BinOrOld). 1560 1561 1562 1563% case StringType of 1564% ?N_BIT_STRING when BinOrOld == bin -> 1565% {concat_bit_binaries(AccVal, Val), AccRb+Rb}; 1566% _ when binary(Val),binary(AccVal) -> 1567% {<<AccVal/binary,Val/binary>>,AccRb+Rb}; 1568% _ when binary(Val), AccVal==[] -> 1569% {Val,AccRb+Rb}; 1570% _ -> 1571% {AccVal++Val, AccRb+Rb} 1572% end, 1573 1574 1575 1576decode_restricted(Bin, StringType, NamedNumberList,BinOrOld) -> 1577 case StringType of 1578 ?N_BIT_STRING -> 1579 decode_bit_string2(Bin, NamedNumberList, BinOrOld); 1580 ?N_UniversalString -> 1581 mk_universal_string(binary_to_list(Bin)); 1582 ?N_BMPString -> 1583 mk_BMP_string(binary_to_list(Bin)); 1584 _ -> 1585 Bin 1586 end. 1587 1588 1589check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) -> 1590 {StrLen,NewVal} = case StringType of 1591 ?N_BIT_STRING when NamedNumberList /= [] -> 1592 {no_check,Val}; 1593 ?N_BIT_STRING when list(Val) -> 1594 {length(Val),Val}; 1595 ?N_BIT_STRING when tuple(Val) -> 1596 {(size(element(2,Val))*8) - element(1,Val),Val}; 1597 _ when binary(Val) -> 1598 {size(Val),binary_to_list(Val)}; 1599 _ when list(Val) -> 1600 {length(Val), Val} 1601 end, 1602 case Range of 1603 _ when StrLen == no_check -> 1604 NewVal; 1605 [] -> % No length constraint 1606 NewVal; 1607 {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint 1608 NewVal; 1609 {{Lb,_Ub},[]} when StrLen >= Lb -> 1610 NewVal; 1611 {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1; 1612 StrLen =< Ub2, StrLen >= Lb2 -> 1613 NewVal; 1614 StrLen -> % fixed length constraint 1615 NewVal; 1616 {_,_} -> 1617 exit({error,{asn1,{length,Range,Val}}}); 1618 _Len when integer(_Len) -> 1619 exit({error,{asn1,{length,Range,Val}}}); 1620 _ -> % some strange constraint that we don't support yet 1621 NewVal 1622 end. 1623 1624 1625%%============================================================================ 1626%% encode Universal string 1627%%============================================================================ 1628 1629encode_universal_string(C, {Name, Universal}, TagIn) when atom(Name) -> 1630 encode_universal_string(C, Universal, TagIn); 1631encode_universal_string(_C, Universal, TagIn) -> 1632 OctetList = mk_uni_list(Universal), 1633 encode_tags(TagIn, OctetList, length(OctetList)). 1634 1635mk_uni_list(In) -> 1636 mk_uni_list(In,[]). 1637 1638mk_uni_list([],List) -> 1639 lists:reverse(List); 1640mk_uni_list([{A,B,C,D}|T],List) -> 1641 mk_uni_list(T,[D,C,B,A|List]); 1642mk_uni_list([H|T],List) -> 1643 mk_uni_list(T,[H,0,0,0|List]). 1644 1645%%=========================================================================== 1646%% decode Universal strings 1647%% (Buffer, Range, StringType, HasTag, LenIn) -> 1648%% {String, Remain, RemovedBytes} 1649%%=========================================================================== 1650 1651decode_universal_string(Buffer, Range, Tags) -> 1652 decode_restricted_string(Buffer, Range, ?N_UniversalString, 1653 Tags, [], old). 1654 1655 1656mk_universal_string(In) -> 1657 mk_universal_string(In,[]). 1658 1659mk_universal_string([],Acc) -> 1660 lists:reverse(Acc); 1661mk_universal_string([0,0,0,D|T],Acc) -> 1662 mk_universal_string(T,[D|Acc]); 1663mk_universal_string([A,B,C,D|T],Acc) -> 1664 mk_universal_string(T,[{A,B,C,D}|Acc]). 1665 1666 1667%%============================================================================ 1668%% encode BMP string 1669%%============================================================================ 1670 1671encode_BMP_string(C, {Name,BMPString}, TagIn) when atom(Name)-> 1672 encode_BMP_string(C, BMPString, TagIn); 1673encode_BMP_string(_C, BMPString, TagIn) -> 1674 OctetList = mk_BMP_list(BMPString), 1675 encode_tags(TagIn, OctetList, length(OctetList)). 1676 1677mk_BMP_list(In) -> 1678 mk_BMP_list(In,[]). 1679 1680mk_BMP_list([],List) -> 1681 lists:reverse(List); 1682mk_BMP_list([{0,0,C,D}|T],List) -> 1683 mk_BMP_list(T,[D,C|List]); 1684mk_BMP_list([H|T],List) -> 1685 mk_BMP_list(T,[H,0|List]). 1686 1687%%============================================================================ 1688%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList} 1689%% (Buffer, Range, StringType, HasTag, TotalLen) -> 1690%% {String, Remain, RemovedBytes} 1691%%============================================================================ 1692decode_BMP_string(Buffer, Range, Tags) -> 1693 decode_restricted_string(Buffer, Range, ?N_BMPString, 1694 Tags, [], old). 1695 1696mk_BMP_string(In) -> 1697 mk_BMP_string(In,[]). 1698 1699mk_BMP_string([],US) -> 1700 lists:reverse(US); 1701mk_BMP_string([0,B|T],US) -> 1702 mk_BMP_string(T,[B|US]); 1703mk_BMP_string([C,D|T],US) -> 1704 mk_BMP_string(T,[{0,0,C,D}|US]). 1705 1706 1707%%============================================================================ 1708%% Generalized time, ITU_T X.680 Chapter 39 1709%% 1710%% encode Generalized time 1711%%============================================================================ 1712 1713encode_generalized_time(C, {Name,OctetList}, TagIn) when atom(Name) -> 1714 encode_generalized_time(C, OctetList, TagIn); 1715encode_generalized_time(_C, OctetList, TagIn) -> 1716 encode_tags(TagIn, OctetList, length(OctetList)). 1717 1718%%============================================================================ 1719%% decode Generalized time 1720%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1721%%============================================================================ 1722 1723decode_generalized_time(Tlv, _Range, Tags) -> 1724 Val = match_tags(Tlv, Tags), 1725 NewVal = case Val of 1726 PartList = [_H|_T] -> % constructed 1727 collect_parts(PartList); 1728 Bin -> 1729 Bin 1730 end, 1731 binary_to_list(NewVal). 1732 1733%%============================================================================ 1734%% Universal time, ITU_T X.680 Chapter 40 1735%% 1736%% encode UTC time 1737%%============================================================================ 1738 1739encode_utc_time(C, {Name,OctetList}, TagIn) when atom(Name) -> 1740 encode_utc_time(C, OctetList, TagIn); 1741encode_utc_time(_C, OctetList, TagIn) -> 1742 encode_tags(TagIn, OctetList, length(OctetList)). 1743 1744%%============================================================================ 1745%% decode UTC time 1746%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes} 1747%%============================================================================ 1748 1749decode_utc_time(Tlv, _Range, Tags) -> 1750 Val = match_tags(Tlv, Tags), 1751 NewVal = case Val of 1752 PartList = [_H|_T] -> % constructed 1753 collect_parts(PartList); 1754 Bin -> 1755 Bin 1756 end, 1757 binary_to_list(NewVal). 1758 1759 1760%%============================================================================ 1761%% Length handling 1762%% 1763%% Encode length 1764%% 1765%% encode_length(Int | indefinite) -> 1766%% [<127]| [128 + Int (<127),OctetList] | [16#80] 1767%%============================================================================ 1768 1769encode_length(indefinite) -> 1770 {[16#80],1}; % 128 1771encode_length(L) when L =< 16#7F -> 1772 {[L],1}; 1773encode_length(L) -> 1774 Oct = minimum_octets(L), 1775 Len = length(Oct), 1776 if 1777 Len =< 126 -> 1778 {[ (16#80+Len) | Oct ],Len+1}; 1779 true -> 1780 exit({error,{asn1, to_long_length_oct, Len}}) 1781 end. 1782 1783 1784%% Val must be >= 0 1785minimum_octets(Val) -> 1786 minimum_octets(Val,[]). 1787 1788minimum_octets(0,Acc) -> 1789 Acc; 1790minimum_octets(Val, Acc) -> 1791 minimum_octets((Val bsr 8),[Val band 16#FF | Acc]). 1792 1793 1794%%=========================================================================== 1795%% Decode length 1796%% 1797%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} | 1798%% {{Length, RestOctetsL}, NoRemovedBytes} 1799%%=========================================================================== 1800 1801decode_length(<<1:1,0:7,T/binary>>) -> 1802 {indefinite, T}; 1803decode_length(<<0:1,Length:7,T/binary>>) -> 1804 {Length,T}; 1805decode_length(<<1:1,LL:7,T/binary>>) -> 1806 <<Length:LL/unit:8,Rest/binary>> = T, 1807 {Length,Rest}. 1808 1809 1810 1811%%------------------------------------------------------------------------- 1812%% INTERNAL HELPER FUNCTIONS (not exported) 1813%%------------------------------------------------------------------------- 1814 1815 1816%% decoding postitive integer values. 1817decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>) -> 1818 <<Int:Len/unit:8>> = Bin, 1819 Int; 1820%% decoding negative integer values. 1821decode_integer2(Len,<<1:1,B2:7,Bs/binary>>) -> 1822 <<N:Len/unit:8>> = <<B2,Bs/binary>>, 1823 Int = N - (1 bsl (8 * Len - 1)), 1824 Int. 1825 1826get_constraint(C,Key) -> 1827 case lists:keysearch(Key,1,C) of 1828 false -> 1829 no; 1830 {value,{_,V}} -> 1831 V 1832 end. 1833 1834collect_parts(TlvList) -> 1835 collect_parts(TlvList,[]). 1836 1837collect_parts([{_,L}|Rest],Acc) when list(L) -> 1838 collect_parts(Rest,[collect_parts(L)|Acc]); 1839collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],_Acc) -> 1840 collect_parts_bit(Rest,[Bits],Unused); 1841collect_parts([{_T,V}|Rest],Acc) -> 1842 collect_parts(Rest,[V|Acc]); 1843collect_parts([],Acc) -> 1844 list_to_binary(lists:reverse(Acc)). 1845 1846collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) -> 1847 collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc); 1848collect_parts_bit([],Acc,Uacc) -> 1849 list_to_binary([Uacc|lists:reverse(Acc)]). 1850