On Wed, 24 Jun 1998, Pekka Pessi wrote:
The current H.225.0 algorithm for calculating the ICV does not work well with the PER extension mechanism.
Agreed.
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.
PER is not inherently canonical. To get canonical behavior you have to either do as this set of standards have been doing and stay away from types REAL and SET OF, or you have to use Canonical PER Aligned or Canonical PER Unaligned.
However, there is a serious problem: the canonical representation changes if the ASN.1 SEQUENCE type is extended later.
Correct.
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 }
A lot of research has gone into how to most effectively create ICV's by the designers of the Secure Electronic Payment protocol (SET), e-check protocol and others. That's why in SET you see the likes of:
UnsignedCertificate ::= SEQUENCE { version [0] CertificateVersion, serialNumber CertificateSerialNumber, signature AlgorithmIdentifier {{SignatureAlgorithms}}, issuer Name, validity Validity, subject Name, subjectPublicKeyInfo SubjectPublicKeyInfo{{SupportedAlgorithms}}, issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, extensions [3] Extensions -- Required for SET usage }
-- Compute the encrypted hash of this value if issuing a certificate, -- or recompute the issuer's signature on this value if validating a -- certificate. -- EncodedCertificate ::= TYPE-IDENTIFIER.&Type (UnsignedCertificate)
Certificate::= SIGNED { EncodedCertificate } ( CONSTRAINED BY { -- Verify Or Sign Certificate -- } )
SIGNED { ToBeSigned } ::= SEQUENCE { toBeSigned ToBeSigned, algorithm AlgorithmIdentifier {{SignatureAlgorithms}}, signature BIT STRING }
The key thing to notice is that they DO NOT attempt to sign the unencoded certificate (i.e., UnsignedCertficate). The actual signing occurs on an open type which has been constrained to carry the value of the particular type that is to be signed (TYPE-IDENTIFIER.&Type (UnsignedCertificate)). In so doing, a) they clearly identify that the type should be encoded independently of the ICV, b) they avoid having to do a re-encode of the data after the CRV has been calculated, c) the type to which the ICV is to be applied can be extended with no problem, and d) they prepared themselves for the possible use of PER by utilizing an open type to carry the value to be signed - something that is *crucial* to signing PER-encoded data.
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.
That's the correct behavior only if you are originating a message. Encoders should not complain about criticalExtension being absent if they are not originating the message.
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.)
It is an error for encoders not to encode extension additions that are mandatory but missing if such extension additions do not occur within an extension addition group and if no other extension addition values follow the missing but mandatory extension. (I don't believe H.225 employs extension addition groups (i.e., the "[[" and "]]" notation.)) This is indicated in X.680:1997 clause 7.1 (X.680:1994 Amd.1 clause 6.1) which unconditionally mandates that it be possible for decoded components that are defined to both the sender and receiver be re-encodable by the receiver.
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.
Neat! A nice and simple solution for use with such compilers.
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
Note that it says the *type* being encoded, not the value. That's distinct from the value.
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.
It is true that they can be left out without changing the semantics, but this is not what PER mandates (It should have mandated what you suggest, but hindsight is 20-20.) Unless everyone encodes according to PER its canonical nature will be lost.
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.
Yes, this would work, but as you point out, it requires that PER be changed.
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.
I don't like this too much because of the possibility, though low, of the data containing the magic ICV value. Still I prefer it to solutions 1 and 2.
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 { -- all previous RasMessage CHOICEs are here authenticatedRasMessage SEQUENCE { plainRasMessage OCTET STRING, ivc IVC, ... } }
This is effectively what is done in SET and other security-conscious protocols, though they typically use open type instead of octet string.
Alternate Solution 1:
To do exactly as is done in SET, you would define RasMessage without an ICV, and define a container, AuthenticatedRasMessage, say, that carries the encoded RasMessage as an open type value (i.e., octet-aligned, and padded with 0-bits at the end to ensure that it is an integral multiple of 8 bits) followed by the ICV value. In other words:
AuthenticatedRasMessage ::= SEQUENCE { plainRasMessage TYPE-IDENTIFIER.&Type (RasMessage), ivc IVC }
Using this approach, the RasMessage (which would be defined without an ICV) would be encoded, then the ICV would be calculated using the encoded RasMessage, then AuthenticatedRasMessage would be encoded. This approach is efficient because RasMessage does not have to be encoded without the ICV value then re-encoded with it, nor does it require that the encoded value be tinkered with in any way.
This technique is good only if backward compatibility is not an issue (i.e., if you don't already have a deployed version of H.225), for the open type carries a length component than an ordinary encoded RasMessage does not have.
Alternate Solution 2:
If backward compatibility is an issue then Solution 4 above is a better alternative, though I would change it to:
RasMessage ::= CHOICE { -- all previous RasMessage CHOICEs are here authenticatedRasMessage AuthenticatedRasMessage }
Open type and octet string produce identical encodings, but I have a preference for the open type notation because it allows you to clearly identify what the value is - in this case an encoded RasMessage, and because it can simplify implementations that may not have a need to authenticate the RasMessage upon decoding (e.g., line monitors.)
I am not intimate with H.225, so I don't know for sure of Solution 4 or this minor variation is backward compatible. It is if the ICV was just introduced, else I don't think it is.
-------------------------------------------------------------------------- Bancroft Scott Toll Free :1-888-OSS-ASN1 Open Systems Solutions, Inc. International:1-609-987-9073 baos@oss.com Tech Support :1-732-249-5107 http://www.oss.com Fax :1-732-249-4636
I just wanted to point out a couple of things.
As Bancroft correctly points out, it is tough to do crypto on un-encoded ASN.1. SET and H.235 solve this by defining the open types (SIGNED, ENCRYPTED etc...) to accomplish this. H.323 systems shouldn't have any issues in this area other than the ICV mechanism described wholy within H.225.0
The ICV was dropped in kind of late in the schedule of security work for H.323. One of the intended goals was to make it 'light weight' in that clients would not have to have any dynamic call back after the ASN.1 was encoded (this appears to be a fools paradise... ;-( )
I would vote for adding a new 'open type' as is done from H.235 to encompass RAS messages - essentially what Pekka had proposed for #4 in his message. The main issue is that it were're saying that the current ICV is inoperable and irrelevant. If we can get agreement on this quickly we can incorpate it in the v2 Implementers Guide and bring it forward for v3.
Comments? jimt.
***************************************************** *** +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 *** *****************************************************
participants (2)
-
Bancroft Scott
-
Jim Toga