a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
4e151b2008-05-02Martin Nilsson #pragma strict_types
dce3662003-01-27Martin Nilsson #define COMPATIBILITY
a20af62000-09-26Fredrik Hübinette (Hubbe) 
6e91d92002-12-05H. William Welliver III //! Decodes a DER object.
3e031f1998-06-13Niels Möller 
0d17372003-01-26Martin Nilsson //! Primitive unconstructed ASN1 data type.
8325042007-12-27Martin Nilsson class Primitive
3e031f1998-06-13Niels Möller {
bc0dc22003-07-23Henrik Grubbström (Grubba)  //! @decl inherit Types.Object
8325042007-12-27Martin Nilsson  inherit .Types.Object;
bc0dc22003-07-23Henrik Grubbström (Grubba) 
0d17372003-01-26Martin Nilsson  constant constructed = 0;
1ec5d61999-03-22Niels Möller  int combined_tag;
6e91d92002-12-05H. William Welliver III 
1ec5d61999-03-22Niels Möller  string raw;
17e7422003-01-26Martin Nilsson 
0d17372003-01-26Martin Nilsson  //! get raw encoded contents of object
3e031f1998-06-13Niels Möller  string get_der() { return raw; }
1ec5d61999-03-22Niels Möller  int get_combined_tag() { return combined_tag; }
6e91d92002-12-05H. William Welliver III 
0d17372003-01-26Martin Nilsson  //! get tag
8325042007-12-27Martin Nilsson  int get_tag() { return .Types.extract_tag(combined_tag); }
6e91d92002-12-05H. William Welliver III 
0d17372003-01-26Martin Nilsson  //! get class
8325042007-12-27Martin Nilsson  int get_cls() { return .Types.extract_cls(combined_tag); }
17e7422003-01-26Martin Nilsson 
0d17372003-01-26Martin Nilsson  void create(int t, string r) { combined_tag = t; raw = r; }
dee37a1998-08-19Niels Möller 
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
dce3662003-01-27Martin Nilsson  return t=='O' && sprintf("%O(%d)", this_program, combined_tag); } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
0d17372003-01-26Martin Nilsson  return sprintf("primitive(%d)", combined_tag); }
dce3662003-01-27Martin Nilsson #endif
3e031f1998-06-13Niels Möller }
8325042007-12-27Martin Nilsson //! Constructed type class Constructed
3e031f1998-06-13Niels Möller {
3a10622013-09-02Martin Nilsson  inherit .Types.Compound;
b2bc5b2013-10-21Martin Nilsson  constant type_name = "CONSTRUCTED";
bc0dc22003-07-23Henrik Grubbström (Grubba) 
1ec5d61999-03-22Niels Möller  int combined_tag;
17e7422003-01-26Martin Nilsson 
0d17372003-01-26Martin Nilsson  //! raw encoded contents
3e031f1998-06-13Niels Möller  string raw;
6e91d92002-12-05H. William Welliver III 
3e031f1998-06-13Niels Möller  string get_der() { return raw; }
1ec5d61999-03-22Niels Möller  int get_combined_tag() { return combined_tag; }
6e91d92002-12-05H. William Welliver III 
0d17372003-01-26Martin Nilsson  //! get tag
8325042007-12-27Martin Nilsson  int get_tag() { return .Types.extract_tag(combined_tag); }
6e91d92002-12-05H. William Welliver III 
0d17372003-01-26Martin Nilsson  //! get class
8325042007-12-27Martin Nilsson  int get_cls() { return .Types.extract_cls(combined_tag); }
3e031f1998-06-13Niels Möller 
3a10622013-09-02Martin Nilsson  void create(int t, string r, array(.Types.Object) e) {
0d17372003-01-26Martin Nilsson  combined_tag = t; raw = r; elements = e; }
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! @param data //! an instance of ADT.struct //! @param types
17e7422003-01-26Martin Nilsson //! a mapping from combined tag numbers to classes from or derived from //! @[Standards.ASN1.Types]. Combined tag numbers may be generated using
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Types.make_combined_tag]. //! //! @returns
17e7422003-01-26Martin Nilsson //! an object from @[Standards.ASN1.Types] or
8325042007-12-27Martin Nilsson //! either @[Standards.ASN1.Decode.Primitive] or
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Decode.constructed] if the type is unknown. //! Throws an exception if the data could not be decoded.
17e7422003-01-26Martin Nilsson //!
6e91d92002-12-05H. William Welliver III //! @fixme //! Handling of implicit and explicit ASN.1 tagging, as well as //! other context dependence, is next to non_existant.
8325042007-12-27Martin Nilsson .Types.Object der_decode(ADT.struct data, mapping(int:program(.Types.Object)) types)
3e031f1998-06-13Niels Möller { int raw_tag = data->get_uint(1); int len;
d74f032013-12-08Henrik Grubbström (Grubba)  string(0..255) contents;
3e031f1998-06-13Niels Möller  #ifdef ASN1_DEBUG
0d17372003-01-26Martin Nilsson  werror("decoding raw_tag %x\n", raw_tag);
3e031f1998-06-13Niels Möller #endif if ( (raw_tag & 0x1f) == 0x1f)
0d17372003-01-26Martin Nilsson  error("High tag numbers is not supported\n");
3e031f1998-06-13Niels Möller 
e42b872000-09-05Per Hedbor  len = data->get_uint(1);
3e031f1998-06-13Niels Möller  if (len & 0x80) len = data->get_uint(len & 0x7f);
17e7422003-01-26Martin Nilsson 
3e031f1998-06-13Niels Möller #ifdef ASN1_DEBUG
0d17372003-01-26Martin Nilsson  werror("len : %d\n", len);
3e031f1998-06-13Niels Möller #endif contents = data->get_fix_string(len);
17e7422003-01-26Martin Nilsson 
3e031f1998-06-13Niels Möller #ifdef ASN1_DEBUG
0d17372003-01-26Martin Nilsson  werror("contents: %O\n", contents);
3e031f1998-06-13Niels Möller #endif
8325042007-12-27Martin Nilsson  int tag = .Types.make_combined_tag(raw_tag >> 6, raw_tag & 0x1f);
1ec5d61999-03-22Niels Möller 
8325042007-12-27Martin Nilsson  program(.Types.Object) p = types[tag];
17e7422003-01-26Martin Nilsson 
dee37a1998-08-19Niels Möller  if (raw_tag & 0x20)
3e031f1998-06-13Niels Möller  { /* Constructed encoding */
dee37a1998-08-19Niels Möller #ifdef ASN1_DEBUG werror("Decoding constructed\n"); #endif
8325042007-12-27Martin Nilsson  array(.Types.Object) elements = ({ });
0d17372003-01-26Martin Nilsson  ADT.struct struct = ADT.struct(contents);
17e7422003-01-26Martin Nilsson 
3e031f1998-06-13Niels Möller  if (!p) {
dee37a1998-08-19Niels Möller #ifdef ASN1_DEBUG werror("Unknown constructed type\n"); #endif
3e031f1998-06-13Niels Möller  while (!struct->is_empty()) elements += ({ der_decode(struct, types) }); return constructed(tag, contents, elements); }
8325042007-12-27Martin Nilsson  .Types.Object res = p();
3e031f1998-06-13Niels Möller  res->begin_decode_constructed(contents);
17e7422003-01-26Martin Nilsson 
3e031f1998-06-13Niels Möller  int i;
0d17372003-01-26Martin Nilsson  // Ask object which types it expects for field i, decode it, and // record the decoded object
3e031f1998-06-13Niels Möller  for(i = 0; !struct->is_empty(); i++)
dee37a1998-08-19Niels Möller  { #ifdef ASN1_DEBUG
0d17372003-01-26Martin Nilsson  werror("Element %d\n", i);
dee37a1998-08-19Niels Möller #endif
3e031f1998-06-13Niels Möller  res->decode_constructed_element (i, der_decode(struct, res->element_types(i, types)));
dee37a1998-08-19Niels Möller  }
9fe6161998-06-13Henrik Grubbström (Grubba)  return res->end_decode_constructed(i);
3e031f1998-06-13Niels Möller  }
0d17372003-01-26Martin Nilsson 
dee37a1998-08-19Niels Möller #ifdef ASN1_DEBUG
8325042007-12-27Martin Nilsson  werror("Decoding Primitive\n");
dee37a1998-08-19Niels Möller #endif
0d17372003-01-26Martin Nilsson  // Primitive encoding
7a00e72008-04-25Henrik Grubbström (Grubba)  return p ? p()->decode_primitive(contents, this_object(), types)
8325042007-12-27Martin Nilsson  : Primitive(tag, contents);
3e031f1998-06-13Niels Möller }
8325042007-12-27Martin Nilsson #define U(x) .Types.make_combined_tag(0, (x)) mapping(int:program(.Types.Object)) universal_types = ([ U(1) : .Types.Boolean, U(2) : .Types.Integer, U(3) : .Types.BitString, U(4) : .Types.OctetString, U(5) : .Types.Null, U(6) : .Types.Identifier, // U(9) : .Types.Real, // U(10) : .Types.Enumerated, U(12) : .Types.UTF8String, U(16) : .Types.Sequence, U(17) : .Types.Set, U(19) : .Types.PrintableString, U(20) : .Types.TeletexString, // or broken_teletexString? U(22) : .Types.IA5String, U(23) : .Types.UTC, U(28) : .Types.UniversalString, U(30) : .Types.BMPString,
1ec5d61999-03-22Niels Möller  ]);
3e031f1998-06-13Niels Möller 
6e91d92002-12-05H. William Welliver III //! decode a DER encoded object using universal data types //! //! @param data //! a DER encoded object //! @returns
17e7422003-01-26Martin Nilsson //! an object from @[Standards.ASN1.Types] or
8325042007-12-27Martin Nilsson //! either @[Standards.ASN1.Decode.Primitive] or
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Decode.constructed] if the type is unknown.
d74f032013-12-08Henrik Grubbström (Grubba) .Types.Object simple_der_decode(string(0..255) data)
3e031f1998-06-13Niels Möller {
1ec5d61999-03-22Niels Möller  return der_decode(ADT.struct(data), universal_types);
3e031f1998-06-13Niels Möller }
92dbd31999-08-24Fredrik Hübinette (Hubbe) 
8325042007-12-27Martin Nilsson #ifdef COMPATIBILITY constant primitive = Primitive; constant constructed = Constructed; #endif