ASN1.Mod 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. MODULE ASN1; (** AUTHOR "Patrick Hunziker"; PURPOSE "ISO 8824/8825 standard tag/length/data encoding"; *)
  2. (* ASN1(Abstract Syntax Notation One) is a standard that defines a formalism for the specification of abstract data types.
  3. PROCEDURE Decode(ASN1Stream):Triplet produces a hierarchical tree with triple.next and triplet.child dependencies.*)
  4. (*to do: correctly decode big integer numbers which do not fit into standard oberon types*)
  5. (*to do for more general ASN1 implementation: bit strings of undefined length: see ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc; not needed for certifcates*)
  6. (*refine standard OIDs as hex constants, for direct comparison*)
  7. (*to do: encoding *)
  8. IMPORT Streams;
  9. CONST
  10. Trace=FALSE;
  11. (*ASN1 class*)
  12. ASN1Universal*=0;
  13. ASN1Application*=1;
  14. ASN1Context*=2;
  15. ASN1Private*=3;
  16. (*
  17. BER_TAG_UNKNOWN 0
  18. BER_TAG_BOOLEAN 1
  19. BER_TAG_INTEGER 2
  20. BER_TAG_BIT_STRING 3
  21. BER_TAG_OCTET_STRING 4
  22. BER_TAG_NULL 5
  23. BER_TAG_OID 6
  24. BER_TAG_OBJECT_DESCRIPTOR 7
  25. BER_TAG_EXTERNAL 8
  26. BER_TAG_REAL 9
  27. BER_TAG_ENUMERATED 10
  28. 12 to 15 are reserved for future versions of the recommendation
  29. BER_TAG_PKIX_UTF8_STRING 12
  30. BER_TAG_SEQUENCE 16
  31. BER_TAG_SET 17
  32. BER_TAG_NUMERIC_STRING 18
  33. BER_TAG_PRINTABLE_STRING 19
  34. BER_TAG_T61_STRING 20
  35. BER_TAG_TELETEX_STRING BER_TAG_T61_STRING
  36. BER_TAG_VIDEOTEX_STRING 21
  37. BER_TAG_IA5_STRING 22
  38. BER_TAG_UTC_TIME 23
  39. BER_TAG_GENERALIZED_TIME 24
  40. BER_TAG_GRAPHIC_STRING 25
  41. BER_TAG_ISO646_STRING 26
  42. BER_TAG_GENERAL_STRING 27
  43. BER_TAG_VISIBLE_STRING BER_TAG_ISO646_STRING
  44. 28 - are reserved for future versions of the recommendation
  45. BER_TAG_PKIX_UNIVERSAL_STRING 28
  46. BER_TAG_PKIX_BMP_STRING 30
  47. *)
  48. Boolean* =1H;
  49. Integer* =2H;
  50. BitString* =3H;
  51. (*
  52. BIT STRING: BER encoding. Primitive or constructed.
  53. In a primitive encoding, the first contents octet gives the number of bits by which the length of the bit string
  54. is less than the next multiple of eight (this is called the "number of unused bits").
  55. The second and following contents octets give the value of the bit string, converted to an octet string.
  56. The conversion process is as follows:
  57. 1. The bit string is padded after the last bit with zero to seven bits of any value to make the length
  58. of the bit string a multiple of eight. If the length of the bit string is a multiple of eight
  59. already, no padding is done.
  60. 2. The padded bit string is divided into octets. The first eight bits of the padded bit string become
  61. the first octet, bit 8 to bit 1, and so on through the last eight bits of the padded bit string.
  62. In a constructed encoding, the contents octets give the concatenation of the BER encodings of consecutive substrings
  63. of the bit string, where each substring except the last has a length that is a multiple of eight bits.
  64. Example: The BER encoding of the BIT STRING value "011011100101110111" can be any of the following, among
  65. others, depending on the choice of padding bits, the form of length octets, and whether the encoding is primitive or constructed:
  66. 03 04 06 6e 5d c0 DER encoding
  67. 03 04 06 6e 5d e0 padded with "100000"
  68. 03 81 04 06 6e 5d c0 long form of length octets
  69. 23 09 constructed encoding: "0110111001011101" + "11"
  70. 03 03 00 6e 5d
  71. 03 02 06 c0
  72. DER encoding. Primitive.
  73. The contents octects are as for a primitive BER encoding, except that the bit string is padded with zero-valued bits.
  74. Example: The DER encoding of the BIT STRING value "011011100101110111" is 03 04 06 6e 5d c0
  75. *)
  76. String* =4H;
  77. Null* =5H;
  78. Oid* =6H;
  79. UTF8* =0CH;
  80. PrintableString* =13H;
  81. TeletexString* =14H;
  82. IA5String*=16H;
  83. (*
  84. UTCTime
  85. The UTCTime type denotes a coordinated universal time or Greenwich Mean Time (GMT) value. A UTCTime value includes
  86. the local time precise to either minutes or seconds, and an offset from GMT in hours and minutes. It takes any of the
  87. following forms:
  88. YYMMDDhhmmZ
  89. YYMMDDhhmm+hh'mm'
  90. YYMMDDhhmm-hh'mm'
  91. YYMMDDhhmmssZ
  92. YYMMDDhhmmss+hh'mm'
  93. YYMMDDhhmmss-hh'mm'
  94. *)
  95. UTCTime* =17H;
  96. BMPString* =1EH;
  97. Sequence* =30H;
  98. Set* =31H;
  99. TYPE CharString*=POINTER TO ARRAY OF CHAR;
  100. (* data element in DER encoded certificates: tag[class+type] - length[1..n bytes] - value[0..n bytes] *)
  101. TYPE Triplet* = OBJECT (* todo: 1 Byte tags are sufficient for certificates, but in general, multiple byte tags may occur in other contexts *)
  102. VAR tag*:LONGINT;
  103. class*:LONGINT;
  104. length*:LONGINT;
  105. unusedbits*:LONGINT;
  106. constructed*:BOOLEAN;
  107. definite*: BOOLEAN;
  108. bvalue*:BOOLEAN;
  109. ivalue*:LONGINT;
  110. svalue*:POINTER TO ARRAY OF CHAR;
  111. child*, curchild:Triplet;
  112. next*:Triplet;
  113. level*:LONGINT; (*pretty print*)
  114. PROCEDURE AppendChild*(t:Triplet);
  115. BEGIN
  116. IF child=NIL THEN child:=t; curchild:=t ELSE curchild.next:=t; curchild:=t; END;
  117. END AppendChild;
  118. PROCEDURE Print*(w: Streams.Writer);
  119. VAR i:LONGINT;
  120. BEGIN
  121. w.Char(09X);
  122. FOR i:=0 TO level-1 DO w.String("- "); END;
  123. w.Hex(tag,4); w.String("H[");
  124. w.Int(length,0); w.String("]");
  125. CASE tag OF
  126. | Boolean: IF bvalue THEN w.String("true") ELSE w.String("false") END;
  127. | Integer: IF length<=4 THEN w.Int(ivalue,0);ELSE PrintHexString(w,svalue^) END;
  128. | Oid: PrintNumericString(w, svalue^); w.String(" "); PrintHexString(w, svalue^);
  129. | PrintableString: PrintString(w,svalue^);
  130. | UTCTime: PrintString(w,svalue^);
  131. | BitString: w.Char("("); w.Int(unusedbits,0); w.Char(")"); IF svalue#NIL THEN PrintHexString(w, svalue^) END;
  132. | Sequence, Set:
  133. ELSE
  134. IF svalue#NIL THEN PrintHexString(w,svalue^);END;
  135. END;
  136. w.Ln;
  137. END Print;
  138. END Triplet;
  139. VAR log*: Streams.Writer;
  140. PROCEDURE PrintHexString*(w:Streams.Writer; CONST s: ARRAY OF CHAR);
  141. CONST hex="0123456789ABCDEF";
  142. VAR i:LONGINT; c:CHAR;
  143. BEGIN
  144. FOR i:=0 TO LEN(s)-1 DO
  145. c:=s[i];
  146. w.Char(hex[ORD(c) DIV 16]);
  147. w.Char(hex[ORD(c) MOD 16]);
  148. w.Char(" ");
  149. END;
  150. END PrintHexString;
  151. PROCEDURE PrintNumericString*(w:Streams.Writer; CONST s: ARRAY OF CHAR);
  152. VAR i:LONGINT; c:CHAR;
  153. BEGIN
  154. w.String(" ");
  155. FOR i:=0 TO LEN(s)-1 DO
  156. c:=s[i];
  157. w.Int(ORD(c),0);
  158. w.Char(".");
  159. END;
  160. END PrintNumericString;
  161. PROCEDURE PrintString*(w:Streams.Writer; CONST s: ARRAY OF CHAR);
  162. VAR i:LONGINT; c:CHAR;
  163. BEGIN
  164. FOR i:=0 TO LEN(s)-1 DO
  165. c:=s[i];
  166. IF (ORD(c)>=20H) & (ORD(c)<=7EH) THEN w.Char(c) ELSE w.Char("."); END;
  167. END;
  168. END PrintString;
  169. PROCEDURE Decode*(reader:Streams.Reader; level:LONGINT; VAR len:LONGINT): Triplet;
  170. VAR t,t1:Triplet; lengthbytes,len0,hdrlen:LONGINT; i:LONGINT; c:CHAR;
  171. BEGIN
  172. NEW(t); t.level:=level;
  173. len:=0; hdrlen:=0;
  174. reader.Char(c); INC(len); INC(hdrlen);
  175. IF Trace & (log#NIL) THEN log.Char("{"); log.Hex(ORD(c),0);log.Char("H"); log.Char("}"); END;
  176. t.class:= ORD(c) DIV 64;
  177. t.constructed:= ODD (ORD(c) DIV 32);
  178. IF ORD(c) MOD 32#31 THEN t.tag:=ORD(c) MOD 64; (* 'constructed' bit included *)
  179. ELSE
  180. REPEAT
  181. reader.Char(c); INC(len); INC(hdrlen);
  182. t.tag:=t.tag*128+ ORD(c) MOD 128;
  183. UNTIL ORD(c) DIV 128 # 1;
  184. END;
  185. reader.Char(c); INC(len); INC(hdrlen);
  186. IF ORD(c)<128 THEN t.length:=ORD(c); t.definite:=TRUE;
  187. ELSIF ORD(c)=128 THEN t.definite:=FALSE;
  188. (* to do: class=0, length=0 is used to encode end of bit stream of undefined length, see ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc*)
  189. ELSE
  190. lengthbytes:= ORD(c) MOD 128; t.definite:=TRUE;
  191. FOR i:=0 TO lengthbytes-1 DO (* read all length bytes here ...*)
  192. t.length:=256*t.length;
  193. reader.Char(c); INC(len); INC(hdrlen);
  194. t.length:=t.length+ORD(c);
  195. END;
  196. END;
  197. CASE t.tag OF
  198. | Boolean: reader.Char(c);INC(len); t.bvalue:=c#0X;
  199. | Integer:
  200. IF t.length<=4 THEN
  201. NEW(t.svalue,t.length);
  202. FOR i:=0 TO t.length-1 DO
  203. t.ivalue:=256*t.ivalue;
  204. reader.Char(c); INC(len);
  205. t.svalue[i]:=c;
  206. t.ivalue:=t.ivalue+ORD(c);
  207. END;
  208. ELSE
  209. NEW(t.svalue,t.length);
  210. reader.Bytes(t.svalue^,0,t.length,len0); len:=len+len0;
  211. END;
  212. | BitString:
  213. reader.Char(c); t.unusedbits:=ORD(c); INC(len);
  214. IF FALSE & (ORD(reader.Peek())=30H) (*rsa bit string 1024b*) THEN (*unreliable hack. to do: pass info about recursive bitstring to child*)
  215. IF Trace & (log#NIL) THEN log.String("(BitSRec "); log.Int(len,0); log.String(")");t.Print(log); END;
  216. t.child:=Decode(reader,level+1, len0); len:=len+len0;
  217. ELSE
  218. NEW(t.svalue,t.length-1);
  219. IF t.length>0 THEN reader.Bytes(t.svalue^,0,t.length-1,len0); len:=len+len0; END;
  220. END;
  221. | String:
  222. NEW(t.svalue,t.length);
  223. reader.Bytes(t.svalue^,0,t.length,len0);len:=len+len0;
  224. | Set:
  225. IF Trace & (log#NIL) THEN log.String("(Set "); log.Int(len,0); log.String("+)"); t.Print(log); END; (*bytes not including body*)
  226. t.child:=Decode(reader,level+1, len0);len:=len+len0;
  227. | Sequence:
  228. IF Trace & (log#NIL) THEN log.String("(Seq "); log.Int(len,0); log.String("+)"); t.Print(log); END; (*bytes not including body*)
  229. WHILE len-hdrlen<t.length DO
  230. t1:=Decode(reader,level+1, len0); len:=len+len0;
  231. (*t1.next:=t.next; t.next:=t1;*)
  232. t.AppendChild(t1);
  233. END;
  234. ELSE
  235. NEW(t.svalue,t.length);
  236. IF t.length>0 THEN reader.Bytes(t.svalue^,0,t.length,len0); len:=len+len0; END;
  237. END;
  238. IF Trace & (log#NIL) THEN
  239. CASE t.tag OF
  240. | Integer: log.String("(Integer "); log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  241. | BitString:
  242. IF t.constructed THEN log.String("(constrBitString "); ELSE log.String("(BitString "); END;
  243. log.Int(len,4); log.Char(")"); t.Print(log); (*bytes including header*)
  244. | String: log.String("(String ");log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  245. | Null: log.String("(Null ");log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  246. | Oid: log.String("(OID");log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  247. | PrintableString: log.String("(Printable");log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  248. | UTCTime: log.String("(UTCTime");log.Int(len,4); log.Char(")"); t.Print(log);(*bytes including header*)
  249. | Set:
  250. | Sequence:
  251. ELSE log.String("(t.tag="); log.Hex(t.tag,4);log.Int(len,4); log.Char(")"); t.Print(log); (*bytes including header*)
  252. END;
  253. END;
  254. RETURN t
  255. END Decode;
  256. END ASN1.