6e91d92002-12-05H. William Welliver III //! Encodes various asn.1 objects according to the Distinguished //! Encoding Rules (DER)
a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
4e151b2008-05-02Martin Nilsson #pragma strict_types
3980c72003-01-26Martin Nilsson #define COMPATIBILITY
a20af62000-09-26Fredrik Hübinette (Hubbe) 
3e031f1998-06-13Niels Möller #if 0 #define WERROR werror #else
fa323d2004-02-29Martin Nilsson #define WERROR(x ...)
3e031f1998-06-13Niels Möller #endif
1ec5d61999-03-22Niels Möller 
3980c72003-01-26Martin Nilsson // Helper functions
1ec5d61999-03-22Niels Möller 
240d3e2014-06-10Martin Nilsson //! Combines tag and class to a single integer, for intenal uses.
17e7422003-01-26Martin Nilsson //!
6e91d92002-12-05H. William Welliver III //! @param cls
240d3e2014-06-10Martin Nilsson //! ASN1 type class (0..3).
6e91d92002-12-05H. William Welliver III //! @param tag
240d3e2014-06-10Martin Nilsson //! ASN1 type tag (1..).
6e91d92002-12-05H. William Welliver III //! @returns
240d3e2014-06-10Martin Nilsson //! The combined tag.
17e7422003-01-26Martin Nilsson //! @seealso
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Types.extract_tag] //! @[Standards.ASN1.Types.extract_cls]
1ec5d61999-03-22Niels Möller int make_combined_tag(int cls, int tag)
372d652014-06-09Martin Nilsson { return tag << 2 | cls; }
1ec5d61999-03-22Niels Möller 
240d3e2014-06-10Martin Nilsson //! Extract ASN1 type tag from a combined tag.
17e7422003-01-26Martin Nilsson //! @seealso
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Types.make_combined_tag]
1ec5d61999-03-22Niels Möller int extract_tag(int i) { return i >> 2; }
6e91d92002-12-05H. William Welliver III 
240d3e2014-06-10Martin Nilsson //! Extract ASN1 type class from a combined tag.
17e7422003-01-26Martin Nilsson //! @seealso
6e91d92002-12-05H. William Welliver III //! @[Standards.ASN1.Types.make_combined_tag]
240d3e2014-06-10Martin Nilsson int(0..3) extract_cls(int i) { return [int(0..3)](i & 3); }
1ec5d61999-03-22Niels Möller 
3980c72003-01-26Martin Nilsson  // Class definitions //! Generic, abstract base class for ASN1 data types. class Object
3e031f1998-06-13Niels Möller {
39fddc2014-06-09Martin Nilsson  int cls = 0; int tag = 0;
3e031f1998-06-13Niels Möller  constant constructed = 0;
8856fc2014-02-21Henrik Grubbström (Grubba)  constant type_name = ""; //! Return the DER payload. string(8bit) get_der_content() { return ""; } string(0..255) der_encode() { return build_der(get_der_content()); }
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! Get the class of this object. //! //! @returns //! The class of this object.
3e031f1998-06-13Niels Möller  int get_cls() { return cls; }
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! Get the tag for this object. //! //! @returns //! The tag for this object.
3e031f1998-06-13Niels Möller  int get_tag() { return tag; }
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! Get the combined tag (tag + class) for this object. //! //! @returns //! the combined tag header int get_combined_tag() {
8c92912014-01-19Henrik Grubbström (Grubba)  return make_combined_tag(get_cls(), get_tag());
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  string(0..255) der;
17e7422003-01-26Martin Nilsson  // Should be overridden by subclasses
12e4902008-04-22Henrik Grubbström (Grubba)  this_program decode_primitive(string contents, function(ADT.struct, mapping(int:program(Object)): Object) decoder, mapping(int:program(Object)) types);
f49ea82003-01-27Martin Nilsson  this_program begin_decode_constructed(string raw); this_program decode_constructed_element(int i, object e); this_program end_decode_constructed(int length);
3e031f1998-06-13Niels Möller 
c485aa2003-01-27Martin Nilsson  mapping(int:program(Object)) element_types(int i, mapping(int:program(Object)) types) {
7991f12008-01-05Henrik Grubbström (Grubba)  return types; i;
c485aa2003-01-27Martin Nilsson  }
7991f12008-01-05Henrik Grubbström (Grubba)  this_program init(mixed ... args) { return this; args; }
3980c72003-01-26Martin Nilsson 
240d3e2014-06-10Martin Nilsson  protected string(0..255) to_base_128(int n)
d74f032013-12-08Henrik Grubbström (Grubba)  {
240d3e2014-06-10Martin Nilsson  string(0..255) ret = [string(0..127)]sprintf("%c", n&0x7f); n >>= 7; while( n )
3e031f1998-06-13Niels Möller  {
240d3e2014-06-10Martin Nilsson  ret = [string(0..255)]sprintf("%c", (n&0x7f) | 0x80) + ret;
3980c72003-01-26Martin Nilsson  n >>= 7;
3e031f1998-06-13Niels Möller  }
240d3e2014-06-10Martin Nilsson  return ret;
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
240d3e2014-06-10Martin Nilsson  protected string(0..255) encode_tag()
d74f032013-12-08Henrik Grubbström (Grubba)  {
3980c72003-01-26Martin Nilsson  int tag = get_tag(); int cls = get_cls(); if (tag < 31)
d74f032013-12-08Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%c", (cls << 6) | (constructed << 5) | tag);
3980c72003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%c%s", (cls << 6) | (constructed << 5) | 0x1f, to_base_128(tag) );
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
240d3e2014-06-10Martin Nilsson  protected string(0..255) encode_length(int|object len)
d74f032013-12-08Henrik Grubbström (Grubba)  {
3980c72003-01-26Martin Nilsson  if (len < 0x80)
d74f032013-12-08Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%c", len);
3980c72003-01-26Martin Nilsson  string s = Gmp.mpz(len)->digits(256); if (sizeof(s) >= 0x80) error("Max length exceeded.\n" );
d74f032013-12-08Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%c%s", sizeof(s) | 0x80, s);
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
240d3e2014-06-10Martin Nilsson  protected string(0..255) build_der(string(0..255) contents)
d74f032013-12-08Henrik Grubbström (Grubba)  { string(0..255) data = encode_tag() + encode_length(sizeof(contents)) + contents;
fa323d2004-02-29Martin Nilsson  WERROR("build_der: %O\n", data);
3980c72003-01-26Martin Nilsson  return data; }
3e031f1998-06-13Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  __deprecated__ string(0..255) record_der(string(0..255) s) {
3980c72003-01-26Martin Nilsson  return (der = s); }
0ecedd1999-03-23Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  void record_der_contents(string(0..255) s) {
983ea12013-12-04Martin Nilsson  der = build_der(s);
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
0a38772004-01-26H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! Get the DER encoded version of this object. //! //! @returns //! DER encoded representation of this object.
d74f032013-12-08Henrik Grubbström (Grubba)  string(0..255) get_der() {
983ea12013-12-04Martin Nilsson  return der || (der = der_encode());
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
33dd5f2014-02-11Henrik Grubbström (Grubba)  protected void create(mixed ...args) {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_object[%s]->create\n", type_name);
3980c72003-01-26Martin Nilsson  if (sizeof(args)) init(@args); }
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! Compound object primitive
3980c72003-01-26Martin Nilsson class Compound
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
3e031f1998-06-13Niels Möller  constant constructed = 1;
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! contents of compound object, elements are from @[Standards.ASN1.Types]
0324132004-01-27Martin Nilsson  array(Object) elements = ({ });
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson  this_program init(array args) {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_compound[%s]->init(%O)\n", type_name, args);
3980c72003-01-26Martin Nilsson  foreach(args, mixed o) if (!objectp(o))
6725f52013-11-22Martin Nilsson  error( "Non-object argument %O\n", o );
009d772004-02-22Martin Nilsson  elements = [array(Object)]args;
fa323d2004-02-29Martin Nilsson  WERROR("asn1_compound: %O\n", elements);
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program begin_decode_constructed(string(0..255) raw) {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_compound[%s]->begin_decode_constructed\n", type_name);
3980c72003-01-26Martin Nilsson  record_der_contents(raw);
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson  this_program decode_constructed_element(int i, object e) {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_compound[%s]->decode_constructed_element(%O)\n", type_name, e);
3980c72003-01-26Martin Nilsson  if (i != sizeof(elements)) error("Unexpected index!\n"); elements += ({ e });
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  this_program end_decode_constructed(int length) { if (length != sizeof(elements)) error("Invalid length!\n");
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
d01fbe2013-08-30Martin Nilsson  protected mixed `[](mixed index) { if( intp(index) ) return elements[index]; return ::`[]([string]index); } protected int _sizeof() { return sizeof(elements); }
36261f2013-03-01Chris Angelico  protected string _sprintf(int t,mapping(string:int)|void params) { if (params) ++params->indent; else params=([]);
eac0f72013-11-28Martin Nilsson  return t=='O' && sprintf("%O(%*O)", this_program, params, elements);
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_compound[%s]->debug_string(), elements = %O\n", type_name, elements);
3980c72003-01-26Martin Nilsson  return _sprintf('O'); } #endif
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! string object primitive
3980c72003-01-26Martin Nilsson class String
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! value of object
3e031f1998-06-13Niels Möller  string value;
d74f032013-12-08Henrik Grubbström (Grubba)  this_program init(string(0..255) s) {
3980c72003-01-26Martin Nilsson  value = s;
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content() { return [string(0..255)]value;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents); value = contents;
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
6725f52013-11-22Martin Nilsson  return t=='O' && sprintf("%O(%O)", this_program, value);
3980c72003-01-26Martin Nilsson  } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_string[%s]->debug_string(), value = %O\n", type_name, value);
3980c72003-01-26Martin Nilsson  return _sprintf('O'); } #endif
3e031f1998-06-13Niels Möller } // FIXME: What is the DER-encoding of TRUE???
47b5911999-02-19Niels Möller // According to Jan Petrous, the LDAP spec says that 0xff is right.
ffbc622003-01-28Martin Nilsson // No, every nonzero value is true according to the ASN1 spec, // but they use 0xff as example of a true value. /Nilsson
3e031f1998-06-13Niels Möller 
6e91d92002-12-05H. William Welliver III //! boolean object
3980c72003-01-26Martin Nilsson class Boolean
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
39fddc2014-06-09Martin Nilsson  int tag = 1;
3e031f1998-06-13Niels Möller  constant type_name = "BOOLEAN";
3980c72003-01-26Martin Nilsson  //! value of object
3e031f1998-06-13Niels Möller  int value;
17e7422003-01-26Martin Nilsson 
12e4902008-04-22Henrik Grubbström (Grubba)  this_program init(int x) { value = x; return this; }
3e031f1998-06-13Niels Möller 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content() { return value ? "\377" : "\0";
12e4902008-04-22Henrik Grubbström (Grubba)  }
3980c72003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents);
b935cc2014-06-10Martin Nilsson  if( contents=="" ) error("Illegal boolean value.\n");
12e4902008-04-22Henrik Grubbström (Grubba)  value = (contents != "\0");
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
3980c72003-01-26Martin Nilsson  return t=='O' && sprintf("%O(%s)", this_program, (value?"TRUE":"FALSE")); } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
3980c72003-01-26Martin Nilsson  return value ? "TRUE" : "FALSE"; } #endif
3e031f1998-06-13Niels Möller }
3980c72003-01-26Martin Nilsson 
17e7422003-01-26Martin Nilsson //! Integer object
6e91d92002-12-05H. William Welliver III //! All integers are represented as bignums, for simplicity
3980c72003-01-26Martin Nilsson class Integer
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
39fddc2014-06-09Martin Nilsson  int tag = 2;
3e031f1998-06-13Niels Möller  constant type_name = "INTEGER";
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  //! value of object Gmp.mpz value;
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson  this_object init(int|object n) { value = Gmp.mpz(n);
fa323d2004-02-29Martin Nilsson  WERROR("i = %s\n", value->digits());
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  { string(0..255) s;
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  if (value < 0)
3e031f1998-06-13Niels Möller  {
009d772004-02-22Martin Nilsson  Gmp.mpz n = [object(Gmp.mpz)](value + pow(256, ([object(Gmp.mpz)](- value))-> size(256)));
3980c72003-01-26Martin Nilsson  s = n->digits(256); if (!(s[0] & 0x80)) s = "\377" + s; } else { s = value->digits(256); if (s[0] & 0x80) s = "\0" + s;
3e031f1998-06-13Niels Möller  }
8856fc2014-02-21Henrik Grubbström (Grubba)  return s;
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  this_object decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents); value = Gmp.mpz(contents, 256); if (contents[0] & 0x80) /* Negative */ value -= pow(256, sizeof(contents));
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
3980c72003-01-26Martin Nilsson  return t=='O' && sprintf("%O(%d %s)", this_program, value->size(), value->digits()); } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
3980c72003-01-26Martin Nilsson  return sprintf("INTEGER (%d) %s", value->size(), value->digits()); } #endif
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III  //! Enumerated object
3980c72003-01-26Martin Nilsson class Enumerated
47b5911999-02-19Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Integer;
39fddc2014-06-09Martin Nilsson  int tag = 10;
47b5911999-02-19Niels Möller  constant type_name ="ENUMERATED"; }
3e031f1998-06-13Niels Möller 
6e91d92002-12-05H. William Welliver III //! Bit string object
3980c72003-01-26Martin Nilsson class BitString
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
39fddc2014-06-09Martin Nilsson  int tag = 3;
3e031f1998-06-13Niels Möller  constant type_name = "BIT STRING";
6e91d92002-12-05H. William Welliver III 
3980c72003-01-26Martin Nilsson  //! value of object
d74f032013-12-08Henrik Grubbström (Grubba)  string(0..255) value;
6e91d92002-12-05H. William Welliver III 
3e031f1998-06-13Niels Möller  int unused = 0;
17e7422003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program init(string(0..255) s) {
12e4902008-04-22Henrik Grubbström (Grubba)  value = s; return this; }
3e031f1998-06-13Niels Möller 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  {
8856fc2014-02-21Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%c%s", unused, value);
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
78e4182004-02-22Martin Nilsson  //! Set the bitstring value as a string with @expr{"1"@} and //! @expr{"0"@}.
d74f032013-12-08Henrik Grubbström (Grubba)  this_program set_from_ascii(string(0..255) s) {
78e4182004-02-22Martin Nilsson  array v = array_sscanf(s, "%8b"*(sizeof(s)/8)+"%b"); v[-1] = v[-1]<<((-sizeof(s))%8);
d74f032013-12-08Henrik Grubbström (Grubba)  value = (string(0..255))v;
78e4182004-02-22Martin Nilsson  set_length(sizeof(s)); return this; }
f02e6f2014-04-05Martin Nilsson  //! Sets the length of the bit string to @[len] number of bits. Will //! only work correctly on strings longer than @[len] bits.
74b5f02014-04-05Martin Nilsson  this_program set_length(int len) {
3980c72003-01-26Martin Nilsson  if (len)
3e031f1998-06-13Niels Möller  {
3980c72003-01-26Martin Nilsson  value = value[..(len + 7)/8]; unused = (- len) % 8;
f02e6f2014-04-05Martin Nilsson  value[-1] &= 256-(1<<unused);
3980c72003-01-26Martin Nilsson  } else { unused = 0; value = "";
3e031f1998-06-13Niels Möller  }
74b5f02014-04-05Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents); if (!sizeof(contents)) return 0; unused = contents[0]; if (unused >= 8) return 0; value = contents[1..];
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
78e4182004-02-22Martin Nilsson  int size = sizeof(value)*8-unused;
86fa1b2014-05-20Martin Nilsson  if(t!='O') return UNDEFINED; if(!unused) return sprintf("%O(%d %O)", this_program, size, value); return sprintf("%O(%d %0"+size+"s)", this_program, size, ([object(Gmp.mpz)](Gmp.mpz(value, 256) >> unused)) ->digits(2));
3980c72003-01-26Martin Nilsson  } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
3980c72003-01-26Martin Nilsson  return sprintf("BIT STRING (%d) %s", sizeof(value) * 8 - unused,
009d772004-02-22Martin Nilsson  ([object(Gmp.mpz)](Gmp.mpz(value, 256) >> unused)) ->digits(2));
3980c72003-01-26Martin Nilsson  } #endif
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! Octet string object
3980c72003-01-26Martin Nilsson class OctetString
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 4;
3e031f1998-06-13Niels Möller  constant type_name = "OCTET STRING"; }
6e91d92002-12-05H. William Welliver III //! Null object
3980c72003-01-26Martin Nilsson class Null
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
39fddc2014-06-09Martin Nilsson  int tag = 5;
3e031f1998-06-13Niels Möller  constant type_name = "NULL";
17e7422003-01-26Martin Nilsson 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content() { return ""; }
3e031f1998-06-13Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents);
563bd72004-01-11Martin Nilsson  return !sizeof(contents) && this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() { return "NULL"; }
3980c72003-01-26Martin Nilsson #endif
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! Object identifier object
3980c72003-01-26Martin Nilsson class Identifier
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Object;
39fddc2014-06-09Martin Nilsson  int tag = 6;
3e031f1998-06-13Niels Möller  constant type_name = "OBJECT IDENTIFIER";
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  //! value of object
3e031f1998-06-13Niels Möller  array(int) id;
3980c72003-01-26Martin Nilsson  this_program init(int ... args) { if ( (sizeof(args) < 2) || (args[0] > 2) || (args[1] >= ( (args[0] < 2) ? 40 : 176) )) error( "Invalid object identifier.\n" ); id = args;
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
b1693a2000-04-07Fredrik Hübinette (Hubbe)  mixed _encode() { return id; }
3980c72003-01-26Martin Nilsson  void _decode(array(int) data) { id=data; }
b1693a2000-04-07Fredrik Hübinette (Hubbe) 
86e5af2004-02-22Martin Nilsson  //! Returns a new @[Identifier] object with @[args] appended to the //! ID path.
3980c72003-01-26Martin Nilsson  this_program append(int ... args) {
563bd72004-01-11Martin Nilsson  return this_program(@id, @args);
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  {
8856fc2014-02-21Henrik Grubbström (Grubba)  return [string(0..255)]sprintf("%s%@s", to_base_128(40 * id[0] + id[1]), map(id[2..], to_base_128));
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  record_der_contents(contents);
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson  if (contents[0] < 120) id = ({ contents[0] / 40, contents[0] % 40 }); else id = ({ 2, contents[0] - 80 }); int index = 1; while(index < sizeof(contents))
3e031f1998-06-13Niels Möller  {
3980c72003-01-26Martin Nilsson  int element = 0; do { element = element << 7 | (contents[index] & 0x7f); } while(contents[index++] & 0x80); id += ({ element });
3e031f1998-06-13Niels Möller  }
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
3980c72003-01-26Martin Nilsson  return t=='O' && sprintf("%O(%s)", this_program, (array(string))id*"."); } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
3980c72003-01-26Martin Nilsson  return "IDENTIFIER " + (array(string)) id * "."; } #endif
c0903c2014-04-25Martin Nilsson  protected int __hash()
0a38772004-01-26H. William Welliver III  { return hash(get_der()); }
c0903c2014-04-25Martin Nilsson  protected int(0..1) `==(mixed other) {
3980c72003-01-26Martin Nilsson  return (objectp(other) &&
563bd72004-01-11Martin Nilsson  (this_program == object_program(other)) &&
009d772004-02-22Martin Nilsson  equal(id, ([object(Identifier)]other)->id));
3980c72003-01-26Martin Nilsson  }
c0903c2014-04-25Martin Nilsson  protected int(0..1) `<(mixed other) { if( !objectp(other) || (this_program != object_program(other)) ) return 0; array oid = ([object(Identifier)]other)->id; for( int i; i<min(sizeof(id),sizeof(oid)); i++ ) { if( id[i] < oid[i] ) return 1; if( id[i] > oid[i] ) return 0; } return sizeof(id) < sizeof(oid); }
3e031f1998-06-13Niels Möller }
3980c72003-01-26Martin Nilsson //! Checks if a Pike string can be encoded with UTF8. That is //! always the case... int(1..1) asn1_utf8_valid (string s)
a6914b1999-06-07Martin Stjernholm {
d74f032013-12-08Henrik Grubbström (Grubba)  return 1;
a6914b1999-06-07Martin Stjernholm }
6e91d92002-12-05H. William Welliver III //! UTF8 string object //! //! Character set: ISO/IEC 10646-1 (compatible with Unicode). //! //! Variable width encoding, see rfc2279.
3980c72003-01-26Martin Nilsson class UTF8String
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 12;
a6914b1999-06-07Martin Stjernholm  constant type_name = "UTF8String";
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  {
8856fc2014-02-21Henrik Grubbström (Grubba)  return string_to_utf8(value);
3980c72003-01-26Martin Nilsson  }
a6914b1999-06-07Martin Stjernholm 
12e4902008-04-22Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents, function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
983ea12013-12-04Martin Nilsson  der = contents;
3980c72003-01-26Martin Nilsson  if (catch { value = utf8_to_string(contents); }) return 0;
17e7422003-01-26Martin Nilsson 
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  } }
a6914b1999-06-07Martin Stjernholm 
6e91d92002-12-05H. William Welliver III //! Sequence object
3980c72003-01-26Martin Nilsson class Sequence
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Compound;
39fddc2014-06-09Martin Nilsson  int tag = 16;
3e031f1998-06-13Niels Möller  constant type_name = "SEQUENCE";
17e7422003-01-26Martin Nilsson 
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  {
fa323d2004-02-29Martin Nilsson  WERROR("ASN1.Sequence: elements = '%O\n", elements);
3980c72003-01-26Martin Nilsson  array(string) a = elements->get_der();
fa323d2004-02-29Martin Nilsson  WERROR("ASN1.Sequence: der_encode(elements) = '%O\n", a);
8856fc2014-02-21Henrik Grubbström (Grubba)  return [string(0..255)]`+("", @ a);
3980c72003-01-26Martin Nilsson  }
12e4902008-04-22Henrik Grubbström (Grubba) 
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive(string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object) decoder, mapping(int:program(Object)) types) {
983ea12013-12-04Martin Nilsson  der = contents;
12e4902008-04-22Henrik Grubbström (Grubba)  elements = ({}); ADT.struct struct = ADT.struct(contents); while (!struct->is_empty()) { elements += ({ decoder(struct, types) }); } return this; }
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! Set object
3980c72003-01-26Martin Nilsson class Set
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit Compound;
39fddc2014-06-09Martin Nilsson  int tag = 17;
3e031f1998-06-13Niels Möller  constant type_name = "SET";
17e7422003-01-26Martin Nilsson 
ee60602014-02-20Henrik Grubbström (Grubba)  int(-1..1) compare_octet_strings(string r, string s) { if (r == s) return 0;
3980c72003-01-26Martin Nilsson  for(int i = 0;; i++) { if (i == sizeof(r))
ee60602014-02-20Henrik Grubbström (Grubba)  return (i = sizeof(s)) ? 0 : -1;
3980c72003-01-26Martin Nilsson  if (i == sizeof(s)) return 1;
ee60602014-02-20Henrik Grubbström (Grubba)  if (r[i] < s[i])
3980c72003-01-26Martin Nilsson  return -1;
ee60602014-02-20Henrik Grubbström (Grubba)  else if (r[i] > s[i]) return 1;
3e031f1998-06-13Niels Möller  }
3980c72003-01-26Martin Nilsson  }
3e031f1998-06-13Niels Möller 
8856fc2014-02-21Henrik Grubbström (Grubba)  string get_der_content() {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_set->der: elements = '%O\n", elements);
3980c72003-01-26Martin Nilsson  array(string) a = elements->get_der();
fa323d2004-02-29Martin Nilsson  WERROR("asn1_set->der: der_encode(elements) = '%O\n", a);
8856fc2014-02-21Henrik Grubbström (Grubba)  return [string(0..255)] `+("", @[array(string)] Array.sort_array(a, compare_octet_strings));
3980c72003-01-26Martin Nilsson  }
a6914b1999-06-07Martin Stjernholm }
3980c72003-01-26Martin Nilsson Regexp asn1_printable_invalid_chars = Regexp("([^-A-Za-z0-9 '()+,./:=?])");
a6914b1999-06-07Martin Stjernholm 
3980c72003-01-26Martin Nilsson //! Checks if a Pike string can be encoded as a @[PrintableString]. int(0..1) asn1_printable_valid (string s) { if (global.String.width(s)!=8) return 0; return !asn1_printable_invalid_chars->match(s);
a6914b1999-06-07Martin Stjernholm }
6e91d92002-12-05H. William Welliver III //! PrintableString object
3980c72003-01-26Martin Nilsson class PrintableString
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 19;
3e031f1998-06-13Niels Möller  constant type_name = "PrintableString"; }
3980c72003-01-26Martin Nilsson Regexp asn1_teletex_invalid_chars = Regexp ("([\\\\{}\240®©¬¦\255Ð])");
a6914b1999-06-07Martin Stjernholm 
3980c72003-01-26Martin Nilsson //! int(0..1) asn1_teletex_valid (string s)
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  if (global.String.width(s)!=8)
a6914b1999-06-07Martin Stjernholm  // T.61 encoding of wide strings not implemented. return 0; return !asn1_teletex_invalid_chars->match (s); }
6e91d92002-12-05H. William Welliver III //! TeletexString object //! //! Avoid this one; it seems to be common that this type is used to //! label strings encoded with the ISO 8859-1 character set (use //! asn1_broken_teletex_string for that). From //! http://www.mindspring.com/~asn1/nlsasn.htm: //! //! /.../ Types GeneralString, VideotexString, TeletexString //! (T61String), and GraphicString exist in earlier versions //! [pre-1994] of ASN.1. They are considered difficult to use //! correctly by applications providing national language support. //! Varying degrees of application support for T61String values seems //! to be most common in older applications. Correct support is made //! more difficult, as character values available in type T61String //! have changed with the addition of new register entries from the //! 1984 through 1997 versions. //! //! This implementation is based on the description of T.61 and T.51 //! in "Some functions for representing T.61 characters from the //! X.500 Directory Service in ISO 8859 terminals (Version 0.2. July //! 1994.)" by Enrique Silvestre Mora (mora@@si.uji.es), Universitat //! Jaume I, Spain, found in the package //! ftp://pereiii.uji.es/pub/uji-ftp/unix/ldap/iso-t61.translation.tar.Z //! //! The translation is only complete for 8-bit latin 1 strings. It //! encodes strictly to T.61, but decodes from the superset T.51.
12e4902008-04-22Henrik Grubbström (Grubba) //! //! @note
3f5bd42008-04-22Henrik Grubbström (Grubba) //! CCITT Recommendation T.61 is also known as ISO-IR 103:1985 //! (graphic characters) and ISO-IR 106:1985 and ISO-IR 107:1985 //! (control characters).
12e4902008-04-22Henrik Grubbström (Grubba) //! //! @seealso
0b8d2f2013-06-17Martin Nilsson //! @[Charset]
3980c72003-01-26Martin Nilsson class TeletexString
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 20;
a6914b1999-06-07Martin Stjernholm  constant type_name = "TeletexString"; // Alias: T61String #define ENC_ERR(char) char #define DEC_ERR(str) str #define DEC_COMB_MARK "\300" #define GR(char) "\301" char /* Combining grave accent */ #define AC(char) "\302" char /* Combining acute accent */ #define CI(char) "\303" char /* Combining circumflex accent */ #define TI(char) "\304" char /* Combining tilde */ #define MA(char) "\305" char /* Combining macron */ #define BR(char) "\306" char /* Combining breve */ #define DA(char) "\307" char /* Combining dot above */ #define DI(char) "\310" char /* Combining diaeresis */ #define RA(char) "\312" char /* Combining ring above */ #define CE(char) "\313" char /* Combining cedilla */ #define UN(char) "\314" char /* Combining underscore (note 6) */ #define DO(char) "\315" char /* Combining double acute accent */ #define OG(char) "\316" char /* Combining ogonek */ #define CA(char) "\317" char /* Combining caron */ constant encode_from = ({ /*"#", "$",*/ "¤", // Note 3 "\\", "{", "}", // Note 7 "\240", // No-break space (note 7) "×", // Multiplication sign "÷", // Division sign "¹", // Superscript one "®", // Registered sign (note 7) "©", // Copyright sign (note 7) "¬", // Not sign (note 7) "¦", // Broken bar (note 7) "Æ", // Latin capital ligature ae "ª", // Feminine ordinal indicator "Ø", // Latin capital letter o with stroke "º", // Masculine ordinal indicator "Þ", // Latin capital letter thorn "æ", // Latin small ligature ae "ð", // Latin small letter eth "ø", // Latin small letter o with stroke "ß", // Latin small letter sharp s "þ", // Latin small letter thorn "\255", // Soft hyphen (note 7) "Ð", // Latin capital letter eth (no equivalent) // Combinations "^", "`", "~", // Note 4 "´", "¨", "¯", "¸", "À", "Á", "Â", "Ã", "Ä", "Å", "à", "á", "â", "ã", "ä", "å", "Ç", "ç", "È", "É", "Ê", "Ë", "è", "é", "ê", "ë", "Ì", "Í", "Î", "Ï", "ì", "í", "î", "ï", "Ñ", "ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "ò", "ó", "ô", "õ", "ö", "Ù", "Ú", "Û", "Ü", "ù", "ú", "û", "ü", "Ý", "ý", }); constant encode_to = ({ /*"#", "$",*/ "\250", // Note 3 ENC_ERR("\\"), ENC_ERR("{"), ENC_ERR("}"), // Note 7 ENC_ERR("\240"), // No-break space (note 7) "\264", // Multiplication sign "\270", // Division sign "\321", // Superscript one ENC_ERR("®"), // Registered sign (note 7) ENC_ERR("©"), // Copyright sign (note 7) ENC_ERR("¬"), // Not sign (note 7) ENC_ERR("¦"), // Broken bar (note 7) "\341", // Latin capital ligature ae "\343", // Feminine ordinal indicator "\351", // Latin capital letter o with stroke "\353", // Masculine ordinal indicator "\354", // Latin capital letter thorn "\361", // Latin small ligature ae "\363", // Latin small letter eth "\371", // Latin small letter o with stroke "\373", // Latin small letter sharp s "\374", // Latin small letter thorn ENC_ERR("\255"), // Soft hyphen (note 7) ENC_ERR("Ð"), // Latin capital letter eth (no equivalent) // Combinations CI(" "), GR(" "), TI(" "), // Note 4 AC(" "), DI(" "), MA(" "), CE(" "), GR("A"), AC("A"), CI("A"), TI("A"), DI("A"), RA("A"), GR("a"), AC("a"), CI("a"), TI("a"), DI("a"), RA("a"), CE("C"), CE("c"), GR("E"), AC("E"), CI("E"), DI("E"), GR("e"), AC("e"), CI("e"), DI("e"), GR("I"), AC("I"), CI("I"), DI("I"), GR("i"), AC("i"), CI("i"), DI("i"), TI("N"), TI("n"), GR("O"), AC("O"), CI("O"), TI("O"), DI("O"), GR("o"), AC("o"), CI("o"), TI("o"), DI("o"), GR("U"), AC("U"), CI("U"), DI("U"), GR("u"), AC("u"), CI("u"), DI("u"), GR("Y"), GR("y"), }); constant decode_from = ({ /*"#", "$",*/ "\244", "\246", "\250", // Note 3 /*"^", "`", "~",*/ // Note 4 "\251", // Left single quotation mark (note 7) "\252", // Left double quotation mark (note 7) "\254", // Leftwards arrow (note 7) "\255", // Upwards arrow (note 7) "\256", // Rightwards arrow (note 7) "\257", // Downwards arrow (note 7) "\264", // Multiplication sign "\270", // Division sign "\271", // Right single quotation mark (note 7) "\272", // Right double quotation mark (note 7) "\300", // Note 5 GR(""), // Combining grave accent AC(""), // Combining acute accent CI(""), // Combining circumflex accent TI(""), // Combining tilde MA(""), // Combining macron BR(""), // Combining breve DA(""), // Combining dot above DI(""), // Combining diaeresis "\311", // Note 5 RA(""), // Combining ring above CE(""), // Combining cedilla UN(""), // Combining underscore (note 6) DO(""), // Combining double acute accent OG(""), // Combining ogonek CA(""), // Combining caron "\320", // Em dash (note 7) "\321", // Superscript one "\322", // Registered sign (note 7) "\323", // Copyright sign (note 7) "\324", // Trade mark sign (note 7) "\325", // Eighth note (note 7) "\326", // Not sign (note 7) "\327", // Broken bar (note 7) "\330", "\331", "\332", "\333", // Note 2 "\334", // Vulgar fraction one eighth (note 7) "\335", // Vulgar fraction three eighths (note 7) "\336", // Vulgar fraction five eighths (note 7) "\337", // Vulgar fraction seven eighths (note 7) "\340", // Ohm sign "\341", // Latin capital ligature ae "\342", // Latin capital letter d with stroke "\343", // Feminine ordinal indicator "\344", // Latin capital letter h with stroke "\345", // Note 2 "\346", // Latin capital ligature ij "\347", // Latin capital letter l with middle dot "\350", // Latin capital letter l with stroke "\351", // Latin capital letter o with stroke "\352", // Latin capital ligature oe "\353", // Masculine ordinal indicator "\354", // Latin capital letter thorn "\355", // Latin capital letter t with stroke "\356", // Latin capital letter eng "\357", // Latin small letter n preceded by apostrophe "\360", // Latin small letter kra "\361", // Latin small ligature ae "\362", // Latin small letter d with stroke "\363", // Latin small letter eth "\364", // Latin small letter h with stroke "\365", // Latin small letter dotless i "\366", // Latin small ligature ij "\367", // Latin small letter l with middle dot "\370", // Latin small letter l with stroke "\371", // Latin small letter o with stroke "\372", // Latin small ligature oe "\373", // Latin small letter sharp s "\374", // Latin small letter thorn "\375", // Latin small letter t with stroke "\376", // Latin small letter eng "\377", // Soft hyphen (note 7) }); constant decode_to = ({ /*"#", "$",*/ "$", "#", "\244", // Note 3 /*"^", "`", "~",*/ // Note 4 DEC_ERR("\251"), // Left single quotation mark (note 7) DEC_ERR("\252"), // Left double quotation mark (note 7) DEC_ERR("\254"), // Leftwards arrow (note 7) DEC_ERR("\255"), // Upwards arrow (note 7) DEC_ERR("\256"), // Rightwards arrow (note 7) DEC_ERR("\257"), // Downwards arrow (note 7) "×", // Multiplication sign "÷", // Division sign DEC_ERR("\271"), // Right single quotation mark (note 7) DEC_ERR("\272"), // Right double quotation mark (note 7) DEC_ERR("\300"), // Note 5 DEC_COMB_MARK GR(""), // Combining grave accent DEC_COMB_MARK AC(""), // Combining acute accent DEC_COMB_MARK CI(""), // Combining circumflex accent DEC_COMB_MARK TI(""), // Combining tilde DEC_COMB_MARK MA(""), // Combining macron DEC_COMB_MARK BR(""), // Combining breve DEC_COMB_MARK DA(""), // Combining dot above DEC_COMB_MARK DI(""), // Combining diaeresis DEC_ERR("\311"), // Note 5 DEC_COMB_MARK RA(""), // Combining ring above DEC_COMB_MARK CE(""), // Combining cedilla DEC_COMB_MARK UN(""), // Combining underscore (note 6) DEC_COMB_MARK DO(""), // Combining double acute accent DEC_COMB_MARK OG(""), // Combining ogonek DEC_COMB_MARK CA(""), // Combining caron DEC_ERR("\320"), // Em dash (note 7) "¹", // Superscript one "®", // Registered sign (note 7) "©", // Copyright sign (note 7) DEC_ERR("\324"), // Trade mark sign (note 7) DEC_ERR("\325"), // Eighth note (note 7) "¬", // Not sign (note 7) "¦", // Broken bar (note 7) DEC_ERR("\330"), DEC_ERR("\331"), DEC_ERR("\332"), DEC_ERR("\333"), // Note 2 DEC_ERR("\334"), // Vulgar fraction one eighth (note 7) DEC_ERR("\335"), // Vulgar fraction three eighths (note 7) DEC_ERR("\336"), // Vulgar fraction five eighths (note 7) DEC_ERR("\337"), // Vulgar fraction seven eighths (note 7) DEC_ERR("\340"), // Ohm sign "Æ", // Latin capital ligature ae DEC_ERR("\342"), // Latin capital letter d with stroke "ª", // Feminine ordinal indicator DEC_ERR("\344"), // Latin capital letter h with stroke DEC_ERR("\345"), // Note 2 DEC_ERR("\346"), // Latin capital ligature ij DEC_ERR("\347"), // Latin capital letter l with middle dot DEC_ERR("\350"), // Latin capital letter l with stroke "Ø", // Latin capital letter o with stroke DEC_ERR("\352"), // Latin capital ligature oe "º", // Masculine ordinal indicator "Þ", // Latin capital letter thorn DEC_ERR("\355"), // Latin capital letter t with stroke DEC_ERR("\356"), // Latin capital letter eng DEC_ERR("\357"), // Latin small letter n preceded by apostrophe DEC_ERR("\360"), // Latin small letter kra "æ", // Latin small ligature ae DEC_ERR("\362"), // Latin small letter d with stroke "ð", // Latin small letter eth DEC_ERR("\364"), // Latin small letter h with stroke DEC_ERR("\365"), // Latin small letter dotless i DEC_ERR("\366"), // Latin small ligature ij DEC_ERR("\367"), // Latin small letter l with middle dot DEC_ERR("\370"), // Latin small letter l with stroke "ø", // Latin small letter o with stroke DEC_ERR("\372"), // Latin small ligature oe "ß", // Latin small letter sharp s "þ", // Latin small letter thorn DEC_ERR("\375"), // Latin small letter t with stroke DEC_ERR("\376"), // Latin small letter eng "\255", // Soft hyphen (note 7) }); constant decode_comb = ([ GR(" "): "`", AC(" "): "´", CI(" "): "^", TI(" "): "~", DI(" "): "¨", // RA(" "): DEC_ERR(RA(" ")), MA(" "): "¯", // BR(" "): DEC_ERR(BR(" ")), // DA(" "): DEC_ERR(DA(" ")), CE(" "): "¸", // DO(" "): DEC_ERR(DO(" ")), // OG(" "): DEC_ERR(OG(" ")), // CA(" "): DEC_ERR(CA(" ")), GR("A"): "À", AC("A"): "Á", CI("A"): "Â", TI("A"): "Ã", DI("A"): "Ä", RA("A"): "Å", GR("a"): "à", AC("a"): "á", CI("a"): "â", TI("a"): "ã", DI("a"): "ä", RA("a"): "å", CE("C"): "Ç", CE("c"): "ç", GR("E"): "È", AC("E"): "É", CI("E"): "Ê", DI("E"): "Ë", GR("e"): "è", AC("e"): "é", CI("e"): "ê", DI("e"): "ë", GR("I"): "Ì", AC("I"): "Í", CI("I"): "Î", DI("I"): "Ï", GR("i"): "ì", AC("i"): "í", CI("i"): "î", DI("i"): "ï", TI("N"): "Ñ", TI("n"): "ñ", GR("O"): "Ò", AC("O"): "Ó", CI("O"): "Ô", TI("O"): "Õ", DI("O"): "Ö", GR("o"): "ò", AC("o"): "ó", CI("o"): "ô", TI("o"): "õ", DI("o"): "ö", GR("U"): "Ù", AC("U"): "Ú", CI("U"): "Û", DI("U"): "Ü", GR("u"): "ù", AC("u"): "ú", CI("u"): "û", DI("u"): "ü", GR("Y"): "Ý", GR("y"): "ý", ]); /* Notes from Moras paper: (1) All characters in 0xC0-0xCF are non-spacing characters. They are all diacritical marks. To be represented stand-alone, they need to be followed by a SPACE (0x20). They can appear, also, before letters if the couple is one of the defined combinations. (2) Reserved for future standardization. (3) Current terminals may send and receive 0xA6 and 0xA4 for the NUMBER SIGN and DOLLAR SIGN, respectively. When receiving codes 0x23 and 0x24, they may interpret them as NUMBER SIGN and CURRENCY SIGN, respectively. Future applications should code the NUMBER SIGN, DOLLAR SIGN and CURRENCY SIGN as 0x23, 0x24 and 0xA8, respectively. (4) Terminals should send only the codes 0xC1, 0xC3 and 0xC4, followed by SPACE (0x20) for stand-alone GRAVE ACCENT, CIRCUMFLEX ACCENT and TILDE, respectively. Nevertheless the terminal shall interpret the codes 0x60, 0x5E and 0x7E as GRAVE, CIRCUMFLEX and TILDE, respectively. (5) This code position is reserved and shall not be used. (6) It is recommended to implement the "underline" function by means of the control function SGR(4) instead of the "non-spacing underline" graphic character. (7) Not used in current teletex service (Recommendation T.61). */ #undef GR #undef AC #undef CI #undef TI #undef MA #undef BR #undef DA #undef DI #undef RA #undef CE #undef UN #undef DO #undef OG #undef CA
8856fc2014-02-21Henrik Grubbström (Grubba)  string(0..255) get_der_content()
d74f032013-12-08Henrik Grubbström (Grubba)  {
8856fc2014-02-21Henrik Grubbström (Grubba)  return [string(0..255)]replace(value, [array(string)]encode_from, [array(string(0..255))]encode_to);
a6914b1999-06-07Martin Stjernholm  }
d74f032013-12-08Henrik Grubbström (Grubba)  this_program decode_primitive (string(0..255) contents,
12e4902008-04-22Henrik Grubbström (Grubba)  function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
983ea12013-12-04Martin Nilsson  der = contents;
a6914b1999-06-07Martin Stjernholm  array(string) parts =
28c6d52004-02-23Martin Nilsson  replace (contents, [array(string)]decode_from, [array(string)]decode_to) / DEC_COMB_MARK;
a6914b1999-06-07Martin Stjernholm  value = parts[0]; foreach (parts[1..], string part) value += (decode_comb[part[..1]] || DEC_ERR(part[..1])) + part[2..];
563bd72004-01-11Martin Nilsson  return this;
a6914b1999-06-07Martin Stjernholm  } #undef ENC_ERR #undef DEC_ERR #undef DEC_COMB_MARK }
3980c72003-01-26Martin Nilsson //! int(0..1) asn1_broken_teletex_valid (string s)
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  return global.String.width(s)==8;
a6914b1999-06-07Martin Stjernholm }
6e91d92002-12-05H. William Welliver III //! (broken) TeletexString object //! //! Encodes and decodes latin1, but labels it TeletexString, as is //! common in many broken programs (e.g. Netscape 4.0X).
3980c72003-01-26Martin Nilsson class BrokenTeletexString
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 20;
a6914b1999-06-07Martin Stjernholm  constant type_name = "TeletexString"; // Alias: T61String }
8b72ec2005-01-21Martin Stjernholm Regexp asn1_IA5_invalid_chars = Regexp ("([\200-\377])");
a6914b1999-06-07Martin Stjernholm 
3980c72003-01-26Martin Nilsson //! int(0..1) asn1_IA5_valid (string s)
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  if (global.String.width(s)!=8) return 0;
a6914b1999-06-07Martin Stjernholm  return !asn1_printable_invalid_chars->match (s);
3e031f1998-06-13Niels Möller }
6e91d92002-12-05H. William Welliver III //! IA5 String object //! //! Character set: ASCII. Fixed width encoding with 1 octet per //! character.
3980c72003-01-26Martin Nilsson class IA5String
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 22;
3e031f1998-06-13Niels Möller  constant type_name = "IA5STRING"; }
53df712003-01-26Martin Nilsson 
ffbc622003-01-28Martin Nilsson //! class VisibleString { inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 26;
ffbc622003-01-28Martin Nilsson  constant type_name = "VisibleString"; }
eb16ad2014-05-14Henrik Grubbström (Grubba) //! UTCTime
53df712003-01-26Martin Nilsson //!
eb16ad2014-05-14Henrik Grubbström (Grubba) //! RFC 2459 4.1.2.5.1
3980c72003-01-26Martin Nilsson class UTC
3e031f1998-06-13Niels Möller {
3980c72003-01-26Martin Nilsson  inherit String;
39fddc2014-06-09Martin Nilsson  int tag = 23;
3e031f1998-06-13Niels Möller  constant type_name = "UTCTime";
6725f52013-11-22Martin Nilsson 
eb16ad2014-05-14Henrik Grubbström (Grubba)  //!
6725f52013-11-22Martin Nilsson  this_program set_posix(int t) {
e2f0772014-03-02Marcus Comstedt  object second = Calendar.ISO_UTC.Second(t);
6725f52013-11-22Martin Nilsson 
eb16ad2014-05-14Henrik Grubbström (Grubba)  // RFC 2459 4.1.2.5.1: // // Where YY is greater than or equal to 50, the year shall be // interpreted as 19YY; and // // Where YY is less than 50, the year shall be interpreted as 20YY.
6725f52013-11-22Martin Nilsson  if (second->year_no() >= 2050) error( "Times later than 2049 not supported.\n" );
eb16ad2014-05-14Henrik Grubbström (Grubba)  if (second->year_no() < 1950) error( "Times earlier than 1950 not supported.\n" );
6725f52013-11-22Martin Nilsson  value = sprintf("%02d%02d%02d%02d%02d%02dZ", [int]second->year_no() % 100, [int]second->month_no(), [int]second->month_day(), [int]second->hour_no(), [int]second->minute_no(), [int]second->second_no()); return this; }
eb16ad2014-05-14Henrik Grubbström (Grubba)  //!
6725f52013-11-22Martin Nilsson  int get_posix() { if( !value || sizeof(value)!=13 ) error("Data not UTC date string.\n"); array t = (array(int))(value[..<1]/2); if(t[0]>49) t[0]+=1900; else t[0]+=2000;
e2f0772014-03-02Marcus Comstedt  return [int]Calendar.ISO_UTC.Second(@t)->unix_time();
6725f52013-11-22Martin Nilsson  }
3e031f1998-06-13Niels Möller }
3980c72003-01-26Martin Nilsson //! int(0..0) asn1_universal_valid (string s)
a6914b1999-06-07Martin Stjernholm {
7991f12008-01-05Henrik Grubbström (Grubba)  return 0; s; // Return 0 since the UniversalString isn't implemented.
a6914b1999-06-07Martin Stjernholm }
6e91d92002-12-05H. William Welliver III //! Universal String object //! //! Character set: ISO/IEC 10646-1 (compatible with Unicode). //! Fixed width encoding with 4 octets per character. //! //! @fixme //! The encoding is very likely UCS-4, but that's not yet verified.
3980c72003-01-26Martin Nilsson class UniversalString
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  inherit OctetString;
39fddc2014-06-09Martin Nilsson  int tag = 28;
a6914b1999-06-07Martin Stjernholm  constant type_name = "UniversalString";
8856fc2014-02-21Henrik Grubbström (Grubba)  string get_der_content() {
3980c72003-01-26Martin Nilsson  error( "Encoding not implemented\n" );
a6914b1999-06-07Martin Stjernholm  }
12e4902008-04-22Henrik Grubbström (Grubba)  this_program decode_primitive (string contents, function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
7991f12008-01-05Henrik Grubbström (Grubba)  error( "Decoding not implemented\n" ); contents;
a6914b1999-06-07Martin Stjernholm  } }
3980c72003-01-26Martin Nilsson //! int(0..1) asn1_bmp_valid (string s)
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  return global.String.width(s)<32;
a6914b1999-06-07Martin Stjernholm }
6e91d92002-12-05H. William Welliver III //! BMP String object //! //! Character set: ISO/IEC 10646-1 (compatible with Unicode). //! Fixed width encoding with 2 octets per character. //! //! FIXME: The encoding is very likely UCS-2, but that's not yet verified.
3980c72003-01-26Martin Nilsson class BMPString
a6914b1999-06-07Martin Stjernholm {
3980c72003-01-26Martin Nilsson  inherit OctetString;
39fddc2014-06-09Martin Nilsson  int tag = 30;
a6914b1999-06-07Martin Stjernholm  constant type_name = "BMPString";
8856fc2014-02-21Henrik Grubbström (Grubba)  string get_der_content() { return string_to_unicode (value);
a6914b1999-06-07Martin Stjernholm  }
12e4902008-04-22Henrik Grubbström (Grubba)  this_program decode_primitive (string(0..255) contents, function(ADT.struct, mapping(int:program(Object)): Object)|void decoder, mapping(int:program(Object))|void types) {
983ea12013-12-04Martin Nilsson  der = contents;
a6914b1999-06-07Martin Stjernholm  value = unicode_to_string (contents);
563bd72004-01-11Martin Nilsson  return this;
a6914b1999-06-07Martin Stjernholm  } }
3980c72003-01-26Martin Nilsson //! Meta-instances handle a particular explicit tag and set of types.
dd85c02013-08-16Martin Nilsson //! Once cloned this object works as a factory for Compound objects //! with the cls and tag that the meta object was initialized with.
6e91d92002-12-05H. William Welliver III //!
dd85c02013-08-16Martin Nilsson //! @example //! MetaExplicit m = MetaExplicit(1,2); //! Compound c = m(Integer(3));
3980c72003-01-26Martin Nilsson class MetaExplicit
3e031f1998-06-13Niels Möller { int real_tag;
1ec5d61999-03-22Niels Möller  int real_cls;
17e7422003-01-26Martin Nilsson 
c485aa2003-01-27Martin Nilsson  mapping(int:program(Object)) valid_types;
3e031f1998-06-13Niels Möller 
3980c72003-01-26Martin Nilsson  class `() { inherit Compound; constant type_name = "EXPLICIT"; constant constructed = 1;
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  int get_tag() { return real_tag; } int get_cls() { return real_cls; }
17e7422003-01-26Martin Nilsson 
3980c72003-01-26Martin Nilsson  Object contents;
3e031f1998-06-13Niels Möller 
8c92912014-01-19Henrik Grubbström (Grubba)  array(Object) `elements() { return contents ? ({ contents }) : ({}); } void `elements=(array(Object) args) { if (sizeof(args) > 1) error("Invalid number of elements.\n"); contents = sizeof(args) && args[0]; } int `combined_tag() { return get_combined_tag(); }
3980c72003-01-26Martin Nilsson  this_program init(Object o) { contents = o;
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  }
17e7422003-01-26Martin Nilsson 
8856fc2014-02-21Henrik Grubbström (Grubba)  string get_der_content() {
fa323d2004-02-29Martin Nilsson  WERROR("asn1_explicit->der: contents = '%O\n", contents);
8856fc2014-02-21Henrik Grubbström (Grubba)  return contents->get_der();
3e031f1998-06-13Niels Möller  }
3980c72003-01-26Martin Nilsson  this_program decode_constructed_element(int i, Object e) { if (i) error("Unexpected index!\n"); contents = e;
563bd72004-01-11Martin Nilsson  return this;
3980c72003-01-26Martin Nilsson  } this_program end_decode_constructed(int length) { if (length != 1) error("length != 1!\n");
563bd72004-01-11Martin Nilsson  return this;
3e031f1998-06-13Niels Möller  }
3980c72003-01-26Martin Nilsson 
c485aa2003-01-27Martin Nilsson  mapping(int:program(Object)) element_types(int i, mapping(int:program(Object)) types) {
3980c72003-01-26Martin Nilsson  if (i) error("Unexpected index!\n"); return valid_types || types; }
9eaf1d2008-06-28Martin Nilsson  protected string _sprintf(int t) {
bc5ae92014-01-18Henrik Grubbström (Grubba)  if (t != 'O') return UNDEFINED; if ((real_cls == 2) && (real_tag <= 3)) { // Special case for the convenience variants further below. return sprintf("%O.TaggedType%d(%O)", global::this, real_tag, contents); } return sprintf("%O(%s %d %O)", this_program, type_name, real_tag, contents);
3980c72003-01-26Martin Nilsson  } #ifdef COMPATIBILITY
3e88822013-08-30Martin Nilsson  __deprecated__ string debug_string() {
009d772004-02-22Martin Nilsson  return type_name + "[" + (int) real_tag + "]";
3980c72003-01-26Martin Nilsson  } #endif }
17e7422003-01-26Martin Nilsson 
dd85c02013-08-16Martin Nilsson  //!
33dd5f2014-02-11Henrik Grubbström (Grubba)  protected void create(int cls, int tag, mapping(int:program(Object))|void types) {
3980c72003-01-26Martin Nilsson  real_cls = cls; real_tag = tag; valid_types = types; }
3e031f1998-06-13Niels Möller }
d9b4021999-08-06Fredrik Hübinette (Hubbe) 
bc5ae92014-01-18Henrik Grubbström (Grubba) //! Some common explicit tags for convenience. //! //! These are typically used to indicate which //! of several optional fields are present. //! //! @example //! Eg RFC 5915 section 3: //! @code //! ECPrivateKey ::= SEQUENCE { //! version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), //! privateKey OCTET STRING, //! parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, //! publicKey [1] BIT STRING OPTIONAL //! } //! @endcode //! The presence of the fields @tt{parameters@} and @tt{publicKey@} above //! are indicated with @[TaggedType0] and @[TaggedType1] respectively. MetaExplicit TaggedType0 = MetaExplicit(2, 0); MetaExplicit TaggedType1 = MetaExplicit(2, 1); MetaExplicit TaggedType2 = MetaExplicit(2, 2); MetaExplicit TaggedType3 = MetaExplicit(2, 3);
3980c72003-01-26Martin Nilsson  #ifdef COMPATIBILITY constant meta_explicit = MetaExplicit; constant asn1_object = Object; constant asn1_compound = Compound; constant asn1_string = String; constant asn1_boolean = Boolean; constant asn1_integer = Integer; constant asn1_enumerated = Enumerated; constant asn1_bit_string = BitString; constant asn1_octet_string = OctetString; constant asn1_null = Null; constant asn1_identifier = Identifier; constant asn1_utf8_string = UTF8String; constant asn1_sequence = Sequence; constant asn1_set = Set; constant asn1_printable_string = PrintableString; constant asn1_teletex_string = TeletexString; constant asn1_broken_teletex_string = BrokenTeletexString; constant asn1_IA5_string = IA5String;
53df712003-01-26Martin Nilsson constant asn1_utc = UTC;
3980c72003-01-26Martin Nilsson constant asn1_universal_string = UniversalString; constant asn1_bmp_string = BMPString; #endif