diff options
Diffstat (limited to 'lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl')
-rw-r--r-- | lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl | 1609 |
1 files changed, 0 insertions, 1609 deletions
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl deleted file mode 100644 index d531a165ae..0000000000 --- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl +++ /dev/null @@ -1,1609 +0,0 @@ -%% ``The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved via the world wide web at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% -%% $Id: asn1rt_per.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $ -%% --module(asn1rt_per). - -%% encoding / decoding of PER aligned - --include("asn1_records.hrl"). - --export([dec_fixup/3, cindex/3, list_to_record/2]). --export([setchoiceext/1, setext/1, fixoptionals/2, fixextensions/2, setoptionals/1, - getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]). --export([getoptionals/3, set_choice/3, encode_integer/2, encode_integer/3 ]). --export([decode_integer/2, decode_integer/3, encode_boolean/1, - decode_boolean/1, encode_length/2, decode_length/1, decode_length/2, - encode_small_length/1, decode_small_length/1]). --export([encode_enumerated/3, decode_enumerated/3, - encode_bit_string/3, decode_bit_string/3 ]). --export([encode_octet_string/2, decode_octet_string/2, - encode_restricted_string/4, encode_restricted_string/5, - decode_restricted_string/4, decode_restricted_string/5, - encode_null/1, decode_null/1, - encode_object_identifier/1, decode_object_identifier/1, - complete/1]). - --export([encode_open_type/2, decode_open_type/2]). - --export([encode_UniversalString/2, decode_UniversalString/2, - encode_PrintableString/2, decode_PrintableString/2, - encode_GeneralString/2, decode_GeneralString/2, - encode_GraphicString/2, decode_GraphicString/2, - encode_TeletexString/2, decode_TeletexString/2, - encode_VideotexString/2, decode_VideotexString/2, - encode_VisibleString/2, decode_VisibleString/2, - encode_BMPString/2, decode_BMPString/2, - encode_IA5String/2, decode_IA5String/2, - encode_NumericString/2, decode_NumericString/2 - ]). - - -dec_fixup(Terms,Cnames,RemBytes) -> - dec_fixup(Terms,Cnames,RemBytes,[]). - -dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) -> - dec_fixup(T,Tc,RemBytes,Acc); -dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) -> - dec_fixup(T,Tc,RemBytes,Acc); -dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) -> - dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]); -dec_fixup([],_Cnames,RemBytes,Acc) -> - {lists:reverse(Acc),RemBytes}. - -cindex(Ix,Val,Cname) -> - case element(Ix,Val) of - {Cname,Val2} -> Val2; - X -> X - end. - -% converts a list to a record if necessary -list_to_record(Name,List) when list(List) -> - list_to_tuple([Name|List]); -list_to_record(_Name,Tuple) when tuple(Tuple) -> - Tuple. - -%%-------------------------------------------------------- -%% setchoiceext(InRootSet) -> [{bit,X}] -%% X is set to 1 when InRootSet==false -%% X is set to 0 when InRootSet==true -%% -setchoiceext(true) -> - [{debug,choiceext},{bit,0}]; -setchoiceext(false) -> - [{debug,choiceext},{bit,1}]. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% setext(true|false) -> CompleteList -%% - -setext(true) -> - [{debug,ext},{bit,1}]; -setext(false) -> - [{debug,ext},{bit,0}]. - -fixoptionals(OptList,Val) when tuple(Val) -> - fixoptionals(OptList,Val,[]); - -fixoptionals(OptList,Val) when list(Val) -> - fixoptionals(OptList,Val,1,[],[]). - -fixoptionals([],Val,Acc) -> - % return {Val,Opt} - {Val,lists:reverse(Acc)}; -fixoptionals([{_,Pos}|Ot],Val,Acc) -> - case element(Pos+1,Val) of - asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]); - asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]); - _ -> fixoptionals(Ot,Val,[1|Acc]) - end. - - -%setoptionals(OptList,Val) -> -% Vlist = tuple_to_list(Val), -% setoptionals(OptList,Vlist,1,[]). - -fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) -> - fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]); -fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) -> - fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]); -fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) -> - fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]); -fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) -> - fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]); -fixoptionals([],[],_,Acc1,Acc2) -> - % return {Val,Opt} - {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}. - -setoptionals([H|T]) -> - [{bit,H}|setoptionals(T)]; -setoptionals([]) -> - [{debug,optionals}]. - -getext(Bytes) when tuple(Bytes) -> - getbit(Bytes); -getext(Bytes) when list(Bytes) -> - getbit({0,Bytes}). - -getextension(0, Bytes) -> - {{},Bytes}; -getextension(1, Bytes) -> - {Len,Bytes2} = decode_small_length(Bytes), - {Blist, Bytes3} = getbits_as_list(Len,Bytes2), - {list_to_tuple(Blist),Bytes3}. - -fixextensions({ext,ExtPos,ExtNum},Val) -> - case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of - 0 -> []; - ExtBits -> - [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}] - end. - -fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos -> - Acc; -fixextensions(Pos,ExtPos,Val,Acc) -> - Bit = case catch(element(Pos+1,Val)) of - asn1_NOVALUE -> - 0; - asn1_NOEXTVALUE -> - 0; - {'EXIT',_} -> - 0; - _ -> - 1 - end, - fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit). - -skipextensions(Bytes,Nr,ExtensionBitPattern) -> - case (catch element(Nr,ExtensionBitPattern)) of - 1 -> - {_,Bytes2} = decode_open_type(Bytes,[]), - skipextensions(Bytes2, Nr+1, ExtensionBitPattern); - 0 -> - skipextensions(Bytes, Nr+1, ExtensionBitPattern); - {'EXIT',_} -> % badarg, no more extensions - Bytes - end. - - -getchoice(Bytes,1,0) -> % only 1 alternative is not encoded - {0,Bytes}; -getchoice(Bytes,_NumChoices,1) -> - decode_small_number(Bytes); -getchoice(Bytes,NumChoices,0) -> - decode_integer(Bytes,[{'ValueRange',{0,NumChoices-1}}]). - -getoptionals(Bytes,L,NumComp) when list(L) -> - {Blist,Bytes1} = getbits_as_list(length(L),Bytes), - {list_to_tuple(comptuple(Blist,L,NumComp,1)),Bytes1}. - -comptuple([Bh|Bt],[{_Name,Nr}|T],NumComp,Nr) -> - [Bh|comptuple(Bt,T,NumComp-1,Nr+1)]; -comptuple(Bl,[{Name,Tnr}|Tl],NumComp,Nr) -> - [0|comptuple(Bl,[{Name,Tnr}|Tl],NumComp-1,Nr+1)]; -comptuple(_B,_L,0,_Nr) -> - []; -comptuple(B,O,N,Nr) -> - [0|comptuple(B,O,N-1,Nr+1)]. - -getbits_as_list(Num,Bytes) -> - getbits_as_list(Num,Bytes,[]). - -getbits_as_list(0,Bytes,Acc) -> - {lists:reverse(Acc),Bytes}; -getbits_as_list(Num,Bytes,Acc) -> - {Bit,NewBytes} = getbit(Bytes), - getbits_as_list(Num-1,NewBytes,[Bit|Acc]). - -getbit(Bytes) -> -% io:format("getbit:~p~n",[Bytes]), - getbit1(Bytes). - -getbit1({7,[H|T]}) -> - {H band 1,{0,T}}; -getbit1({Pos,[H|T]}) -> - {(H bsr (7-Pos)) band 1,{(Pos+1) rem 8,[H|T]}}; -getbit1(Bytes) when list(Bytes) -> - getbit1({0,Bytes}). - -%% This could be optimized -getbits(Buffer,Num) -> -% io:format("getbits:Buffer = ~p~nNum=~p~n",[Buffer,Num]), - getbits(Buffer,Num,0). - -getbits(Buffer,0,Acc) -> - {Acc,Buffer}; -getbits(Buffer,Num,Acc) -> - {B,NewBuffer} = getbit(Buffer), - getbits(NewBuffer,Num-1,B + (Acc bsl 1)). - - -getoctet(Bytes) when list(Bytes) -> - getoctet({0,Bytes}); -getoctet(Bytes) -> -% io:format("getoctet:Buffer = ~p~n",[Bytes]), - getoctet1(Bytes). - -getoctet1({0,[H|T]}) -> - {H,{0,T}}; -getoctet1({_Pos,[_,H|T]}) -> - {H,{0,T}}. - -align({0,L}) -> - {0,L}; -align({_Pos,[_H|T]}) -> - {0,T}; -align(Bytes) -> - {0,Bytes}. - -getoctets(Buffer,Num) -> -% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]), - getoctets(Buffer,Num,0). - -getoctets(Buffer,0,Acc) -> - {Acc,Buffer}; -getoctets(Buffer,Num,Acc) -> - {Oct,NewBuffer} = getoctet(Buffer), - getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct). - -getoctets_as_list(Buffer,Num) -> - getoctets_as_list(Buffer,Num,[]). - -getoctets_as_list(Buffer,0,Acc) -> - {lists:reverse(Acc),Buffer}; -getoctets_as_list(Buffer,Num,Acc) -> - {Oct,NewBuffer} = getoctet(Buffer), - getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings -%% Alt = atom() -%% Altnum = integer() | {integer(),integer()}% number of alternatives -%% Choices = [atom()] | {[atom()],[atom()]} -%% When Choices is a tuple the first list is the Rootset and the -%% second is the Extensions and then Altnum must also be a tuple with the -%% lengths of the 2 lists -%% -set_choice(Alt,{L1,L2},{Len1,_Len2}) -> - case set_choice_tag(Alt,L1) of - N when integer(N), Len1 > 1 -> - [{bit,0}, % the value is in the root set - encode_integer([{'ValueRange',{0,Len1-1}}],N)]; - N when integer(N) -> - [{bit,0}]; % no encoding if only 0 or 1 alternative - false -> - [{bit,1}, % extension value - case set_choice_tag(Alt,L2) of - N2 when integer(N2) -> - encode_small_number(N2); - false -> - unknown_choice_alt - end] - end; -set_choice(Alt,L,Len) -> - case set_choice_tag(Alt,L) of - N when integer(N), Len > 1 -> - encode_integer([{'ValueRange',{0,Len-1}}],N); - N when integer(N) -> - []; % no encoding if only 0 or 1 alternative - false -> - [unknown_choice_alt] - end. - -set_choice_tag(Alt,Choices) -> - set_choice_tag(Alt,Choices,0). - -set_choice_tag(Alt,[Alt|_Rest],Tag) -> - Tag; -set_choice_tag(Alt,[_H|Rest],Tag) -> - set_choice_tag(Alt,Rest,Tag+1); -set_choice_tag(_,[],_) -> - false. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% encode_open_type(Constraint, Value) -> CompleteList -%% Value = list of bytes of an already encoded value (the list must be flat) -%% | binary -%% Contraint = not used in this version -%% -encode_open_type(_Constraint, Val) when list(Val) -> - [encode_length(undefined,length(Val)),align, - {octets,Val}]; -encode_open_type(_Constraint, Val) when binary(Val) -> - [encode_length(undefined,size(Val)),align, - {octets,binary_to_list(Val)}]. -%% the binary_to_list is not optimal but compatible with the current solution - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% decode_open_type(Buffer,Constraint) -> Value -%% Constraint is not used in this version -%% Buffer = [byte] with PER encoded data -%% Value = [byte] with decoded data (which must be decoded again as some type) -%% -decode_open_type(Bytes, _Constraint) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - Bytes3 = align(Bytes2), - getoctets_as_list(Bytes3,Len). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList -%% encode_integer(Constraint,Value) -> CompleteList -%% encode_integer(Constraint,{Name,Value}) -> CompleteList -%% -%% -encode_integer(C,V,NamedNumberList) when atom(V) -> - case lists:keysearch(V,1,NamedNumberList) of - {value,{_,NewV}} -> - encode_integer(C,NewV); - _ -> - exit({error,{asn1,{namednumber,V}}}) - end; -encode_integer(C,V,_NamedNumberList) when integer(V) -> - encode_integer(C,V). - -encode_integer(C,{Name,Val}) when atom(Name) -> - encode_integer(C,Val); - -encode_integer({Rc,_Ec},Val) -> - case (catch encode_integer(Rc,Val)) of - {'EXIT',{error,{asn1,_}}} -> - [{bit,1},encode_unconstrained_number(Val)]; - Encoded -> - [{bit,0},Encoded] - end; -encode_integer(C,Val ) when list(C) -> - case get_constraint(C,'SingleValue') of - no -> - encode_integer1(C,Val); - V when integer(V),V == Val -> - []; % a type restricted to a single value encodes to nothing - V when list(V) -> - case lists:member(Val,V) of - true -> - encode_integer1(C,Val); - _ -> - exit({error,{asn1,{illegal_value,Val}}}) - end; - _ -> - exit({error,{asn1,{illegal_value,Val}}}) - end. - -encode_integer1(C, Val) -> - case VR = get_constraint(C,'ValueRange') of - no -> - encode_unconstrained_number(Val); - {Lb,'MAX'} -> - encode_semi_constrained_number(Lb,Val); - %% positive with range - {Lb,Ub} when Val >= Lb, - Ub >= Val -> - encode_constrained_number(VR,Val) - end. - -decode_integer(Buffer,Range,NamedNumberList) -> - {Val,Buffer2} = decode_integer(Buffer,Range), - case lists:keysearch(Val,2,NamedNumberList) of - {value,{NewVal,_}} -> {NewVal,Buffer2}; - _ -> {Val,Buffer2} - end. - -decode_integer(Buffer,{Rc,_Ec}) -> - {Ext,Buffer2} = getext(Buffer), - case Ext of - 0 -> decode_integer(Buffer2,Rc); - 1 -> decode_unconstrained_number(Buffer2) - end; -decode_integer(Buffer,undefined) -> - decode_unconstrained_number(Buffer); -decode_integer(Buffer,C) -> - case get_constraint(C,'SingleValue') of - V when integer(V) -> - {V,Buffer}; - V when list(V) -> - {Val,Buffer2} = decode_integer1(Buffer,C), - case lists:member(Val,V) of - true -> - {Val,Buffer2}; - _ -> - exit({error,{asn1,{illegal_value,Val}}}) - end; - _ -> - decode_integer1(Buffer,C) - end. - -decode_integer1(Buffer,C) -> - case VR = get_constraint(C,'ValueRange') of - no -> - decode_unconstrained_number(Buffer); - {Lb, 'MAX'} -> - decode_semi_constrained_number(Buffer,Lb); - {_,_} -> - decode_constrained_number(Buffer,VR) - end. - -% X.691:10.6 Encoding of a normally small non-negative whole number -% Use this for encoding of CHOICE index if there is an extension marker in -% the CHOICE -encode_small_number({Name,Val}) when atom(Name) -> - encode_small_number(Val); -encode_small_number(Val) when Val =< 63 -> - [{bit,0},{bits,6,Val}]; -encode_small_number(Val) -> - [{bit,1},encode_semi_constrained_number(0,Val)]. - -decode_small_number(Bytes) -> - {Bit,Bytes2} = getbit(Bytes), - case Bit of - 0 -> - getbits(Bytes2,6); - 1 -> - decode_semi_constrained_number(Bytes2,{0,'MAX'}) - end. - -% X.691:10.7 Encoding of a semi-constrained whole number -%% might be an optimization encode_semi_constrained_number(0,Val) -> -encode_semi_constrained_number(C,{Name,Val}) when atom(Name) -> - encode_semi_constrained_number(C,Val); -encode_semi_constrained_number({Lb,'MAX'},Val) -> - encode_semi_constrained_number(Lb,Val); -encode_semi_constrained_number(Lb,Val) -> - Val2 = Val - Lb, - Octs = eint_positive(Val2), - [encode_length(undefined,length(Octs)),{octets,Octs}]. - -decode_semi_constrained_number(Bytes,{Lb,_}) -> - decode_semi_constrained_number(Bytes,Lb); -decode_semi_constrained_number(Bytes,Lb) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - {V,Bytes3} = getoctets(Bytes2,Len), - {V+Lb,Bytes3}. - -encode_constrained_number(Range,{Name,Val}) when atom(Name) -> - encode_constrained_number(Range,Val); -encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val -> - Range = Ub - Lb + 1, - Val2 = Val - Lb, - if - Range == 2 -> - {bits,1,Val2}; - Range =< 4 -> - {bits,2,Val2}; - Range =< 8 -> - {bits,3,Val2}; - Range =< 16 -> - {bits,4,Val2}; - Range =< 32 -> - {bits,5,Val2}; - Range =< 64 -> - {bits,6,Val2}; - Range =< 128 -> - {bits,7,Val2}; - Range =< 255 -> - {bits,8,Val2}; - Range =< 256 -> - {octets,1,Val2}; - Range =< 65536 -> - {octets,2,Val2}; - Range =< 16#1000000 -> - Octs = eint_positive(Val2), - [encode_length({1,3},length(Octs)),{octets,Octs}]; - Range =< 16#100000000 -> - Octs = eint_positive(Val2), - [encode_length({1,4},length(Octs)),{octets,Octs}]; - Range =< 16#10000000000 -> - Octs = eint_positive(Val2), - [encode_length({1,5},length(Octs)),{octets,Octs}]; - true -> - exit({not_supported,{integer_range,Range}}) - end. - -decode_constrained_number(Buffer,{Lb,Ub}) -> - Range = Ub - Lb + 1, -% Val2 = Val - Lb, - {Val,Remain} = - if - Range == 2 -> - getbits(Buffer,1); - Range =< 4 -> - getbits(Buffer,2); - Range =< 8 -> - getbits(Buffer,3); - Range =< 16 -> - getbits(Buffer,4); - Range =< 32 -> - getbits(Buffer,5); - Range =< 64 -> - getbits(Buffer,6); - Range =< 128 -> - getbits(Buffer,7); - Range =< 255 -> - getbits(Buffer,8); - Range =< 256 -> - getoctets(Buffer,1); - Range =< 65536 -> - getoctets(Buffer,2); - Range =< 16#1000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,3}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#100000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,4}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#10000000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,5}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - true -> - exit({not_supported,{integer_range,Range}}) - end, - {Val+Lb,Remain}. - -% X.691:10.8 Encoding of an unconstrained whole number - -encode_unconstrained_number(Val) when Val >= 0 -> - Oct = eint(Val,[]), - [{debug,unconstrained_number}, - encode_length({0,'MAX'},length(Oct)), - {octets,Oct}]; -encode_unconstrained_number(Val) -> % negative - Oct = enint(Val,[]), - [{debug,unconstrained_number}, - encode_length({0,'MAX'},length(Oct)), - {octets,Oct}]. - -%% used for positive Values which don't need a sign bit -eint_positive(Val) -> - case eint(Val,[]) of - [0,B1|T] -> - [B1|T]; - T -> - T - end. - -eint(0, [B|Acc]) when B < 128 -> - [B|Acc]; -eint(N, Acc) -> - eint(N bsr 8, [N band 16#ff| Acc]). - -enint(-1, [B1|T]) when B1 > 127 -> - [B1|T]; -enint(N, Acc) -> - enint(N bsr 8, [N band 16#ff|Acc]). - -%% used for signed positive values - -%eint(Val, Ack) -> -% X = Val band 255, -% Next = Val bsr 8, -% if -% Next == 0, X >= 127 -> -% [0,X|Ack]; -% Next == 0 -> -% [X|Ack]; -% true -> -% eint(Next,[X|Ack]) -% end. - -%%% used for signed negative values -%enint(Val, Acc) -> -% NumOctets = if -% -Val < 16#80 -> 1; -% -Val < 16#8000 ->2; -% -Val < 16#800000 ->3; -% -Val < 16#80000000 ->4; -% -Val < 16#8000000000 ->5; -% -Val < 16#800000000000 ->6; -% -Val < 16#80000000000000 ->7; -% -Val < 16#8000000000000000 ->8; -% -Val < 16#800000000000000000 ->9 -% end, -% enint(Val,Acc,NumOctets). - -%enint(Val, Acc,0) -> -% Acc; -%enint(Val, Acc,NumOctets) -> -% enint(Val bsr 8,[Val band 255|Acc],NumOctets-1). - - -decode_unconstrained_number(Bytes) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - {Ints,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_integer(Ints),Bytes3}. - -dec_pos_integer(Ints) -> - decpint(Ints, 8 * (length(Ints) - 1)). -dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number - decpint(Ints, 8 * (length(Ints) - 1)); -dec_integer(Ints) -> %% Negative - decnint(Ints, 8 * (length(Ints) - 1)). - -decpint([Byte|Tail], Shift) -> - (Byte bsl Shift) bor decpint(Tail, Shift-8); -decpint([], _) -> 0. - -decnint([Byte|Tail], Shift) -> - (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8). - -minimum_octets(Val) -> - minimum_octets(Val,[]). - -minimum_octets(Val,Acc) when Val > 0 -> - minimum_octets((Val bsr 8),[Val band 16#FF|Acc]); -minimum_octets(0,Acc) -> - Acc. - - -%% X.691:10.9 Encoding of a length determinant -%%encode_small_length(undefined,Len) -> % null means no UpperBound -%% encode_small_number(Len). - -%% X.691:10.9.3.5 -%% X.691:10.9.3.7 -encode_length(undefined,Len) -> % un-constrained - if - Len < 128 -> - {octet,Len band 16#7F}; - Len < 16384 -> - {octets,2,2#1000000000000000 bor Len}; - true -> - exit({error,{asn1,{encode_length,{nyi,above_16k}}}}) - end; - -encode_length({0,'MAX'},Len) -> - encode_length(undefined,Len); -encode_length({Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained - encode_constrained_number({Lb,Ub},Len); -encode_length(SingleValue,_Len) when integer(SingleValue) -> - []. - -encode_small_length(Len) when Len =< 64 -> - [{bit,0},{bits,6,Len-1}]; -encode_small_length(Len) -> - [{bit,1},encode_length(undefined,Len)]. - -decode_small_length(Buffer) -> - case getbit(Buffer) of - {0,Remain} -> - {Bits,Remain2} = getbits(Remain,6), - {Bits+1,Remain2}; - {1,Remain} -> - decode_length(Remain,undefined) - end. - -decode_length(Buffer) -> - decode_length(Buffer,undefined). - -decode_length(Buffer,undefined) -> % un-constrained - Buffer2 = align(Buffer), - {Bits,_} = getbits(Buffer2,2), - case Bits of - 2 -> - {Val,Bytes3} = getoctets(Buffer2,2), - {(Val band 16#3FFF),Bytes3}; - 3 -> - exit({error,{asn1,{decode_length,{nyi,above_16k}}}}); - _ -> - {Val,Bytes3} = getoctet(Buffer2), - {Val band 16#7F,Bytes3} - end; - -decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained - decode_constrained_number(Buffer,{Lb,Ub}); - % X.691:10.9.3.5 -decode_length(Buffer,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub - case getbit(Buffer) of - {0,Remain} -> - getbits(Remain,7); - {1,_Remain} -> - {Val,Remain2} = getoctets(Buffer,2), - {Val band 2#0111111111111111, Remain2} - end; -decode_length(Buffer,SingleValue) when integer(SingleValue) -> - {SingleValue,Buffer}. - - -% X.691:11 -encode_boolean({Name,Val}) when atom(Name) -> - encode_boolean(Val); -encode_boolean(true) -> - {bit,1}; -encode_boolean(false) -> - {bit,0}; -encode_boolean(Val) -> - exit({error,{asn1,{encode_boolean,Val}}}). - - -decode_boolean(Buffer) -> %when record(Buffer,buffer) - case getbit(Buffer) of - {1,Remain} -> {true,Remain}; - {0,Remain} -> {false,Remain} - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% X.691:12 -%% ENUMERATED -%% -%% encode_enumerated(C,Value,NamedNumberTup) -> CompleteList -%% -%% - -encode_enumerated(C,{Name,Value},NamedNumberList) when - atom(Name),list(NamedNumberList) -> - encode_enumerated(C,Value,NamedNumberList); - -%% ENUMERATED with extension mark -encode_enumerated(_C,{asn1_enum,Value},{_Nlist1,Nlist2}) when Value >= length(Nlist2) -> - [{bit,1},encode_small_number(Value)]; -encode_enumerated(C,Value,{Nlist1,Nlist2}) -> - case enum_search(Value,Nlist1,0) of - NewV when integer(NewV) -> - [{bit,0},encode_integer(C,NewV)]; - false -> - case enum_search(Value,Nlist2,0) of - ExtV when integer(ExtV) -> - [{bit,1},encode_small_number(ExtV)]; - false -> - exit({error,{asn1,{encode_enumerated,Value}}}) - end - end; - -encode_enumerated(C,Value,NamedNumberList) when list(NamedNumberList) -> - case enum_search(Value,NamedNumberList,0) of - NewV when integer(NewV) -> - encode_integer(C,NewV); - false -> - exit({error,{asn1,{encode_enumerated,Value}}}) - end. - -%% returns the ordinal number from 0 ,1 ... in the list where Name is found -%% or false if not found -%% -enum_search(Name,[Name|_NamedNumberList],Acc) -> - Acc; -enum_search(Name,[_H|T],Acc) -> - enum_search(Name,T,Acc+1); -enum_search(_,[],_) -> - false. % name not found !error - -%% ENUMERATED with extension marker -decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) -> - {Ext,Buffer2} = getext(Buffer), - case Ext of - 0 -> % not an extension value - {Val,Buffer3} = decode_integer(Buffer2,C), - case catch (element(Val+1,Ntup1)) of - NewVal when atom(NewVal) -> {NewVal,Buffer3}; - _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}}) - end; - 1 -> % this an extension value - {Val,Buffer3} = decode_small_number(Buffer2), - case catch (element(Val+1,Ntup2)) of - NewVal when atom(NewVal) -> {NewVal,Buffer3}; - _ -> {{asn1_enum,Val},Buffer3} - end - end; - -decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) -> - {Val,Buffer2} = decode_integer(Buffer,C), - case catch (element(Val+1,NamedNumberTup)) of - NewVal when atom(NewVal) -> {NewVal,Buffer2}; - _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}}) - end. - -%%=============================================================================== -%%=============================================================================== -%%=============================================================================== -%% Bitstring value, ITU_T X.690 Chapter 8.5 -%%=============================================================================== -%%=============================================================================== -%%=============================================================================== - -%%=============================================================================== -%% encode bitstring value -%%=============================================================================== - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% bitstring NamedBitList -%% Val can be of: -%% - [identifiers] where only named identifers are set to one, -%% the Constraint must then have some information of the -%% bitlength. -%% - [list of ones and zeroes] all bits -%% - integer value representing the bitlist -%% C is constraint Len, only valid when identifiers - -%% when the value is a list of named bits -encode_bit_string(C, [FirstVal | RestVal], NamedBitList) when atom(FirstVal) -> - ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []), - BitList = make_and_set_list(ToSetPos,0), - encode_bit_string(C,BitList,NamedBitList); - -encode_bit_string(C, [{bit,No} | RestVal], NamedBitList) -> - ToSetPos = get_all_bitposes([{bit,No} | RestVal], NamedBitList, []), - BitList = make_and_set_list(ToSetPos,0), - encode_bit_string(C,BitList,NamedBitList); - -%% when the value is a list of ones and zeroes - -encode_bit_string(C, BitListValue, _NamedBitList) when list(BitListValue) -> - %% first remove any trailing zeroes - Bl1 = lists:dropwhile(fun(0)->true;(1)->false end,lists:reverse(BitListValue)), - BitList = [{bit,X} || X <- lists:reverse(Bl1)], - case get_constraint(C,'SizeConstraint') of - 0 -> % fixed length - []; % nothing to encode - V when integer(V),V=<16 -> % fixed length 16 bits or less - pad_list(V,BitList); - V when integer(V) -> % fixed length more than 16 bits - [align,pad_list(V,BitList)]; - {Lb,Ub} when integer(Lb),integer(Ub) -> - [encode_length({Lb,Ub},length(BitList)),align,BitList]; - no -> - [encode_length(undefined,length(BitList)),align,BitList] - end; - -%% when the value is an integer -encode_bit_string(C, IntegerVal, NamedBitList) -> - BitList = int_to_bitlist(IntegerVal), - encode_bit_string(C,BitList,NamedBitList). - - - - -%%%%%%%%%%%%%%% -%% The result is presented as a list of named bits (if possible) -%% else as a list of 0 and 1. -%% -decode_bit_string(Buffer, C, NamedNumberList) -> - case get_constraint(C,'SizeConstraint') of - 0 -> % fixed length - {[],Buffer}; % nothing to encode - V when integer(V),V=<16 -> % fixed length 16 bits or less - bit_list_to_named(Buffer,V,NamedNumberList); - V when integer(V) -> % fixed length 16 bits or less - Bytes2 = align(Buffer), - bit_list_to_named(Bytes2,V,NamedNumberList); - {Lb,Ub} when integer(Lb),integer(Ub) -> - {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}), - Bytes3 = align(Bytes2), - bit_list_to_named(Bytes3,Len,NamedNumberList); - no -> - {Len,Bytes2} = decode_length(Buffer,undefined), - Bytes3 = align(Bytes2), - bit_list_to_named(Bytes3,Len,NamedNumberList) - end. - -%% if no named bits are declared we will return a -%% BitList = [0 | 1] - -bit_list_to_named(Buffer,Len,[]) -> - getbits_as_list(Len,Buffer); - -%% if there are named bits declared we will return a named -%% BitList where the names are atoms and unnamed bits represented -%% as {bit,Pos} -%% BitList = [atom() | {bit,Pos}] -%% Pos = integer() - -bit_list_to_named(Buffer,Len,NamedNumberList) -> - {BitList,Rest} = getbits_as_list(Len,Buffer), - {bit_list_to_named1(0,BitList,NamedNumberList,[]), Rest}. - -bit_list_to_named1(Pos,[0|Bt],Names,Acc) -> - bit_list_to_named1(Pos+1,Bt,Names,Acc); -bit_list_to_named1(Pos,[1|Bt],Names,Acc) -> - case lists:keysearch(Pos,2,Names) of - {value,{Name,_}} -> - bit_list_to_named1(Pos+1,Bt,Names,[Name|Acc]); - _ -> - bit_list_to_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc]) - end; -bit_list_to_named1(_Pos,[],_Names,Acc) -> - lists:reverse(Acc). - - - -%%%%%%%%%%%%%%% -%% - -int_to_bitlist(0) -> - []; -int_to_bitlist(Int) when integer(Int), Int >= 0 -> - [Int band 1 | int_to_bitlist(Int bsr 1)]. - - -%%%%%%%%%%%%%%%%%% -%% get_all_bitposes([list of named bits to set], named_bit_db, []) -> -%% [sorted_list_of_bitpositions_to_set] - -get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) -> - get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]); - -get_all_bitposes([Val | Rest], NamedBitList, Ack) -> - case lists:keysearch(Val, 1, NamedBitList) of - {value, {_ValName, ValPos}} -> - get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]); - _ -> - exit({error,{asn1, {bitstring_namedbit, Val}}}) - end; -get_all_bitposes([], _NamedBitList, Ack) -> - lists:sort(Ack). - -%%%%%%%%%%%%%%%%%% -%% make_and_set_list([list of positions to set to 1])-> -%% returns list with all in SetPos set. -%% in positioning in list the first element is 0, the second 1 etc.., but -%% - -make_and_set_list([XPos|SetPos], XPos) -> - [1 | make_and_set_list(SetPos, XPos + 1)]; -make_and_set_list([Pos|SetPos], XPos) -> - [0 | make_and_set_list([Pos | SetPos], XPos + 1)]; -make_and_set_list([], _) -> - []. - -%%%%%%%%%%%%%%%%% -%% pad_list(N,BitList) -> PaddedList -%% returns a padded (with trailing {bit,0} elements) list of length N -%% if Bitlist contains more than N significant bits set an exit asn1_error -%% is generated - -pad_list(0,BitList) -> - case BitList of - [] -> []; - _ -> exit({error,{asn1,{range_error,{bit_string,BitList}}}}) - end; -pad_list(N,[Bh|Bt]) -> - [Bh|pad_list(N-1,Bt)]; -pad_list(N,[]) -> - [{bit,0},pad_list(N-1,[])]. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% X.691:16 -%% encode_octet_string(Constraint,ExtensionMarker,Val) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -encode_octet_string(C,{Name,Val}) when atom(Name) -> - encode_octet_string(C,false,Val); -encode_octet_string(C,Val) -> - encode_octet_string(C,false,Val). - -encode_octet_string(_C,true,_Val) -> - exit({error,{asn1,{'not_supported',extensionmarker}}}); -encode_octet_string(C,false,Val) -> - case get_constraint(C,'SizeConstraint') of - 0 -> - []; - 1 -> - [V] = Val, - {bits,8,V}; - 2 -> - [V1,V2] = Val, - [{bits,8,V1},{bits,8,V2}]; - Sv when Sv =<65535, Sv == length(Val) -> % fixed length - [align,{octets,Val}]; - {Lb,Ub} -> - [encode_length({Lb,Ub},length(Val)),align, - {octets,Val}]; - Sv when list(Sv) -> - [encode_length({hd(Sv),lists:max(Sv)},length(Val)),align, - {octets,Val}]; - no -> - [encode_length(undefined,length(Val)),align, - {octets,Val}] - end. - -decode_octet_string(Bytes,Range) -> - decode_octet_string(Bytes,Range,false). - -decode_octet_string(Bytes,C,false) -> - case get_constraint(C,'SizeConstraint') of - 0 -> - {[],Bytes}; - 1 -> - {B1,Bytes2} = getbits(Bytes,8), - {[B1],Bytes2}; - 2 -> - {B1,Bytes2}= getbits(Bytes,8), - {B2,Bytes3}= getbits(Bytes2,8), - {[B1,B2],Bytes3}; - {_,0} -> - {[],Bytes}; - Sv when integer(Sv), Sv =<65535 -> % fixed length - Bytes2 = align(Bytes), - getoctets_as_list(Bytes2,Sv); - {Lb,Ub} -> - {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}), - Bytes3 = align(Bytes2), - getoctets_as_list(Bytes3,Len); - Sv when list(Sv) -> - {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}), - Bytes3 = align(Bytes2), - getoctets_as_list(Bytes3,Len); - no -> - {Len,Bytes2} = decode_length(Bytes,undefined), - Bytes3 = align(Bytes2), - getoctets_as_list(Bytes3,Len) - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Restricted char string types -%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString) -%% X.691:26 and X.680:34-36 -%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val) - -encode_restricted_string(aligned,StringType,C,Val) -> -encode_restricted_string(aligned,StringType,C,false,Val). - - -encode_restricted_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) -> - encode_restricted_string(aligned,StringType,C,false,Val); -encode_restricted_string(aligned,StringType,C,_Ext,Val) -> - Result = chars_encode(C,StringType,Val), - NumBits = get_NumBits(C,StringType), - case get_constraint(C,'SizeConstraint') of - Ub when integer(Ub), Ub*NumBits =< 16 -> - case {StringType,Result} of - {'BMPString',{octets,Ol}} -> - [{bits,8,Oct}||Oct <- Ol]; - _ -> - Result - end; - 0 -> - []; - Ub when integer(Ub),Ub =<65535 -> % fixed length - [align,Result]; - {Ub,Lb} -> - [encode_length({Ub,Lb},length(Val)),align,Result]; - Vl when list(Vl) -> - [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result]; - no -> - [encode_length(undefined,length(Val)),align,Result] - end. - -decode_restricted_string(Bytes,aligned,StringType,C) -> - decode_restricted_string(Bytes,aligned,StringType,C,false). - -decode_restricted_string(Bytes,aligned,StringType,C,_Ext) -> - NumBits = get_NumBits(C,StringType), - case get_constraint(C,'SizeConstraint') of - Ub when integer(Ub), Ub*NumBits =< 16 -> - chars_decode(Bytes,NumBits,StringType,C,Ub); - Ub when integer(Ub),Ub =<65535 -> % fixed length - Bytes1 = align(Bytes), - chars_decode(Bytes1,NumBits,StringType,C,Ub); - 0 -> - {[],Bytes}; - Vl when list(Vl) -> - {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}), - Bytes2 = align(Bytes1), - chars_decode(Bytes2,NumBits,StringType,C,Len); - no -> - {Len,Bytes1} = decode_length(Bytes,undefined), - Bytes2 = align(Bytes1), - chars_decode(Bytes2,NumBits,StringType,C,Len); - {Lb,Ub}-> - {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}), - Bytes2 = align(Bytes1), - chars_decode(Bytes2,NumBits,StringType,C,Len) - end. - - - -encode_BMPString(C,Val) -> - encode_restricted_string(aligned,'BMPString',C,false,Val). -decode_BMPString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'BMPString',C,false). - -encode_GeneralString(C,Val) -> - encode_restricted_string(aligned,'GeneralString',C,false,Val). -decode_GeneralString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'GeneralString',C,false). - -encode_GraphicString(C,Val) -> - encode_restricted_string(aligned,'GraphicString',C,false,Val). -decode_GraphicString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'GraphicString',C,false). - -encode_IA5String(C,Val) -> - encode_restricted_string(aligned,'IA5String',C,false,Val). -decode_IA5String(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'IA5String',C,false). - -encode_NumericString(C,Val) -> - encode_restricted_string(aligned,'NumericString',C,false,Val). -decode_NumericString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'NumericString',C,false). - -encode_PrintableString(C,Val) -> - encode_restricted_string(aligned,'PrintableString',C,false,Val). -decode_PrintableString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'PrintableString',C,false). - -encode_TeletexString(C,Val) -> % equivalent with T61String - encode_restricted_string(aligned,'TeletexString',C,false,Val). -decode_TeletexString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'TeletexString',C,false). - -encode_UniversalString(C,Val) -> - encode_restricted_string(aligned,'UniversalString',C,false,Val). -decode_UniversalString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'UniversalString',C,false). - -encode_VideotexString(C,Val) -> - encode_restricted_string(aligned,'VideotexString',C,false,Val). -decode_VideotexString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'VideotexString',C,false). - -encode_VisibleString(C,Val) -> % equivalent with ISO646String - encode_restricted_string(aligned,'VisibleString',C,false,Val). -decode_VisibleString(Bytes,C) -> - decode_restricted_string(Bytes,aligned,'VisibleString',C,false). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes} -%% -getBMPChars(Bytes,1) -> - {O1,Bytes2} = getbits(Bytes,8), - {O2,Bytes3} = getbits(Bytes2,8), - if - O1 == 0 -> - {[O2],Bytes3}; - true -> - {[{O1,O2}],Bytes3} - end; -getBMPChars(Bytes,Len) -> - getBMPChars(Bytes,Len,[]). - -getBMPChars(Bytes,0,Acc) -> - {lists:reverse(Acc),Bytes}; -getBMPChars(Bytes,Len,Acc) -> - {Octs,Bytes1} = getoctets_as_list(Bytes,2), - case Octs of - [0,O2] -> - getBMPChars(Bytes1,Len-1,[O2|Acc]); - [O1,O2]-> - getBMPChars(Bytes1,Len-1,[{O1,O2}|Acc]) - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% chars_encode(C,StringType,Value) -> ValueList -%% -%% encodes chars according to the per rules taking the constraint PermittedAlphabet -%% into account. -%% This function does only encode the value part and NOT the length - -chars_encode(C,StringType,Value) -> - case {StringType,get_constraint(C,'PermittedAlphabet')} of - {'UniversalString',{_,_Sv}} -> - exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}}); - {'BMPString',{_,_Sv}} -> - exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}}); - _ -> - {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)}, - chars_encode2(Value,NumBits,CharOutTab) - end. - -chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min -> - [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})]; -chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min -> - [{bits,NumBits,element(H-Min+1,Tab)}|chars_encode2(T,NumBits,{Min,Max,Tab})]; -chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) -> - %% no value range check here (ought to be, but very expensive) - [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})]; -chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) -> - %% no value range check here (ought to be, but very expensive) - [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})]; -chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) -> - exit({error,{asn1,{illegal_char_value,H}}}); -chars_encode2([],_,_) -> - []. - - -get_NumBits(C,StringType) -> - case get_constraint(C,'PermittedAlphabet') of - {'SingleValue',Sv} -> - charbits(length(Sv),aligned); - no -> - case StringType of - 'GeneralString' -> - exit({error,{asn1,{not implemented,'GeneralString'}}}); - 'GraphicString' -> - exit({error,{asn1,{not implemented,'GraphicString'}}}); - 'TeletexString' -> - exit({error,{asn1,{not implemented,'TeletexString'}}}); - 'VideotexString' -> - exit({error,{asn1,{not implemented,'VideotexString'}}}); - 'IA5String' -> - charbits(128,aligned); % 16#00..16#7F - 'VisibleString' -> - charbits(95,aligned); % 16#20..16#7E - 'PrintableString' -> - charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z - 'NumericString' -> - charbits(11,aligned); % $ ,"0123456789" - 'UniversalString' -> - 32; - 'BMPString' -> - 16 - end - end. - -%%Maybe used later -%%get_MaxChar(C,StringType) -> -%% case get_constraint(C,'PermittedAlphabet') of -%% {'SingleValue',Sv} -> -%% lists:nth(length(Sv),Sv); -%% no -> -%% case StringType of -%% 'IA5String' -> -%% 16#7F; % 16#00..16#7F -%% 'VisibleString' -> -%% 16#7E; % 16#20..16#7E -%% 'PrintableString' -> -%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z -%% 'NumericString' -> -%% $9; % $ ,"0123456789" -%% 'UniversalString' -> -%% 16#ffffffff; -%% 'BMPString' -> -%% 16#ffff -%% end -%% end. - -%%Maybe used later -%%get_MinChar(C,StringType) -> -%% case get_constraint(C,'PermittedAlphabet') of -%% {'SingleValue',Sv} -> -%% hd(Sv); -%% no -> -%% case StringType of -%% 'IA5String' -> -%% 16#00; % 16#00..16#7F -%% 'VisibleString' -> -%% 16#20; % 16#20..16#7E -%% 'PrintableString' -> -%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z -%% 'NumericString' -> -%% $\s; % $ ,"0123456789" -%% 'UniversalString' -> -%% 16#00; -%% 'BMPString' -> -%% 16#00 -%% end -%% end. - -get_CharOutTab(C,StringType) -> - get_CharTab(C,StringType,out). - -get_CharInTab(C,StringType) -> - get_CharTab(C,StringType,in). - -get_CharTab(C,StringType,InOut) -> - case get_constraint(C,'PermittedAlphabet') of - {'SingleValue',Sv} -> - get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut); - no -> - case StringType of - 'IA5String' -> - {0,16#7F,notab}; - 'VisibleString' -> - get_CharTab2(C,StringType,16#20,16#7F,notab,InOut); - 'PrintableString' -> - Chars = lists:sort( - " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), - get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut); - 'NumericString' -> - get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut); - 'UniversalString' -> - {0,16#FFFFFFFF,notab}; - 'BMPString' -> - {0,16#FFFF,notab} - end - end. - -get_CharTab2(C,StringType,Min,Max,Chars,InOut) -> - BitValMax = (1 bsl get_NumBits(C,StringType))-1, - if - Max =< BitValMax -> - {0,Max,notab}; - true -> - case InOut of - out -> - {Min,Max,create_char_tab(Min,Chars)}; - in -> - {Min,Max,list_to_tuple(Chars)} - end - end. - -create_char_tab(Min,L) -> - list_to_tuple(create_char_tab(Min,L,0)). -create_char_tab(Min,[Min|T],V) -> - [V|create_char_tab(Min+1,T,V+1)]; -create_char_tab(_Min,[],_V) -> - []; -create_char_tab(Min,L,V) -> - [false|create_char_tab(Min+1,L,V)]. - -%% This very inefficient and should be moved to compiletime -charbits(NumOfChars,aligned) -> - case charbits(NumOfChars) of - 1 -> 1; - 2 -> 2; - B when B > 2, B =< 4 -> 4; - B when B > 4, B =< 8 -> 8; - B when B > 8, B =< 16 -> 16; - B when B > 16, B =< 32 -> 32 - end. - -charbits(NumOfChars) when NumOfChars =< 2 -> 1; -charbits(NumOfChars) when NumOfChars =< 4 -> 2; -charbits(NumOfChars) when NumOfChars =< 8 -> 3; -charbits(NumOfChars) when NumOfChars =< 16 -> 4; -charbits(NumOfChars) when NumOfChars =< 32 -> 5; -charbits(NumOfChars) when NumOfChars =< 64 -> 6; -charbits(NumOfChars) when NumOfChars =< 128 -> 7; -charbits(NumOfChars) when NumOfChars =< 256 -> 8; -charbits(NumOfChars) when NumOfChars =< 512 -> 9; -charbits(NumOfChars) when NumOfChars =< 1024 -> 10; -charbits(NumOfChars) when NumOfChars =< 2048 -> 11; -charbits(NumOfChars) when NumOfChars =< 4096 -> 12; -charbits(NumOfChars) when NumOfChars =< 8192 -> 13; -charbits(NumOfChars) when NumOfChars =< 16384 -> 14; -charbits(NumOfChars) when NumOfChars =< 32768 -> 15; -charbits(NumOfChars) when NumOfChars =< 65536 -> 16; -charbits(NumOfChars) when integer(NumOfChars) -> - 16 + charbits1(NumOfChars bsr 16). - -charbits1(0) -> - 0; -charbits1(NumOfChars) -> - 1 + charbits1(NumOfChars bsr 1). - - -chars_decode(Bytes,_,'BMPString',C,Len) -> - case get_constraint(C,'PermittedAlphabet') of - no -> - getBMPChars(Bytes,Len); - _ -> - exit({error,{asn1, - {'not implemented', - "BMPString with PermittedAlphabet constraint"}}}) - end; -chars_decode(Bytes,NumBits,StringType,C,Len) -> - CharInTab = get_CharInTab(C,StringType), - chars_decode2(Bytes,CharInTab,NumBits,Len). - - -chars_decode2(Bytes,CharInTab,NumBits,Len) -> - chars_decode2(Bytes,CharInTab,NumBits,Len,[]). - -chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) -> - {lists:reverse(Acc),Bytes}; -chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 -> - {Char,Bytes2} = getbits(Bytes,NumBits), - Result = case minimum_octets(Char+Min) of - [NewChar] -> NewChar; - [C1,C2] -> {0,0,C1,C2}; - [C1,C2,C3] -> {0,C1,C2,C3}; - [C1,C2,C3,C4] -> {C1,C2,C3,C4} - end, - chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]); -chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) -> - {Char,Bytes2} = getbits(Bytes,NumBits), - chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]); - -%% BMPString and UniversalString with PermittedAlphabet is currently not supported -chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) -> - {Char,Bytes2} = getbits(Bytes,NumBits), - chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]). - - - % X.691:17 -encode_null({Name,Val}) when atom(Name) -> - encode_null(Val); -encode_null(_) -> []. % encodes to nothing - -decode_null(Bytes) -> - {'NULL',Bytes}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% encode_object_identifier(Val) -> CompleteList -%% encode_object_identifier({Name,Val}) -> CompleteList -%% Val -> {Int1,Int2,...,IntN} % N >= 2 -%% Name -> atom() -%% Int1 -> integer(0..2) -%% Int2 -> integer(0..39) when Int1 (0..1) else integer() -%% Int3-N -> integer() -%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...] -%% -encode_object_identifier(Val) -> - Octets = e_object_identifier(Val,notag), - [{debug,object_identifier},encode_length(undefined,length(Octets)),{octets,Octets}]. - -%% This code is copied from asn1_encode.erl (BER) and corrected and modified - -e_object_identifier({'OBJECT IDENTIFIER',V},DoTag) -> - e_object_identifier(V,DoTag); -e_object_identifier({Cname,V},DoTag) when atom(Cname),tuple(V) -> - e_object_identifier(tuple_to_list(V),DoTag); -e_object_identifier({Cname,V},DoTag) when atom(Cname),list(V) -> - e_object_identifier(V,DoTag); -e_object_identifier(V,DoTag) when tuple(V) -> - e_object_identifier(tuple_to_list(V),DoTag); - -% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1) -e_object_identifier([E1,E2|Tail],_DoTag) when E1 =< 2 -> - Head = 40*E1 + E2, % weird - Res = e_object_elements([Head|Tail]), -% dotag(DoTag,[6],elength(length(Res)+1),[Head|Res]), - Res. - -e_object_elements([]) -> - []; -e_object_elements([H|T]) -> - lists:append(e_object_element(H),e_object_elements(T)). - -e_object_element(Num) when Num < 128 -> - [Num]; -% must be changed to handle more than 2 octets -e_object_element(Num) -> %% when Num < ??? - Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000, - Right = Num band 2#1111111 , - [Left,Right]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes} -%% ObjId -> {integer(),integer(),...} % at least 2 integers -%% RemainingBytes -> [integer()] when integer() (0..255) -decode_object_identifier(Bytes) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - [First|Rest] = dec_subidentifiers(Octs,0,[]), - Idlist = if - First < 40 -> - [0,First|Rest]; - First < 80 -> - [1,First - 40|Rest]; - true -> - [2,First - 80|Rest] - end, - {list_to_tuple(Idlist),Bytes3}. - -dec_subidentifiers([H|T],Av,Al) when H >=16#80 -> - dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al); -dec_subidentifiers([H|T],Av,Al) -> - dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]); -dec_subidentifiers([],_Av,Al) -> - lists:reverse(Al). - -get_constraint(C,Key) -> - case lists:keysearch(Key,1,C) of - false -> - no; - {value,{_,V}} -> - V - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% complete(InList) -> ByteList -%% Takes a coded list with bits and bytes and converts it to a list of bytes -%% Should be applied as the last step at encode of a complete ASN.1 type -%% -complete(InList) when list(InList) -> - complete(InList,[],0); -complete(InList) -> - complete([InList],[],0). - -complete([{debug,_}|T], Acc, Acclen) -> - complete(T,Acc,Acclen); -complete([H|T],Acc,Acclen) when list(H) -> - complete(lists:concat([H,T]),Acc,Acclen); - - -complete([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) -> - Newval = case N of - 1 -> - Val4 = Val band 16#FF, - [Val4]; - 2 -> - Val3 = (Val bsr 8) band 16#FF, - Val4 = Val band 16#FF, - [Val3,Val4]; - 3 -> - Val2 = (Val bsr 16) band 16#FF, - Val3 = (Val bsr 8) band 16#FF, - Val4 = Val band 16#FF, - [Val2,Val3,Val4]; - 4 -> - Val1 = (Val bsr 24) band 16#FF, - Val2 = (Val bsr 16) band 16#FF, - Val3 = (Val bsr 8) band 16#FF, - Val4 = Val band 16#FF, - [Val1,Val2,Val3,Val4] - end, - complete([{octets,Newval}|T],Acc,Acclen); - -complete([{octets,Oct}|T],[],_Acclen) when list(Oct) -> - complete(T,lists:reverse(Oct),0); -complete([{octets,Oct}|T],[Hacc|Tacc],Acclen) when list(Oct) -> - Rest = 8 - Acclen, - if - Rest == 8 -> - complete(T,lists:concat([lists:reverse(Oct),[Hacc|Tacc]]),0); - true -> - complete(T,lists:concat([lists:reverse(Oct),[Hacc bsl Rest|Tacc]]),0) - end; - -complete([{bit,Val}|T], Acc, Acclen) -> - complete([{bits,1,Val}|T],Acc,Acclen); -complete([{octet,Val}|T], Acc, Acclen) -> - complete([{octets,1,Val}|T],Acc,Acclen); - -complete([{bits,N,Val}|T], Acc, 0) when N =< 8 -> - complete(T,[Val|Acc],N); -complete([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 -> - Rest = 8 - Acclen, - if - Rest >= N -> - complete(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8); - true -> - Diff = N - Rest, - NewHacc = (Hacc bsl Rest) + (Val bsr Diff), - Mask = element(Diff,{1,3,7,15,31,63,127,255}), - complete(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8) - end; -complete([{bits,N,Val}|T], Acc, Acclen) -> % N > 8 - complete([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen); - -complete([align|T],Acc,0) -> - complete(T,Acc,0); -complete([align|T],[Hacc|Tacc],Acclen) -> - Rest = 8 - Acclen, - complete(T,[Hacc bsl Rest|Tacc],0); -complete([{octets,_N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here - complete([{octets,Val}|T],Acc,Acclen); -complete([],Acc,0) -> - lists:reverse(Acc); -complete([],[Hacc|Tacc],Acclen) when Acclen > 0-> - Rest = 8 - Acclen, - NewHacc = Hacc bsl Rest, - lists:reverse([NewHacc|Tacc]). - - - - - - - - - - - - - - - - |