diff --git a/scapy/asn1/asn1.py b/scapy/asn1/asn1.py
index 514404eb7da583ef5fd9c76b8bf4fb8bb06c4f7c..973b24337cf7d5799b964acdf7f3dd6808ed1c21 100644
--- a/scapy/asn1/asn1.py
+++ b/scapy/asn1/asn1.py
@@ -263,19 +263,42 @@ class ASN1_BIT_STRING(ASN1_Object):
     """
     tag = ASN1_Class_UNIVERSAL.BIT_STRING
     def __init__(self, val, readable=False):
-        if readable:
-            self.val_readable = val
-            val = "".join(binrepr(ord(x)).zfill(8) for x in val)
-            self.unused_bits = 0
+        if not readable:
+            self.val = val
         else:
-            if len(val) % 8 == 0:
-                self.unused_bits = 0
+            self.val_readable = val
+    def __setattr__(self, name, value):
+        if name == "val_readable":
+            if isinstance(value, str):
+                val = "".join(binrepr(ord(x)).zfill(8) for x in value)
             else:
-                self.unused_bits = 8 - len(val)%8
-            padded_val = val + "0"*self.unused_bits
-            bytes_arr = zip(*[iter(padded_val)]*8)
-            self.val_readable = "".join(chr(int("".join(x),2)) for x in bytes_arr)
-        ASN1_Object.__init__(self, val)
+                val = "<invalid val_readable>"
+            super(ASN1_Object, self).__setattr__("val", val)
+            super(ASN1_Object, self).__setattr__(name, value)
+            super(ASN1_Object, self).__setattr__("unused_bits", 0)
+        elif name == "val":
+            if isinstance(value, str):
+                if len([c for c in value if c not in ["0", "1"]]) > 0:
+                    print "Invalid operation: 'val' is not a valid bit string."
+                    return
+                else:
+                    if len(value) % 8 == 0:
+                        unused_bits = 0
+                    else:
+                        unused_bits = 8 - (len(value) % 8)
+                    padded_value = value + ("0" * unused_bits)
+                    bytes_arr = zip(*[iter(padded_value)]*8)
+                    val_readable = "".join(chr(int("".join(x),2)) for x in bytes_arr)
+            else:
+                val_readable = "<invalid val>"
+                unused_bits = 0
+            super(ASN1_Object, self).__setattr__("val_readable", val_readable)
+            super(ASN1_Object, self).__setattr__(name, value)
+            super(ASN1_Object, self).__setattr__("unused_bits", unused_bits)
+        elif name == "unused_bits":
+            print "Invalid operation: unused_bits rewriting is not supported."
+        else:
+            super(ASN1_Object, self).__setattr__(name, value)
     def __repr__(self):
         if len(self.val) <= 16:
             return "<%s[%r] (%d unused bit%s)>" % (self.__dict__.get("name", self.__class__.__name__), self.val, self.unused_bits, "s" if self.unused_bits>1 else "")
@@ -328,26 +351,46 @@ class ASN1_IA5_STRING(ASN1_STRING):
 class ASN1_UTC_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
     def __init__(self, val):
-        pretty_time = ""
-        if len(val) == 13 and val[-1] == "Z":
-            dt = datetime.strptime(val[:-1], "%y%m%d%H%M%S")
-            pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
-        self.pretty_time = pretty_time
-        ASN1_STRING.__init__(self, val)
+        super(ASN1_UTC_TIME, self).__init__(val)
+    def __setattr__(self, name, value):
+        if name == "val":
+            pretty_time = None
+            if (isinstance(value, str) and
+                len(value) == 13 and value[-1] == "Z"):
+                dt = datetime.strptime(value[:-1], "%y%m%d%H%M%S")
+                pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
+            else:
+                pretty_time = "%s [invalid utc_time]" % value
+            super(ASN1_UTC_TIME, self).__setattr__("pretty_time", pretty_time)
+            super(ASN1_UTC_TIME, self).__setattr__(name, value)
+        elif name == "pretty_time":
+            print "Invalid operation: pretty_time rewriting is not supported."
+        else:
+            super(ASN1_UTC_TIME, self).__setattr__(name, value)
     def __repr__(self):
-        return self.pretty_time + " " + ASN1_STRING.__repr__(self)
+        return "%s %s" % (self.pretty_time, ASN1_STRING.__repr__(self))
 
 class ASN1_GENERALIZED_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
     def __init__(self, val):
-        pretty_time = ""
-        if len(val) == 15 and val[-1] == "Z":
-            dt = datetime.strptime(val[:-1], "%Y%m%d%H%M%S")
-            pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
-        self.pretty_time = pretty_time
-        ASN1_STRING.__init__(self, val)
+        super(ASN1_GENERALIZED_TIME, self).__init__(val)
+    def __setattr__(self, name, value):
+        if name == "val":
+            pretty_time = None
+            if (isinstance(value, str) and
+                len(value) == 15 and value[-1] == "Z"):
+                dt = datetime.strptime(value[:-1], "%Y%m%d%H%M%S")
+                pretty_time = dt.strftime("%b %d %H:%M:%S %Y GMT")
+            else:
+                pretty_time = "%s [invalid generalized_time]" % value
+            super(ASN1_GENERALIZED_TIME, self).__setattr__("pretty_time", pretty_time)
+            super(ASN1_GENERALIZED_TIME, self).__setattr__(name, value)
+        elif name == "pretty_time":
+            print "Invalid operation: pretty_time rewriting is not supported."
+        else:
+            super(ASN1_GENERALIZED_TIME, self).__setattr__(name, value)
     def __repr__(self):
-        return self.pretty_time + " " + ASN1_STRING.__repr__(self)
+        return "%s %s" % (self.pretty_time, ASN1_STRING.__repr__(self))
 
 class ASN1_ISO646_STRING(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.ISO646_STRING
diff --git a/scapy/asn1/ber.py b/scapy/asn1/ber.py
index cb8447a19bfc3104f15656bcb689b91ac9645e06..b23184d6ce07c5554bf0420b0e5085f6df3993fe 100644
--- a/scapy/asn1/ber.py
+++ b/scapy/asn1/ber.py
@@ -105,13 +105,15 @@ def BER_id_dec(s):
     # This returns the tag ALONG WITH THE PADDED CLASS+CONSTRUCTIVE INFO.
     # Let's recall that bits 8-7 from the first byte of the tag encode
     # the class information, while bit 6 means primitive or constructive.
+    #
     # For instance, with low-tag-number '\x81', class would be 0b10
     # ('context-specific') and tag 0x01, but we return 0x81 as a whole.
-    # For '\xff\x02', class would be 0b11 ('private'), constructed, then
-    # padding, then tag 0x02, but we return (0xff>>5)*128^1 + 0x02*128^0.
+    # For '\xff\x22', class would be 0b11 ('private'), constructed, then
+    # padding, then tag 0x22, but we return (0xff>>5)*128^1 + 0x22*128^0.
     # Why the 5-bit-shifting? Because it provides an unequivocal encoding
     # on base 128 (note that 0xff would equal 1*128^1 + 127*128^0...),
     # as we know that bits 5 to 1 are fixed to 1 anyway.
+    #
     # As long as there is no class differentiation, we have to keep this info
     # encoded in scapy's tag in order to reuse it for packet building.
     # Note that tags thus may have to be hard-coded with their extended
@@ -394,7 +396,7 @@ class BERcodec_ISO646_STRING(BERcodec_STRING):
 class BERcodec_UNIVERSAL_STRING(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
 
-class BERcodec_BMP_STRING (BERcodec_STRING):
+class BERcodec_BMP_STRING(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.BMP_STRING
 
 class BERcodec_SEQUENCE(BERcodec_Object):
diff --git a/scapy/asn1fields.py b/scapy/asn1fields.py
index 7c37d14f92ffe8f6d2e4b16a54cc602109ae23fc..d368f4c0b149f55185975d56af800e56d8350c32 100644
--- a/scapy/asn1fields.py
+++ b/scapy/asn1fields.py
@@ -179,26 +179,16 @@ class ASN1F_enum_INTEGER(ASN1F_INTEGER):
         for k in keys:
             i2s[k] = enum[k]
             s2i[enum[k]] = k
-    def any2i_one(self, pkt, x):
-        if type(x) is str:
-            x = self.s2i[x]
-        return x
-    def any2i(self, pkt, x):
-        if type(x) is list:
-            return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
-        else:
-            return self.any2i_one(pkt, x)        
-    def i2repr_one(self, pkt, x):
-        if x is not None:
-            r = self.i2s.get(x)
+    def i2m(self, pkt, s):
+        if isinstance(s, str):
+            s = self.s2i.get(s)
+        return super(ASN1F_INTEGER, self).i2m(pkt, s)
+    def i2repr(self, pkt, x):
+        if x is not None and isinstance(x, ASN1_INTEGER):
+            r = self.i2s.get(x.val)
             if r:
-                return r + " " + repr(x)
+                return "'%s' %s" % (r, repr(x))
         return repr(x)
-    def i2repr(self, pkt, x):
-        if type(x) is list:
-            return map(lambda z,pkt=pkt:self.i2repr_one(pkt, z), x)
-        else:
-            return self.i2repr_one(pkt, x)
 
 class ASN1F_BIT_STRING(ASN1F_field):
     ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
@@ -479,22 +469,23 @@ class ASN1F_CHOICE(ASN1F_field):
         else:
             choice = self.choices[tag]
         if hasattr(choice, "ASN1_root"):
+            # we don't want to import ASN1_Packet in this module...
             return self.extract_packet(choice, s)
+        elif type(choice) is type:
+            #XXX find a way not to instantiate the ASN1F_field
+            return choice(self.name, "").m2i(pkt, s)
         else:
-            if type(choice) is type:
-                return choice(self.name, "").m2i(pkt, s)
-            else:
-                # choice must be an ASN1F_PACKET instance here
-                return choice.m2i(pkt, s)
+            #XXX check properly if this is an ASN1F_PACKET
+            return choice.m2i(pkt, s)
     def i2m(self, pkt, x):
         if x is None:
             s = ""
         else:
             s = str(x)
-        if hash(type(x)) in self.pktchoices:
-            imp, exp = self.pktchoices[hash(type(x))]
-            s = BER_tagging_enc(s, implicit_tag=imp,
-                                explicit_tag=exp)
+            if hash(type(x)) in self.pktchoices:
+                imp, exp = self.pktchoices[hash(type(x))]
+                s = BER_tagging_enc(s, implicit_tag=imp,
+                                    explicit_tag=exp)
         return BER_tagging_enc(s, explicit_tag=self.explicit_tag)
     def randval(self):
         return RandChoice(*(packet.fuzz(x()) for x in self.choices.itervalues()))