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_check.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $ 18-module(asn1rt_check). 19 20-include("asn1_records.hrl"). 21 22-export([check_bool/2, 23 check_int/3, 24 check_bitstring/3, 25 check_octetstring/2, 26 check_null/2, 27 check_objectidentifier/2, 28 check_objectdescriptor/2, 29 check_real/2, 30 check_enum/3, 31 check_restrictedstring/2]). 32 33-export([transform_to_EXTERNAL1990/1, 34 transform_to_EXTERNAL1994/1]). 35 36 37check_bool(_Bool,asn1_DEFAULT) -> 38 true; 39check_bool(Bool,Bool) when Bool == true; Bool == false -> 40 true; 41check_bool(_Bool1,Bool2) -> 42 throw({error,Bool2}). 43 44check_int(_,asn1_DEFAULT,_) -> 45 true; 46check_int(Value,Value,_) when integer(Value) -> 47 true; 48check_int(DefValue,Value,NNL) when atom(Value) -> 49 case lists:keysearch(Value,1,NNL) of 50 {value,{_,DefValue}} -> 51 true; 52 _ -> 53 throw({error,DefValue}) 54 end; 55check_int(DefaultValue,_Value,_) -> 56 throw({error,DefaultValue}). 57 58% check_bitstring([H|T],[H|T],_) when integer(H) -> 59% true; 60% check_bitstring(V,V,_) when integer(V) -> 61% true; 62%% Two equal lists or integers 63check_bitstring(_,asn1_DEFAULT,_) -> 64 true; 65check_bitstring(V,V,_) -> 66 true; 67%% Default value as a list of 1 and 0 and user value as an integer 68check_bitstring(L=[H|T],Int,_) when integer(Int),integer(H) -> 69 case bit_list_to_int(L,length(T)) of 70 Int -> true; 71 _ -> throw({error,L,Int}) 72 end; 73%% Default value as an integer, val as list 74check_bitstring(Int,Val,NBL) when integer(Int),list(Val) -> 75 BL = int_to_bit_list(Int,[],length(Val)), 76 check_bitstring(BL,Val,NBL); 77%% Default value and user value as lists of ones and zeros 78check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL=[_H|_T]) when integer(H1),integer(H2) -> 79 L2new = remove_trailing_zeros(L2), 80 check_bitstring(L1,L2new,NBL); 81%% Default value as a list of 1 and 0 and user value as a list of atoms 82check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when integer(H1),atom(H2) -> 83 case bit_list_to_nbl(L1,NBL,0,[]) of 84 L3 -> check_bitstring(L3,L2,NBL); 85 _ -> throw({error,L2}) 86 end; 87%% Both default value and user value as a list of atoms 88check_bitstring(L1=[H1|T1],L2=[H2|_T2],_) when atom(H1),atom(H2) -> 89 length(L1) == length(L2), 90 case lists:member(H1,L2) of 91 true -> 92 check_bitstring1(T1,L2); 93 false -> throw({error,L2}) 94 end; 95%% Default value as a list of atoms and user value as a list of 1 and 0 96check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when atom(H1),integer(H2) -> 97 case bit_list_to_nbl(L2,NBL,0,[]) of 98 L3 -> 99 check_bitstring(L1,L3,NBL); 100 _ -> throw({error,L2}) 101 end; 102%% User value in compact format 103check_bitstring(DefVal,CBS={_,_},NBL) -> 104 NewVal = cbs_to_bit_list(CBS), 105 check_bitstring(DefVal,NewVal,NBL); 106check_bitstring(DV,V,_) -> 107 throw({error,DV,V}). 108 109 110bit_list_to_int([0|Bs],ShL)-> 111 bit_list_to_int(Bs,ShL-1) + 0; 112bit_list_to_int([1|Bs],ShL) -> 113 bit_list_to_int(Bs,ShL-1) + (1 bsl ShL); 114bit_list_to_int([],_) -> 115 0. 116 117int_to_bit_list(0,Acc,0) -> 118 Acc; 119int_to_bit_list(Int,Acc,Len) -> 120 int_to_bit_list(Int bsr 1,[Int band 1|Acc],Len - 1). 121 122bit_list_to_nbl([0|T],NBL,Pos,Acc) -> 123 bit_list_to_nbl(T,NBL,Pos+1,Acc); 124bit_list_to_nbl([1|T],NBL,Pos,Acc) -> 125 case lists:keysearch(Pos,2,NBL) of 126 {value,{N,_}} -> 127 bit_list_to_nbl(T,NBL,Pos+1,[N|Acc]); 128 _ -> 129 throw({error,{no,named,element,at,pos,Pos}}) 130 end; 131bit_list_to_nbl([],_,_,Acc) -> 132 Acc. 133 134remove_trailing_zeros(L2) -> 135 remove_trailing_zeros1(lists:reverse(L2)). 136remove_trailing_zeros1(L) -> 137 lists:reverse(lists:dropwhile(fun(0)->true; 138 (_) ->false 139 end, 140 L)). 141 142check_bitstring1([H|T],NBL) -> 143 case lists:member(H,NBL) of 144 true -> 145 check_bitstring1(T,NBL); 146 V -> throw({error,V}) 147 end; 148check_bitstring1([],_) -> 149 true. 150 151cbs_to_bit_list({Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when size(Rest) >= 1 -> 152 [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})]; 153cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) -> 154 [B7,B6,B5,B4,B3,B2,B1,B0]; 155cbs_to_bit_list({Unused,Bin}) when size(Bin) == 1 -> 156 Used = 8-Unused, 157 <<Int:Used,_:Unused>> = Bin, 158 int_to_bit_list(Int,[],Used). 159 160 161check_octetstring(_,asn1_DEFAULT) -> 162 true; 163check_octetstring(L,L) -> 164 true; 165check_octetstring(L,Int) when list(L),integer(Int) -> 166 case integer_to_octetlist(Int) of 167 L -> true; 168 V -> throw({error,V}) 169 end; 170check_octetstring(_,V) -> 171 throw({error,V}). 172 173integer_to_octetlist(Int) -> 174 integer_to_octetlist(Int,[]). 175integer_to_octetlist(0,Acc) -> 176 Acc; 177integer_to_octetlist(Int,Acc) -> 178 integer_to_octetlist(Int bsr 8,[(Int band 255)|Acc]). 179 180check_null(_,asn1_DEFAULT) -> 181 true; 182check_null('NULL','NULL') -> 183 true; 184check_null(_,V) -> 185 throw({error,V}). 186 187check_objectidentifier(_,asn1_DEFAULT) -> 188 true; 189check_objectidentifier(OI,OI) -> 190 true; 191check_objectidentifier(DOI,OI) when tuple(DOI),tuple(OI) -> 192 check_objectidentifier1(tuple_to_list(DOI),tuple_to_list(OI)); 193check_objectidentifier(_,OI) -> 194 throw({error,OI}). 195 196check_objectidentifier1([V|Rest1],[V|Rest2]) -> 197 check_objectidentifier1(Rest1,Rest2,V); 198check_objectidentifier1([V1|Rest1],[V2|Rest2]) -> 199 case reserved_objectid(V2,[]) of 200 V1 -> 201 check_objectidentifier1(Rest1,Rest2,[V1]); 202 V -> 203 throw({error,V}) 204 end. 205check_objectidentifier1([V|Rest1],[V|Rest2],Above) -> 206 check_objectidentifier1(Rest1,Rest2,[V|Above]); 207check_objectidentifier1([V1|Rest1],[V2|Rest2],Above) -> 208 case reserved_objectid(V2,Above) of 209 V1 -> 210 check_objectidentifier1(Rest1,Rest2,[V1|Above]); 211 V -> 212 throw({error,V}) 213 end; 214check_objectidentifier1([],[],_) -> 215 true; 216check_objectidentifier1(_,V,_) -> 217 throw({error,object,identifier,V}). 218 219%% ITU-T Rec. X.680 Annex B - D 220reserved_objectid('itu-t',[]) -> 0; 221reserved_objectid('ccitt',[]) -> 0; 222%% arcs below "itu-t" 223reserved_objectid('recommendation',[0]) -> 0; 224reserved_objectid('question',[0]) -> 1; 225reserved_objectid('administration',[0]) -> 2; 226reserved_objectid('network-operator',[0]) -> 3; 227reserved_objectid('identified-organization',[0]) -> 4; 228 229reserved_objectid(iso,[]) -> 1; 230%% arcs below "iso", note that number 1 is not used 231reserved_objectid('standard',[1]) -> 0; 232reserved_objectid('member-body',[1]) -> 2; 233reserved_objectid('identified-organization',[1]) -> 3; 234 235reserved_objectid('joint-iso-itu-t',[]) -> 2; 236reserved_objectid('joint-iso-ccitt',[]) -> 2; 237 238reserved_objectid(_,_) -> false. 239 240 241check_objectdescriptor(_,asn1_DEFAULT) -> 242 true; 243check_objectdescriptor(OD,OD) -> 244 true; 245check_objectdescriptor(OD,OD) -> 246 throw({error,{not_implemented_yet,check_objectdescriptor}}). 247 248check_real(_,asn1_DEFAULT) -> 249 true; 250check_real(R,R) -> 251 true; 252check_real(_,_) -> 253 throw({error,{not_implemented_yet,check_real}}). 254 255check_enum(_,asn1_DEFAULT,_) -> 256 true; 257check_enum(Val,Val,_) -> 258 true; 259check_enum(Int,Atom,Enumerations) when integer(Int),atom(Atom) -> 260 case lists:keysearch(Atom,1,Enumerations) of 261 {value,{_,Int}} -> true; 262 _ -> throw({error,{enumerated,Int,Atom}}) 263 end; 264check_enum(DefVal,Val,_) -> 265 throw({error,{enumerated,DefVal,Val}}). 266 267 268check_restrictedstring(_,asn1_DEFAULT) -> 269 true; 270check_restrictedstring(Val,Val) -> 271 true; 272check_restrictedstring([V|Rest1],[V|Rest2]) -> 273 check_restrictedstring(Rest1,Rest2); 274check_restrictedstring([V1|Rest1],[V2|Rest2]) -> 275 check_restrictedstring(V1,V2), 276 check_restrictedstring(Rest1,Rest2); 277%% tuple format of value 278check_restrictedstring({V1,V2},[V1,V2]) -> 279 true; 280check_restrictedstring([V1,V2],{V1,V2}) -> 281 true; 282%% quadruple format of value 283check_restrictedstring({V1,V2,V3,V4},[V1,V2,V3,V4]) -> 284 true; 285check_restrictedstring([V1,V2,V3,V4],{V1,V2,V3,V4}) -> 286 true; 287%% character string list 288check_restrictedstring(V1,V2) when list(V1),tuple(V2) -> 289 check_restrictedstring(V1,tuple_to_list(V2)); 290check_restrictedstring(V1,V2) -> 291 throw({error,{restricted,string,V1,V2}}). 292 293transform_to_EXTERNAL1990(Val) when tuple(Val),size(Val) == 4 -> 294 transform_to_EXTERNAL1990(tuple_to_list(Val),[]); 295transform_to_EXTERNAL1990(Val) when tuple(Val) -> 296 %% Data already in ASN1 1990 format 297 Val. 298 299transform_to_EXTERNAL1990(['EXTERNAL'|Rest],Acc) -> 300 transform_to_EXTERNAL1990(Rest,['EXTERNAL'|Acc]); 301transform_to_EXTERNAL1990([{syntax,Syntax}|Rest],Acc) -> 302 transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE,Syntax|Acc]); 303transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest],Acc) -> 304 transform_to_EXTERNAL1990(Rest,[PCid,asn1_NOVALUE|Acc]); 305transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest],Acc) -> 306 {_,Presentation_Cid,Transfer_syntax} = Context_negot, 307 transform_to_EXTERNAL1990(Rest,[Transfer_syntax,Presentation_Cid|Acc]); 308transform_to_EXTERNAL1990([asn1_NOVALUE|Rest],Acc) -> 309 transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE|Acc]); 310transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc) when list(Data_value)-> 311 list_to_tuple(lists:reverse([{'octet-aligned',Data_value}, 312 Data_val_desc|Acc])); 313transform_to_EXTERNAL1990([Data_value],Acc) when list(Data_value)-> 314 list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])). 315 316 317transform_to_EXTERNAL1994(V={'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}) -> 318 Identification = 319 case {DRef,IndRef} of 320 {DRef,asn1_NOVALUE} -> 321 {syntax,DRef}; 322 {asn1_NOVALUE,IndRef} -> 323 {'presentation-context-id',IndRef}; 324 _ -> 325 {'context-negotiation', 326 {'EXTERNAL_identification_context-negotiation',IndRef,DRef}} 327 end, 328 case Encoding of 329 {_,Val} when list(Val) -> 330 {'EXTERNAL',Identification,Data_v_desc,Val}; 331 _ -> 332 V 333 end. 334