Pekka,
I'm confused by a couple of your statements.
The presence of the extention markers is included in the PER encoding (by a single bit at the beginning) but the addition of extentions at a later time should not change any of the encodings of the 'base' structure. Any extentions that are added, end up following the PER structure and are actually encoded as BER 'chunks' so that earlier revisions of the protocol may skip over the ones not understood.
I'm confused as to your example of encoding - decoding - re-encoding The ICV _will_ have to be recalculated. The ICV is calculated after the ASN.1 structure is fully encoded (but excluding the ICV field itself) and just before it is sent out 'on the wire'. The ICV value may in fact change value, and even position, but it should always be recognized by rev2 and newer implementations. Rev1 obviously will ignore it and not generate one to send out....
jimt.
11:12 AM 6/24/98 +0300, Pekka Pessi wrote:
Hello, While debugging our ASN.1/PER encoder, I noticed a problem with the way ICV is calculated in H.225.0. Briefly, the PER encodings change when a SEQUENCE type is further extended, even if the new extension additions are not included in the SEQUENCE value. The issue prevents interoperability between software using H.225.0 version 2 and software using any version, it should be solved before any version 2 devices are released. Pekka Pessi
h2250-integrityCheckValue-problem.txt Pekka Pessi
$Revision: 1.1 $ Nokia Research
Center
June
1998
Comments on H.225.0 (1998): Problems When Calculating integrityCheckValue
The current H.225.0 algorithm for calculating the ICV does not work well with the PER extension mechanism. In order to interwork, each H.323 device needs a separate PER encoding function for each version of H.225.0 ASN.1 definitions.
Algorithm for Calculating integityCheckValue
According to the H.225.0 v2, integrityCheckValue is defined and calculated as follows:
ICV ::= SEQUENCE { algorithmOID OBJECT IDENTIFIER, -- the algorithm used to compute the
signature
icv BIT STRING -- the computed cryptographic integrity
check
-- value or signature
}
integrityCheckValue - provides improved message integrity/message authentication of the RAS messages. The cryptographically based integrity check value is computed by the sender applying a negotiated integrity algorithm and the secret key upon the entire message. Prior to integrityCheckValue computation this field shall be ignored and shall be empty. After computation, the sender puts the computed integrity check value in the integrityCheckValue field and transmits the message.
The above algorithm (AFAIK I have understood it correctly) assumes that the sender and receiver can encode the PDU exactly in the same way. It is a reasonable assumption, as PER produces only one possible (canonical) encoding for given PDU. However, there is a serious problem: the canonical representation changes if the ASN.1 SEQUENCE type is extended later.
PER Encoding of an Extended ASN.1 SEQUENCE
In the PER encoding of extensions to SEQUENCE types, the encoder first encodes the number of extensions as a normally small non-negative integer, then a bit field with one bit for each extension followed by the extensions itself (bit is one if the extension is present, zero if not). The encoding of each extension is preceded by the length of their encoding in octets.
Now, if the sender A uses following ASN.1 definition for a SEQUENCE
Foo ::= SEQUENCE { bar INTEGER (0..127), ..., baz INTEGER (0..255) OPTIONAL, integrityCheckValue ICV OPTIONAL }
When encoding this, the length of extension bitfield is 2. However, recipient B is using extended version of Foo like this:
Foo ::= SEQUENCE { bar INTEGER (0..127), ..., baz INTEGER (0..255) OPTIONAL, integrityCheckValue ICV OPTIONAL, importantExtension SomeType OPTIONAL }
B decodes the Foo, removes ICV and encodes the packet again. In the resulting encoding, the length of extension bitfield is 3, and the ICV that B regenerates is different that A generated and sent to B. B is not able to interwork with systems using earlier version of the ASN.1 spec.
ASN.1 Compilers Don't Grok Unknown Extensions
There are also problems because the way some ASN.1 compilers behave. Using our previous example, when A receives Foo with the importantExtension field from B, A has somehow to include the value when it is re-encoding Foo in order to calculate the ICV. However, it may be very hard to present an value of an unknown extension to the ASN.1 encoding functions. As a possible solution the ICV calculation could be included in the ASN.1 decoding process.
Problems with Non-OPTIONAL Extensions
Another problem with some ASN.1 compilers is inclusion of non-OPTIONAL extensions. Let us assume that software C uses following ASN.1 definition for Foo:
Foo ::= SEQUENCE { bar INTEGER (0..127), ..., baz INTEGER (0..255) OPTIONAL, integrityCheckValue ICV OPTIONAL, importantExtension SomeType OPTIONAL, criticalExtension OtherType }
There are two kinds of problems with an extension like criticalExtension. First, the encoder may try to ensure that all encoded PDUs conform to the specification and signal an error when a PDU without criticalExtension is encoded. Another problem is that the intermediate representation produced by the ASN.1 compiler may not provide means for application to express that criticalExtension is not present. (In other words, the produced structure usually contains a flag telling whether an optional field is present or not. Such flags are not included when the field is not optional.)
The presense or absence of the OPTIONAL flag in an extension does not change the PER encoding of the SEQUENCE. In order to avoid previously mentioned problems, application may use a version of ASN.1 notation that has extra OPTIONAL keyword after each extension.
Solution 1: Clarification to the PER Encoding Process
The text in PER document (X.691, 1994) is somewhat ambiguous how many bits should be included in the extension present bitfield of SEQUENCE. To quote verbatim: "Let the number of extension additions in the type being encoded be "n", then a bit-field with "n" bits shall be produced for addition to the field-list." (Is the "type being encoded" the abstract syntax or an actual value like { bar 1, baz 2 }?) However, the 0 bits at the end of extension present bitfield can be left out without changing the resulting semantics: the corresponding extensions are not present. As a result, the PER encoding does not change after a new extension is added to the ASN.1 specification.
This solution, while leaving H.225.0 v2 protocol as it is, requires however changes to some existing ASN.1 compilers, and in a pessimal case, to the X.691 standard text, too.
Solution 2: Hack
The receiving application does not decode and the re-encode the PDU, but rather removes the ICV from the encoded PDU. In practice, this requires
that
application can identify PER-encoded fields within the PDU and it can regenerate them, i.e. it has effectively the same functionality as a PER encoder/decoder.
Solution 3: Calculating ICV Differently
The following algorithm for generating and checking the ICV makes it possible to avoid all the previously mentioned problems. The problems are avoided by breaking the protocol layering, the application changes
directly
the PER-encoded PDU:
integrityCheckValue - provides improved message integrity/message authentication of the RAS messages. The cryptographically based integrity check value is computed by the sender applying a negotiated integrity algorithm and the secret key upon the entire message. Prior to integrityCheckValue computation an ICV with a previously agreed magic value (or key when using MDC) will be inserted to this field. The magic value will contain same algorithmOID and exactly as many bits in the icv BIT STRING as the computed value. After computation, the sender replaces the magic value with the computed integrity check value and transmits message. The receiver decodes message, replaces the received integrity value with the magic value, calculates the ICV and compares it with the received value.
NOTE: The sender or receiver can encode the ICV separately and replace it directly within the encoded PDU, when the magic ICV and computed ICV have exactly the same length. When replacing ICV value within an encoded PDU, re-encoding the whole PDU can be avoided.
NOTE: The above algorithm does not require directly changing the PER-encoded PDU. Like the current algorithm, ICV can be replaced with a new value above presentation layer then PDU will be re-encoded. It makes it easy, however: as the magic value is a very unique octet-aligned bit pattern (random data of 64 bits or more, probably), it should be easy to spot and replace it from the encoded PDU.
NOTE: It is not advisable to use magic value as the key to MAC algorithm.
Example code:
int icv_replace( u_char *msg, size_t len, u_char const *icv, u_char const *magic, size_t ilen) { u_char *m, *mim; size_t i, j, ilen_in_octets, ilen_in_full_octets; ilen_in_octets = (ilen + 7) >> 3; ilen_in_full_octets = ilen >> 3; /* find magic value from message */ for (m = msg, mim = NULL; m - msg < len - ilen_in_octets; m++) { /* NOTE: the magic value/icv may not be integral number of
octets */
for (i = 0; i < ilen_in_full_octets; i++) { if (m[i] != magic[i]) break; } if (i == ilen_in_full_octets) { if (mim) return -2; /* failure: two or more magic values found */ mim = m; } } if (mim == NULL) { return -1; /* failure: no magic value found */ /* replace magic value with icv */ for (i = 0; i < ilen_in_octets; i++) { mim[i] ^= magic[i] ^ icv[i]; } return 0; /* success */ }
Solution 4:
Fourth alternative is to treat encoded RasMessage as octet string. IVC can be calculated over that octet string and appended to the PDU on separate layer. E.g., RAS PDU could be defined as follows:
RasMessage ::= CHOICE {
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<-- -- all previous RasMessage CHOICEs are here --8<----8<----8<----8<----8<----8<----8<----8<----8<----8<-- authenticatedRasMessage SEQUENCE { plainRasMessage OCTET STRING, ivc IVC, ... } }
***************************************************** *** +1-503-264-8816(voice) Intel - Hillsboro, OR. *** *** mailto:jim.toga@intel.com mailto:james.toga@itu.ch *** *** PGP keyID 36 07 86 49 7D 74 DF 57 50 CB BA 32 08 9C 7C 41 *** *****************************************************