Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 44 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
44
Dung lượng
248,91 KB
Nội dung
Basic encoding rules are the most liberal set of encoding rules, allowing a variety of encodings for the same data. Effectively, any ASN.1 encoding that is either CER or DER can be BER decoded, but not the opposite. All of the data types ASN.1 allows are first described in terms of BER rules, and then CER or DER rules can be applied to them.The actual complete ASN.1 specification is far more complex than that required by the average cryptographic tasking. We will only be looking at the DER rules, as they are what most cryptographic standards require. It should also be noted that we will not be supporting the “constructed” encodings even though we will discuss them initially. ASN.1 was originally standardized in 1994 and again in 1997 and 2002.The current standard is ITU-T X.680, also filed as ISO/IEC 8824-1:2002, and is freely available on the Internet (ASN.1 Reference: http://asn1.elibel.tm.fr/standards/).This chapter discusses the implementation of ASN.1 encodings more than the theory behind the ASN.1 design.The reader is encouraged to read the ITU-T documents for a deeper treatment.The standards we are aiming to support by learning ASN.1 are the PKCS #1/#7 and ANSI X9.62/X9.63 public key cryptography standards. As it turns out, to support these standards your ASN.1 routines have to handle quite a bit of the ASN.1 types in the DER rule-set, resulting in encoding routines usable for a broad range of other tasks. While formally ASN.1 was defined for more than just cryptographic tasks, it has largely been ignored by cryptographic projects. Often, custom headers are encoded in proprietary formats that are not universally decodable (such as some of the ANSI X9.63 data), making their adoption slower as getting compliant and interoperable software is much harder than it needs be. As we explore at the end of this chapter, ASN.1 encoding can be quite easy to use in practical software and very advantageous for the both the developer and the end users. ASN.1 Syntax ASN.1 grammar follows a rather traditional Backus-Naur Form (BNF) style grammar, which is fairly loosely interpreted throughout the cryptographic industry.The elements of the grammar of importance to us are the name, type, modifiers, allowable values, and containers.As mentioned earlier, we are only lightly covering the semantics of the ASN.1 grammar.The goal of this section is to enable the reader to understand ASN.1 definitions sufficient to implement encoders or decoders to handle them.The most basic expression (also referred to as a production in ITU-T documentation) would be Name ::= type which literally states that some element named “Name” is an instance of a given ASN.1 type called “type.” For example, MyName ::= IA5String which would mean that we want an element or variable named “MyName” that is of the ASN.1 type IA5String (like an ASCII string). www.syngress.com ASN.1 Encoding • Chapter 2 23 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 23 ASN.1 Explicit Values Occasionally, we want to specify an ASN.1 type where subsets of the elements have pre- determined values.This is accomplished with the following grammar. Name ::= type (Explicit Value) The explicit value has to be an allowable value for the ASN.1 type chosen and is the only value allowed for the element. For example, using our previous example we can specify a default name. MyName ::= IA5String (Tom) This means that “MyName” is the IA5String encoding of the string “Tom”.To give the language more flexibility the grammar allows other interpretations of the explicit values. One common exception is the composition vertical bar | . Expanding on the previous example again, MyName ::= IA5String (Tom|Joe) This expression means the string can have either value “Tom” or “Joe.”The use of such grammar is to expand on deterministic decoders. For example, PublicKey ::= SEQUENCE { KeyType BOOLEAN(0), Modulus INTEGER, PubExponent INTEGER } PrivateKey ::= SEQUENCE { KeyType BOOLEAN(1), Modulus INTEGER, PubExponent INTEGER, PrivateExponent INTEGER } Do not dwell on the structure used just yet.The point of this example is to show two similar structures can be easily differentiated by a Boolean value that is explicitly set.This means that as a decoder parses the structure, it will first encounter the “KeyType” element and be able to decide how to parse the rest of the encoded data. ASN.1 Containers A container data type (such as a SEQUENCE or Set type) is one that contains other ele- ments of the same or various other types.The purpose is to group a complex set of data ele- ments in one logical element that can be encoded, decoded, or even included in an even larger container. www.syngress.com 24 Chapter 2 • ASN.1 Encoding 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 24 The ASN.1 specification defines four container types: SEQUENCE, SEQUENCE OF, SET, and SET OF. While their meanings are different, their grammar are the same, and are expressed as Name ::= Container { Name Type [Name Type …] } The text in square brackets is optional, as are the number of elements in the container. Certain containers as we shall see have rules as to the assortment of types allowed within the container.To simplify the expression and make it more legible, the elements are often speci- fied one per line and comma separation. Name ::= Container { Name Type, [Name Type, …] } This specifies the same element as the previous example. Nested containers are specified in the exact same manner. Name ::= Container { Name Container { Name Type, [Name Type, …] }, [Name Type, …] } A complete example of which could be UserRecord ::= SEQUENCE { Name SEQUENCE { First IA5String, Last IA5String }, DoB UTCTIME } This last example roughly translates into the following C structure in terms of data it represents. struct UserRecord { struct Name { char *First; char *Last; }; time_t DoB; } As we will see, practical decoding routines for containers are not quite as direct as the last example. However, they are quite approachable and in the end highly flexible. It is, of course, possible to mix container types within an expression. www.syngress.com ASN.1 Encoding • Chapter 2 25 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 25 ASN.1 Modifiers ASN.1 specifies various modifiers such as OPTIONAL, DEFAULT, and CHOICE that can alter the interpretation of an expression.They are typically applied where a type requires flexibility in the encoding but without getting overly verbose in the description. OPTIONAL OPTIONAL, as the name implies, modified an element such that its presence in the encoding is optional. A valid encoder can omit the element and the decoder cannot assume it will be present.This can present problems to decoders when two adjacent elements are of the same type, which means a look-ahead is required to properly parse the data.The basic OPTIONAL modifier looks like Name ::= Type OPTIONAL This can be problematic in containers, such as Float ::= SEQUENCE { Exponent INTEGER OPTIONAL, Mantissa INTEGER, Sign BOOLEAN } When the decoder reads the structure, the first INTEGER it sees could be the “Exponent” member and at worse would be the “Mantissa.”The decoder must look-ahead by one element to determine the proper decoding of the container. Generally, it is inadvisable to generate structures this way. Often, there are simpler ways of expressing a container with redundancy such that the decoding is determinable before decoding has gone fully underway.This leads to coder that is easier to audit and review. However, as we shall see, generic decoding of arbitrary ASN.1 encoded data is possible with a flexible linked list decoding scheme. DEFAULT The DEFAULT modifier allows containers to have a value that is implied if absent.The stan- dard specifies that “The encoding of a set value or sequence value shall not include an encoding for any component value that is equal to its default value” (Section 11.5 of ITU-T Recommendation X.690 International Standards 8825-1).This means quite simply that if the data to be encoded matches the default value, it will be omitted from the data stream emitted. For example, consider the following container. Command ::= SEQUENCE { Token IA5STRING(NOP) DEFAULT, Parameter INTEGER } www.syngress.com 26 Chapter 2 • ASN.1 Encoding 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 26 If the encoder sees that “Token” is representing the string “NOP,” the SEQUENCE will be encoded as if it was specified as Command ::= SEQUENCE { Parameter INTEGER } It is the responsibility of the decoder to perform the look-ahead and substitute the default value if the element has been determined to be missing. Clearly, the default value must be deterministic or the decoder would not know what to replace it with. CHOICE The CHOICE modifier allows an element to have more than one possible type in a given instance. Essentially, the decoder tries all the expected decoding algorithms until one of the types matches.The CHOICE modifier is useful when a complex container contains other containers. For instance, UserKey ::= SEQUENCE { Name IA5STRING, StartDate UTCTIME, Expire UTCTIME, KeyData CHOICE { ECCKey ECCKeyType, RSAKey RSAKeyType } } This last example is a simple public key certificate that presumably allows both ECC and RSA key types.The encoding of this data type is the same as if one of the choices were made; that is, one of the two following containers. ECCUserKey ::= SEQUENCE { Name IA5STRING, StartDate UTCTIME, Expire UTCTIME, ECCKey ECCKeyType, } RSAUserKey ::= SEQUENCE { Name IA5STRING, StartDate UTCTIME, Expire UTCTIME, RSAKey RSAKeyType } The decoder must accept the original sequence “UserKey” and be able to detect which choice was made during encoding, even if the choices involve complicated container struc- tures of their own. www.syngress.com ASN.1 Encoding • Chapter 2 27 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 27 ASN.1 Data Types Now that we have a basic grasp of ASN.1 syntax, we can examine the data types and their encodings that make ASN.1 so useful.ASN.1 specifies many data types for a wide range of applications—most of which have no bearing whatsoever on cryptography and are omitted from our discussions. Readers are encouraged to read the X.680 and X.690 series of specifi- cations if they want to master all that ASN.1 has to offer. Any ASN.1 encoding begins with two common bytes (or octets, groupings of eight bits) that are universally applied regardless of the type.The first byte is the type indicator, which also includes some modification bits we shall briefly touch upon.The second byte is the length header. Lengths are a bit complex at first to decode, but in practice are fairly easy to implement. The data types we shall be examining consist of the following types. ■ Boolean ■ OCTET String ■ BIT String ■ IA5String ■ PrintableString ■ INTEGER ■ OBJECT Identifier (OID) ■ UTCTIME ■ NULL ■ SEQUENCE, SEQUENCE OF ■ SET ■ SET OF This is enough of the types from the ASN.1 specifications to implement PKCS #1 and ANSI X9.62 standards, yet not too much to overwhelm the developer. ASN.1 Header Byte The header byte is always placed at the start of any ASN.1 encoding and is divides into three parts: the classification, the constructed bit, and the primitive type.The header byte is broken as shown in Figure 2.2. www.syngress.com 28 Chapter 2 • ASN.1 Encoding 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 28 Figure 2.2 The ASN.1 Header Byte In the ASN.1 world, they label the bits from one to eight, from least significant bit to most significant bit. Setting bit eight would be equivalent in C to OR’ing the value 0x80 to the byte; similarly, a primitive type of value 15 would be encoded as {0, 1, 1, 1, 1} from bit five to one, respectively. Classification Bits The classification bits form a two-bit value that does not modify the encoding but describes the context in which the data is to be interpreted.Table 2.1 lists the bit configurations for classifications. Table 2.1 The ASN.1 Classifications Bit 8 Bit 7 Class 0 0 Universal 0 1 Application 1 0 Context Specific 1 1 Private Of all the types, the universal classification is most common. Picking one class over another is mostly a cosmetic or side-band piece of information. A valid DER decoder should be able to parse ASN.1 types regardless of the class. It is up to the protocol using the decoder to determine what to do with the parsed data based on the classification. Constructed Bit The constructed bit indicates whether a given encoding is the construction of multiple sub- encodings of the same type.This is useful in general when an application wants to encode what is logically one element but does not have all the components at once. Constructed www.syngress.com ASN.1 Encoding • Chapter 2 29 8 7 6 5 4 3 2 1 Primitive Type Constructed Bit Classification 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 29 elements are also essential for the container types, as they are logically just a gathering of other elements. Constructed elements have their own header byte and length byte(s) followed by the individual encodings of the constituent components of the element.That is, on their own, the constituent component is an individually decodable ASN.1 data type. Strictly speaking, with the Distinguished Encoding Rules (DER) the only constructed data types allowed are the container class.This is simply because for any other data type and given contents only one encoding is allowable. We will assume the constructed bit is zero for all data types except the containers. Primitive Types The lower five bits of the ASN.1 header byte specify one of 32 possible ASN.1 primitives (Table 2.2). Table 2.2 The ASN.1 Primitives Code ASN.1 Type Use Of 1 Boolean Type Store Booleans 2 INTEGER Store large integers 3 BIT STRING Store an array of bits 4 OCTET STRING Store an array of bytes 5 NULL Place holder (e.g., in a CHOICE) 6 OBJECT IDENTIFIER Identify algorithms or protocols 16 SEQUENCE and Container of unsorted elements SEQUENCE OF 17 SET and SET OF Container of sorted elements 19 PrintableString ASCII Encoding (omitting several non-printable chars) 22 IA5STRING ASCII Encoding 23 UTCTIME Time in a universal format At first glance through the specifications, it may seem odd there is no CHOICE primi- tive. However, as mentioned earlier, CHOICE is a modifier and not a type; as such, the ele- ment chosen would be encoded instead. Each of these types is explained in depth later in this chapter; for now, we will just assume they exist. www.syngress.com 30 Chapter 2 • ASN.1 Encoding 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 30 ASN.1 Length Encodings ASN.1 specifies two methods of encoding lengths depending on the actual length of the ele- ment.They can be encoded in either definite or indefinite forms and further split into short or long encodings depending on the length and circumstances. In this case, we are only concerned with the definite encodings and must support both short and long encodings of all types. In the Basic Encoding Rules, the encoder is free to choose either the short or long encodings, provided it can fully represent the length of the element.The Distinguished Encoding Rules specify we must choose the shortest encoding that fully represents the length of the element.The encoded lengths do not include the ASN.1 header or length bytes, simply the payload. The first byte of the encoding determines whether short or long encoding was used (Figure 2.3). Figure 2.3 Length Encoding Byte The most significant bit determines whether the encoding is short or long, while the lower seven bits form an immediate length. Short Encodings In short encodings, the length of the payload must be less than 128 bytes.The immediate length field is used to represent the length of the payload, which is where the restriction on size comes from.This is the mandatory encoding method for all lengths less than 128 bytes. For example, to encode the length 65 (0x41) we simply use the byte 0x41. Since the value does not set the most significant bit, a decoder can determine it is a short encoding and know the length is 65 bytes. Long Encodings In long encodings we have an additional level of abstraction on the encoding of the length—it is meant for all payloads of length 128 bytes or more. In this mode, the immediate length field indicates the number of bytes in the length of the payload.To clarify, it specifies www.syngress.com ASN.1 Encoding • Chapter 2 31 8 7 6 5 4 3 2 1 Immediate Length Long Encoding Bit 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 31 how many bytes are required to encode the length of the payload.The length must be encoded in big endian format. Let us consider an example to show how this works.To encode the length 47,310 (0xB8CE), we first realize that it is greater than 127 so we must use the long encoding format.The actual length requires two octets to represent the value so we use two immediate length bytes. If you look at Figure 2.3, you will see the eighth bit is used to signify long encoding mode and we need two bytes to store the length.Therefore, the first byte is 0x80 | 0x02 or 0x82. Next, we store the value in big endian format.Therefore, the complete encoding is 0x82 B8 CE. As you can see, this is very efficient because with a single byte we can represent lengths of up to 127 bytes, which would allow the encoding of objects up to 2 1016 bits in length. This is a truly huge amount of storage and will not be exceeded sometime in the next century. That said, according to the DER rules the length of the payload length value must be minimal. As a result, the all 1s byte (that is, a long encoding with immediate length of 127) is not valid. Generally, for long encodings it is safe to assume that an immediate length larger than four bytes is not valid, as few cryptographic protocols involve exchanging more than four gigabytes of data in one packet. TIP Generally, it is a good idea to refuse ASN.1 long encoded lengths of more than four bytes, as that would imply the payload is more than four gigabytes in size. While this is a good initial check for safety, it is not sufficient. Readers are encouraged to check the fully decoded payload length against their output buffer size to avoid buffer overflow attacks. Traditionally, such checks should be performed before payload decoding has commenced. This avoids wasting time on erroneous encodings and is much sim- pler to code audit and review. ASN.1 Boolean Type The Boolean data type was provided to encode simple Boolean values without significant overhead in the encoder or decoder. The payload of a Boolean encoding is either all zero or all one bits in a single octet.The header byte begins with 0x01, the length byte is always short encoded as 0x01, and the con- tents are either 0x00 or 0xFF depending on the value of the Boolean (Table 2.3). www.syngress.com 32 Chapter 2 • ASN.1 Encoding 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 32 [...]... power of 25 6 from the encoded value (Table 2. 4) www.syngress.com 33 404_CRYPTO_ 02. qxd 34 10 /27 /06 3:40 PM Page 34 Chapter 2 • ASN.1 Encoding Table 2. 4 Example INTEGER Encodings Value Encoding 0 1 2 127 128 –1 – 128 – 327 68 123 4567890 0x 02 0x 02 0x 02 0x 02 0x 02 0x 02 0x 02 0x 02 0x 02 01 01 01 01 02 01 01 02 04 00 01 02 7F 00 80 FF 80 80 00 49 96 02 D2 Note in particular the difference between 128 and – 128 in... one-based, not zero-based For example, if the number is 1 02, the returned value is one, 10 02 returns 2, and so on 020 021 022 023 024 025 026 void store_unsigned(unsigned char *dst, long num) { int x, y; unsigned char t; x = y = 0; while (num) { www.syngress.com 404_CRYPTO_ 02. qxd 10 /27 /06 3:40 PM Page 49 ASN.1 Encoding • Chapter 2 027 028 029 030 031 0 32 033 034 035 036 037 dst[x++] = num & 25 5; num >>= 8; }... the payload length der_integer_encode.c: 001 #include “asn1.h" www.syngress.com 404_CRYPTO_ 02. qxd 10 /27 /06 3:40 PM Page 51 ASN.1 Encoding • Chapter 2 0 02 003 004 005 006 007 008 009 010 011 0 12 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 0 32 033 034 035 036 037 038 039 040 041 0 42 043 044 int der_integer_encode( long num, unsigned char *out, unsigned long *outlen) { /*... 0, 20 , –300}; they are individually encoded as shown in Table 2. 6 Table 2. 6 Array of INTEGERs Number Encoding 1 10007 0 20 –300 0x 02 0x 02 0x 02 0x 02 0x 02 01 02 00 01 02 01 27 17 14 FE D4 When we sort the encodings from Table 2. 6 in ascending order, we find the listing shown in Table 2. 7 as the order in which they are to be encoded Table 2. 7 Sorted SET OF INTEGERs Number Encoding 0 1 20 10007 –300 0x 02. .. www.syngress.com char *in, long inlen, char *out, long *outlen) inlen, 404_CRYPTO_ 02. qxd 10 /27 /06 3:40 PM Page 57 ASN.1 Encoding • Chapter 2 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 0 32 &type, &payload_length); if (ret < 0) { return ret; } if (type != ASN1_DER_OCTETSTRING) { return -2; } /* check output size */ if (payload_length > *outlen) { return -1; } /* copy out */... header */ 0 12 ret = der_get_header_length(&in, inlen, 013 &type, &payload_length); 014 if (ret < 0) { 015 return ret; 016 } 017 018 if (type != ASN1_DER_BITSTRING || payload_length < 1) { 019 return -2; 020 } 021 022 /* get # of bits */ 023 nbits = ((payload_length - 1) *outlen) { 028 return -1; 029 } 030 *outlen = nbits; 031 0 32 /* start... x = payload_length; 020 y = 0; 021 while (x) { 022 ++y; 023 x >>= 8; 024 } 025 026 /* store length of length */ 027 *ptr++ = 0x80 | y; 028 029 /* align length on 32- bit boundary, we assume y < 5 */ 030 x = y; 031 pl = payload_length; 0 32 while (x < 4) { 033 pl 24 ) & 0xFF; 040 } 041 } 0 42 043 /* get stored size */ 044... (y < 128 ) { 021 *payload_length = y; 022 } else { 023 y &= 0x7F; /* strip off bit 8 */ 024 025 /* simple safety check */ 026 if (y > 4 || (2 + y) > inlen) { 027 return -1; 028 } 029 030 /* read in the length */ 031 x = 0; www.syngress.com 404_CRYPTO_ 02. qxd 10 /27 /06 3:40 PM Page 45 ASN.1 Encoding • Chapter 2 0 32 033 034 035 036 037 038 039 040 041 0 42 043 044 045 046 047 048 049 while (y ) { x = (x . 0x 02 01 01 2 0x 02 01 02 127 0x 02 01 7F 128 0x 02 02 00 80 –1 0x 02 01 FF – 128 0x 02 01 80 – 327 68 0x 02 02 80 00 123 4567890 0x 02 04 49 96 02 D2 Note in particular the difference between 128 and – 128 . shown in Table 2. 6. Table 2. 6 Array of INTEGERs Number Encoding 1 0x 02 01 01 10007 0x 02 02 27 17 0 0x 02 00 20 0x 02 01 14 –300 0x 02 02 FE D4 When we sort the encodings from Table 2. 6 in ascending. listing shown in Table 2. 7 as the order in which they are to be encoded. Table 2. 7 Sorted SET OF INTEGERs Number Encoding 0 0x 02 00 1 0x 02 01 01 20 0x 02 01 14 10007 0x 02 02 27 17 –300 0x 02 02 FE D4 The